home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / rtty / tlmdc / serial.c < prev    next >
C/C++ Source or Header  |  1990-01-29  |  6KB  |  222 lines

  1. #include <stdio.h>
  2. #include <dos.h>
  3. #include <malloc.h>
  4. #define PIC_MASK 0x21
  5. #define    PIC_EOI  0x20
  6. #define ERR_MSK     0x9E
  7.  
  8. /* Definitions for interrupt handling */
  9.  
  10. /*  COM1 */
  11.  
  12. #define COM_DATA_1 0x3F8    /* Data received on this I/O address */
  13. #define COM_IER_1  0x3F9    /* This register enables interrupts */
  14. #define COM_MCR_1  0x3FC    /* Control Register (signals) */
  15. #define COM_STAT_1  0x3FD    /* Status Register */
  16. #define COM_INT_1   0xC        /* 0xC handles IRQ4 or COM1 by standard */
  17. #define INT_MASK_1  0x10    /* Mask for PIC (programmable interrupt
  18.                    controller) 8259A */
  19.  
  20. /* COM2 */
  21.  
  22. #define COM_DATA_2 0x2F8    /* Data received on this I/O address */
  23. #define COM_IER_2  0x2F9    /* This register enables interrupts */
  24. #define COM_MCR_2  0x2FC    /* Control Register (signals) */
  25. #define COM_STAT_2  0x2FD    /* Status Register */
  26. #define COM_INT_2   0xB        /* 0xB handles IRQ3 or COM2 by standard */
  27. #define INT_MASK_2  0x8        /* Mask for PIC (programmable interrupt
  28.                    controller) 8259A */
  29. static unsigned char far *c1_buf;
  30. static unsigned char far *c2_buf;
  31. static unsigned asc_in_1,asc_in_2,asc_old_1,asc_old_2;
  32. static void interrupt cdecl far int_com1();
  33. static void interrupt cdecl far int_com2();
  34. static void far *old_c1,far *old_c2;
  35.  
  36.  
  37. /* Instat is trivial.  If the ring buffer point is not the same as the
  38.    is not the same as the next read point, then you have a character
  39.    waiting */
  40.  
  41. int instat(com_port)
  42. int com_port;
  43. {
  44.     switch(com_port) {
  45.         case 0:{
  46.             if (asc_old_1 == asc_in_1) return 0;
  47.             else return 1;
  48.             break;
  49.         }
  50.         case 1:{
  51.             if (asc_old_2 == asc_in_2) return 0;
  52.             else return 1;
  53.             break;
  54.         }
  55.     }
  56. }
  57.  
  58. /* If the ring buffer write pointer is not the same as the ring buffer
  59.    read pointer, then a character is in the buffer */
  60.  
  61. int rcvbyte(com_port)
  62. int com_port;
  63. {
  64.     int ch;
  65.     switch(com_port) {
  66.         case 0: {
  67.             if (asc_old_1 == asc_in_1) return -1;
  68.             else {
  69.                 ch = c1_buf[asc_old_1];
  70.                 asc_old_1 += 1;
  71.                 if (asc_old_1 == 4096) asc_old_1 = 0;
  72.                 return ch;
  73.             }
  74.         }
  75.         case 1: {
  76.             if (asc_old_2 == asc_in_2) return -1;
  77.              else {
  78.                 ch = c2_buf[asc_old_2];
  79.                 asc_old_2 += 1;
  80.                 if (asc_old_2 == 4096) asc_old_2 = 0;
  81.                 return ch;
  82.             }
  83.         }
  84.     }
  85. }
  86.  
  87. /*  COM1 Interrupt handler.  HARDWARE DEPENDENT */
  88.  
  89. static void interrupt cdecl far int_com1(es,ds,di,si,bp,sp,bx,dx,cx,ax)
  90. unsigned es,ds,di, si, bp, sp, bx, dx, cx, ax;
  91. {
  92.     char ch;
  93.     _disable();        /* Disable interrupts while we move data
  94.                    and pointers */
  95.     if((ch = (inp(COM_STAT_1)&ERR_MSK)) == 0) {  /*If no error message */
  96.         ch = inp(COM_DATA_1);    /* Get the character */
  97.         c1_buf[asc_in_1] = ch;    /* Store data in circular buffer */
  98.         asc_in_1 += 1;
  99.         if (asc_in_1 == 4096) asc_in_1 = 0; /* Have we wrapped? */
  100.     } else ch = inp(COM_DATA_1);    /* Get the character */
  101.     _enable();        /* Enable interrupts */
  102.     outp(PIC_EOI,0x20);    /* Tell 8259A we have handled the interrupt */
  103. }
  104.  
  105. /*  COM2 Interrupt handler.  HARDWARE DEPENDENT */
  106.  
  107. static void interrupt cdecl far int_com2(es,ds,di,si,bp,sp,bx,dx,cx,ax)
  108. unsigned es,ds,di, si, bp, sp, bx, dx, cx, ax;
  109. {
  110.     char ch;
  111.     _disable();        /* Disable interrupts while we move data
  112.                    and pointers */
  113.     if((ch = (inp(COM_STAT_2)&ERR_MSK)) == 0) {/* If no error message*/
  114.         ch = inp(COM_DATA_2);    /* Get the character */
  115.         c2_buf[asc_in_2] = ch;    /* Store data in circular buffer */
  116.         asc_in_2 += 1;
  117.         if (asc_in_2 == 4096) asc_in_2 = 0; /* Have we wrapped? */
  118.     } else ch=inp(COM_DATA_2);
  119.     _enable();        /* Enable interrupts */
  120.     outp(PIC_EOI,0x20);    /* Tell 8259A we have handled the interrupt */
  121. }
  122.  
  123. /* 4096 character buffers are utilized, that is usually more than a screenful
  124.     of data ;-) */
  125. void asc_enab(com_port)
  126. int com_port;
  127. {
  128.     char ch;
  129.     switch(com_port) {
  130.         case 0:{
  131.             asc_in_1 = asc_old_1 = 0;
  132.             if((c1_buf = (unsigned char far *)_fmalloc(4096)) == NULL) {
  133.                 perror("Out of memory");
  134.                 exit(0);
  135.             }
  136.             old_c1 = _dos_getvect(COM_INT_1);  /* Be a friendly
  137.                                   ISR and save the
  138.                                   old vector for
  139.                                   restoration */
  140.             _dos_setvect(COM_INT_1,int_com1); /* Tell DOS whose got
  141.                                  the vector now */
  142.             outp(COM_MCR_1,0xB);    /* Raise DTR and OUT2 */
  143.             outp(COM_IER_1,1);    /* Interrupt enable register*/
  144.             ch = inp(PIC_MASK);    /* Read the current 8259A
  145.                            interrupt mask */
  146.             ch &=  (0xFF^INT_MASK_1);/* Reset mask for COM1 */
  147.             outp(PIC_MASK,ch);    /* Send it to the 8259A */
  148.             break;
  149.         }
  150.         case 1:{
  151.             asc_in_2 = asc_old_2 = 0;
  152.             if((c2_buf = (unsigned char far *)_fmalloc(4096)) == NULL) {
  153.                 perror("Out of memory");
  154.                 exit(0);
  155.             }
  156.             old_c2 = _dos_getvect(COM_INT_2);  /* Be a friendly
  157.                                   ISR and save the
  158.                                   old vector for
  159.                                   restoration */
  160.             _dos_setvect(COM_INT_2,int_com2);  /* Tell DOS whose
  161.                                   got the vector
  162.                                   now */
  163.             outp(COM_MCR_2,0xB);    /* Raise DTR and OUT2 */
  164.             outp(COM_IER_2,1);    /* Interrupt enable register*/
  165.             ch = inp(PIC_MASK);    /* Read the current 8259A
  166.                            interrupt mask */
  167.             ch &=  (0xFF^INT_MASK_2);/* Reset mask for COM2 */
  168.             outp(PIC_MASK,ch);    /* Send it to the 8259A */
  169.             break;
  170.         }
  171.     }
  172. }
  173. void asc_disab(com_port)
  174. int com_port;
  175. {
  176.     char ch;
  177.     switch(com_port){
  178.         case 0: {
  179.             _ffree(c1_buf);        /* Free the ring buffer */
  180.             ch = inp(PIC_MASK);    /* Get 8259A (PIC) Mask */
  181.             ch |= INT_MASK_1;    /* Set Interrupt Mask COM1 */
  182.             outp(PIC_MASK,ch);    /* Write int. mask to 8259A*/
  183.             _dos_setvect(COM_INT_1,old_c1);/* Return the vector
  184.                               to its old position*/
  185.             break;
  186.         }
  187.         case 1: {
  188.             _ffree(c2_buf);        /*Free the ring buffer */
  189.             ch = inp(PIC_MASK);    /* Get 8259A (PIC) Mask */
  190.             ch |= INT_MASK_2;    /* Set Interrupt Mask COM1 */
  191.             outp(PIC_MASK,ch);    /* Write int. mask to 8259A*/
  192.             _dos_setvect(COM_INT_2,old_c2);/* Restore the old
  193.                               vector */
  194.             break;
  195.         }
  196.     }
  197. }
  198.  
  199. putcom(p,ch)
  200. int p;
  201. unsigned char ch;
  202. {
  203.     unsigned char status;
  204.     switch(p) {
  205.         case 0:{
  206.             do {
  207.                 status = inp(COM_STAT_1);
  208.             } while (!(status&0x20));
  209.             outp(COM_DATA_1,ch);
  210.             break;
  211.         }
  212.         case 1:{
  213.             do {
  214.                 status = inp(COM_STAT_2);
  215.             } while (!(status&0x20));
  216.             outp(COM_DATA_2,ch);
  217.             break;
  218.         }
  219.     }
  220. }
  221.  
  222.