home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / datetime / navytime / comm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-08-15  |  7.5 KB  |  250 lines

  1. /* comm -- communications port i/o                                          */
  2. /* copyright 1987  Michael M Rubenstein                                     */
  3.  
  4. #pragma inline
  5. #include <stdio.h>
  6. #include <dos.h>
  7. #include "atfinish.h"
  8. #include "comm.h"
  9.  
  10. #ifndef TRUE
  11. #define TRUE            1
  12. #endif
  13. #ifndef FALSE
  14. #define FALSE           0
  15. #endif
  16.  
  17. #define NUMUNIT         2               /* number of comm units */
  18.  
  19. #define COMM_BUFSIZE    256             /* must be power of 2 <= 2^7 */
  20.  
  21. #define DATA0           0x3f8           /* COM1 port address */
  22. #define DATA1           0x2f8           /* COM2 port address */
  23. #define INTMASK0        0xef            /* mask for COM1 interrupt */
  24. #define INTMASK1        0xf7            /* mask for COM2 interrupt */
  25. #define INTERRUPT_VEC0  0x0c            /* interrupt vector for COM1 */
  26. #define INTERRUPT_VEC1  0x0b            /* interrupt vector for COM2 */
  27.  
  28. #define DATA            comm_base[unit]
  29. #define ENABLE_INT      (comm_base[unit] + 1)
  30. #define DIVISOR0        (comm_base[unit] + 0)
  31. #define DIVISOR1        (comm_base[unit] + 1)
  32. #define INTERRUPT_ID    (comm_base[unit] + 2)
  33. #define LINE_CTL        (comm_base[unit] + 3)
  34. #define MODEM_CTL       (comm_base[unit] + 4)
  35. #define LINE_STATUS     (comm_base[unit] + 5)
  36. #define MODEM_STATUS    (comm_base[unit] + 6)
  37.  
  38. #define INTERRUPT_CTL   0x20
  39. #define INTERRUPT_MASK  0x21
  40.  
  41. static unsigned         comm_base[NUMUNIT] = { DATA0, DATA1 };
  42. static unsigned char    interrupt_mask[NUMUNIT] = { INTMASK0, INTMASK1 };
  43. static unsigned         interrupt_vector[NUMUNIT] = { INTERRUPT_VEC0,
  44.                                                       INTERRUPT_VEC1
  45.                                                     };
  46.  
  47. static void interrupt   (*holdvec[NUMUNIT])();
  48. static unsigned char    hold_interrupt_enable[NUMUNIT];
  49. static unsigned char    hold_interrupt_mask[NUMUNIT];
  50.  
  51. static unsigned char    buffer0[COMM_BUFSIZE];
  52. static unsigned char    buffer1[COMM_BUFSIZE];
  53. static unsigned char    *buffer[NUMUNIT] = { buffer0, buffer1 };
  54.  
  55. static int              first[NUMUNIT] = { 0, 0 },
  56.                         next[NUMUNIT] = { 0, 0 };
  57.  
  58. static int              any_opened = FALSE;
  59. static int              opened[NUMUNIT] = { FALSE, FALSE };
  60.  
  61. void                    comm_int0(void);
  62. void                    comm_int1(void);
  63.  
  64. /* open comm port.                                                          */
  65. int comm_open(unsigned unit, unsigned baud, int parity, int stop,
  66.               int wordsize)
  67. {
  68.   unsigned              divisor;
  69.   struct {              char            p_char;
  70.                         unsigned int    p_bits;
  71.          }              parity_bits[] = { { 'n', 0x00 },
  72.                                           { 'o', 0x04 },
  73.                                           { 'e', 0x0c },
  74.                                           { 0, 0 }
  75.                                         },
  76.                         *pb;
  77.   unsigned              lctl;
  78.  
  79.  
  80.   if (unit >= NUMUNIT)
  81.     return FALSE;
  82.  
  83.   lctl = 0;
  84.   for (pb = parity_bits; pb->p_char != 0; ++ pb)
  85.     if (pb->p_char == parity)
  86.     {
  87.       lctl = pb->p_bits;
  88.       break;
  89.     }
  90.   lctl |= (wordsize - 5);
  91.   lctl |= (stop - 1) << 2;
  92.  
  93.  
  94.   holdvec[unit] = getvect(interrupt_vector[unit]);
  95.   setvect(interrupt_vector[unit],
  96.           (unit == 0) ? (void interrupt (*)()) comm_int0
  97.                       : (void interrupt (*)()) comm_int1);
  98.  
  99.   hold_interrupt_enable[unit] = inportb(ENABLE_INT);
  100.  
  101.   outportb(ENABLE_INT, 0x01);                     /* set data ready int */
  102.   hold_interrupt_mask[unit] = inportb(INTERRUPT_MASK);
  103.   outportb(INTERRUPT_MASK, hold_interrupt_mask[unit] & interrupt_mask[unit]);
  104.  
  105.   outportb(LINE_CTL, 0x80);                       /* access divisor latch */
  106.  
  107.   divisor = (int) (0x1c200l / (long) baud);
  108.   outportb(DIVISOR0, divisor);                    /* set baud divisor */
  109.   outportb(DIVISOR1, divisor >> 8);
  110.   outportb(LINE_CTL, lctl);                       /* 81n */
  111.   outportb(MODEM_CTL, 0x0b);                      /* DTR, RTS, interrupts */
  112.   outportb(INTERRUPT_CTL, 0x20);                  /* EOI to 8259 */
  113.  
  114.   if (!any_opened)
  115.     atfinish(comm_close_all);
  116.  
  117.   any_opened = opened[unit] = TRUE;
  118.  
  119.   comm_clr(unit);
  120.   return TRUE;
  121. }
  122.  
  123. /* close all comm ports                                                     */
  124. void comm_close_all(void)
  125. {
  126.   int                   i;
  127.  
  128.   for (i = 0; i < NUMUNIT; ++i)
  129.     comm_close(i);
  130. }
  131.  
  132. /* close a comm port -- drop modem control signals and stop interrupts      */
  133. void comm_close(unsigned unit)
  134. {
  135.   if (unit < NUMUNIT && opened[unit])
  136.   {
  137.     outportb(MODEM_CTL, 0x00);                  /* no DTR, RTS, interrupts */
  138.     outportb(ENABLE_INT, hold_interrupt_enable[unit]);
  139.     outportb(INTERRUPT_MASK, hold_interrupt_mask[unit]);
  140.     setvect(interrupt_vector[unit], holdvec[unit]);
  141.     opened[unit] = FALSE;
  142.   }
  143. }
  144.  
  145. /* interrupt handler for COM1                                               */
  146. static void comm_int0(void)
  147. {
  148.  asm    push    ds
  149.  asm    push    dx
  150.  asm    push    bx
  151.  asm    push    ax
  152.  
  153.  asm    mov     dx,dgroup
  154.  asm    mov     ds,dx
  155.  asm    mov     dx,3f8h
  156.  asm    in      al,dx                       /* get character */
  157.  asm    sub     bx,bx
  158.  asm    mov     bx,next+0*2
  159.  asm    mov     byte ptr buffer0[bx],al     /* mov char. into buffer */
  160.  asm    inc     bx                          /* advance buffer pointer */
  161.  asm    and     bx,COMM_BUFSIZE-1
  162.  asm    cmp     bx,first+0*2
  163.  asm    je      finish                      /* don't update ptr if no room */
  164.  asm    mov     next+0*2,bx
  165.  
  166. finish:
  167.  asm    mov     al,20h                      /* send EOI to 8259 */
  168.  asm    out     20h,al
  169.  
  170.  asm    pop     ax
  171.  asm    pop     bx
  172.  asm    pop     dx
  173.  asm    pop     ds
  174.  asm    iret
  175. }
  176.  
  177. /* interrupt handler for COM2                                               */
  178. static void comm_int1(void)
  179. {
  180.  asm    push    ds
  181.  asm    push    dx
  182.  asm    push    bx
  183.  asm    push    ax
  184.  
  185.  asm    mov     dx,dgroup
  186.  asm    mov     ds,dx
  187.  asm    mov     dx,2f8h
  188.  asm    in      al,dx                       /* get character */
  189.  asm    sub     bx,bx
  190.  asm    mov     bx,next+1*2
  191.  asm    mov     byte ptr buffer1[bx],al     /* mov char. into buffer */
  192.  asm    inc     bx                          /* advance buffer pointer */
  193.  asm    and     bx,COMM_BUFSIZE-1
  194.  asm    cmp     bx,first+1*2
  195.  asm    je      finish                      /* don't update ptr if no room */
  196.  asm    mov     next+1*2,bx
  197. finish:
  198.  asm    mov     al,20h                      /* send EOI to 8259 */
  199.  asm    out     20h,al
  200.  
  201.  asm    pop     ax
  202.  asm    pop     bx
  203.  asm    pop     dx
  204.  asm    pop     ds
  205.  asm    iret
  206. }
  207.  
  208. /* get character from comm                                                  */
  209. int comm_getc(unsigned unit)
  210. {
  211.   int                   c;
  212.  
  213.   if (unit >= NUMUNIT)
  214.     return -1;
  215.  
  216.   if (first[unit] == next[unit])
  217.     return -1;
  218.  
  219.   c = buffer[unit][first[unit]];
  220.   first[unit] = (first[unit] == COMM_BUFSIZE - 1) ? 0 : first[unit] + 1;
  221.   return c;
  222. }
  223.  
  224. /* clear input buffer                                                       */
  225. void comm_clr(unsigned unit)
  226. {
  227.   if (unit < NUMUNIT)
  228.   {
  229.     disable();
  230.     first[unit] = next[unit];
  231.     inportb(DATA);                /* also clear anything in the chip */
  232.     inportb(DATA);
  233.     enable();
  234.   }
  235. }
  236.  
  237. /* put character to comm                                                    */
  238. int comm_putc(unsigned unit, int c)
  239. {
  240.   if (unit > NUMUNIT)
  241.     return FALSE;
  242.  
  243.   if (inportb(LINE_STATUS) & 0x20)
  244.   {
  245.     outportb(DATA, c);
  246.     return TRUE;
  247.   }
  248.   return FALSE;
  249. }
  250.