home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / communic / tcasync / tasync.c next >
Encoding:
C/C++ Source or Header  |  1987-11-13  |  8.5 KB  |  269 lines

  1. #define TASYNC
  2. #include <dos.h>
  3. #include"tasync.h"
  4. /*
  5.    a set  of Turbo-C functions to support
  6.    interrupt driven serial i/o.
  7.    input and output are buffered line and modem status drivers are
  8.    also interrupt driven. tested upto 9600 baud all code is written
  9.    in "C" thanks to Borland Low level hooks that are available in
  10.    Turbo-C.
  11.    thanks to Glenn F. Marshall for his Pascal code and to
  12.    Curt Klinsing for his assembler routines
  13. */
  14.  
  15. #define false   0
  16. #define true    !false
  17. #define COM0 1          /* either com0 or com1 */
  18.  
  19. #ifdef COM0
  20. #define comport  0      /*  Com port # */
  21. #define base     0x03f8 /* base for serial board  */
  22. #define comint   0xc    /*  Int Vector used by port */
  23. #define enblirq  0xef   /* enable communications  */
  24. #define maskirq  0x10   /* bit to disable comm interrupt */
  25. int pused = 0;
  26. #endif
  27.  
  28. #ifdef COM1
  29. #define comport  1      /*  Com Port */
  30. #define base     0x02f8 /* base for serial board */
  31. #define comint   0xb    /*  Int Vector used by port */
  32. #define enblirq  0xf7   /* enable communications */
  33. #define maskirq  0x8    /* bit to disable comm interrupt */
  34. int pused = 1;
  35. #endif
  36.  
  37. /* 8250 registers */
  38. #define mdmbd0   base    /* lsb baud rate register */
  39. #define dataport base    /* transmit/receive data port */
  40. #define mdmbd1   base+1  /* msb baud rate register */
  41. #define ier      base+1  /*  interrup enable register */
  42. #define irr      base+2  /* reason for interrupt */
  43. #define lcr      base+3  /*  line control register */
  44. #define mcr      base+4  /* modem control register */
  45. #define mdmsta   base+5  /* line status register */
  46. #define mdmmsr   base+6  /* modem status register */
  47.  
  48. /* 8250 values */
  49. #define mdmcd   0x80     /* mask for carrier dectect */
  50. #define mdmtbe  0x20     /* 8250 tbe flag */
  51. #define dlab    0x80     /* enable divisor latch */
  52.  
  53. /* 8250 interrupt enable values */
  54. #define enbldrdy 1       /*  enable 'data-ready' interrupt bit */
  55. #define enbltrdy 2       /*  enable 'xmit-empty' interrupt bit */
  56. #define enbllrdy 4       /*  enable 'line-change' interrupt bit */
  57. #define enblmrdy 8       /*  enable 'modem-change' interrupt bit */
  58.  
  59. /* 8250 interrupt causes */
  60. #define intms    0       /* int caused by modem status */
  61. #define inttx    2       /* int caused by td */
  62. #define intrd    4       /* int caused by dr */
  63. #define intls    6       /* int caused by line status */
  64.  
  65. /* 8259 ports and values */
  66. #define intctlr 0x21     /* ocw 1 for 8259 controller */
  67. #define rs8259  0x20     /* ocw 3 for 8259 */
  68. #define rstint  0x20     /* specific eoi for comm interrupt */
  69.  
  70. /*        miscellaneous equates */
  71. #define xoff    0x13
  72. #define xon     0x11
  73. #define bufsiz  4096     /* max number of chars */
  74.  
  75. char in_c_buf[bufsiz];   /* allow 512 maximum buffered characters */
  76. char ou_c_buf[bufsiz];
  77. volatile char xon_sent,linstat,modstat;
  78.  
  79. #define ou_c_top &ou_c_buf[bufsiz-1]
  80. #define in_c_top &in_c_buf[bufsiz-1]
  81.  
  82. volatile char *in_c_in;   /* in_c_buf pointer to last char. placed in buffer */
  83. volatile char *in_c_cur;  /* in_c_buf pointer to next char. to be retrieved */
  84. volatile int  in_c_ct;    /* count of characters used in buffer */
  85. volatile char *ou_c_in;   /* ou_c_buf pointer to last char. placed in buffer */
  86. volatile char *ou_c_cur;  /* ou_c_buf pointer to next char. to be transmitted */
  87. volatile int  ou_c_ct;    /* count of characters used in buffer */
  88.  
  89. int carrier(void)
  90. {
  91.    return (inport(mdmmsr) & 0x80);
  92. }
  93.  
  94. void setport(int prot,int baud)
  95. {
  96.     disable();
  97.     outport(lcr,dlab);           /* enable buad sender */
  98.     outport(mdmbd0,baud & 0xFF); /* send lsb */
  99.     outport(mdmbd1,baud / 256);  /* send msb */
  100.     outport(lcr,prot);           /* set protocol */
  101.     enable();
  102. }
  103.  
  104. /*  int getport();
  105. 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
  106.    T  T  B  F  P   O  D  D  R  D  C  D  T  D  D
  107.    S  H  I  E  E   R  R  C  I  S  T  D  E  D  C
  108.    R  R                  D     R  S  C  R  S  T
  109.    E  E                              D  I  R  S
  110. Data Ready = DR, Overrun Error = OR, Parity Error = PE, Framing Error = FE,
  111. Break Interrupt = BI, Transmitter Holding Register = THRE,
  112. Transmitter Empty = TSRE, Delta Clear to Send = DCTS, Clear to Send = CTS,
  113. Delta Data Set Ready = DDSR, Data Set Ready = DSR, Ring Indicator = RI,
  114. Trailing Edge Ring Indicator = TERI, Delta Carrier Detect = DCD,
  115. Carrier Detect = CD */
  116. int getport(void)
  117. {
  118.     return(256 * linstat + modstat);
  119. }
  120.  
  121. #define inp_cnt() in_c_ct
  122.  
  123. /* flush_port()    flush the buffers */
  124. void flush_port(void)
  125. {
  126.     disable();
  127.     in_c_in=in_c_cur=&in_c_buf[0];
  128.     ou_c_in=ou_c_cur=&ou_c_buf[0];
  129.     ou_c_ct=xon_sent=in_c_ct=0;
  130.     enable();
  131. }
  132.  
  133. /* uninit()          removes the interrupt structure */
  134.  
  135. void interrupt (*oldhold)();
  136.  
  137. void uninit(void)     /* remove initialization, */
  138. {
  139.     disable();
  140.     setvect(comint,oldhold); /* restore old vector */
  141.     outportb(intctlr,inport(intctlr) | maskirq); /*  disable irq on 8259 */
  142.     outport(ier,0); /* clear all interrupt enables */
  143.     outport(lcr,0); /* clear the protocol */
  144.     outport(mcr,0); /* disable out2 on 8250 */
  145.     enable();
  146. }
  147.  
  148. volatile char rd,tx;  /* last recieved and transmitted character */
  149.  
  150. void scrstat(void) /* will cause loss of characters if called too often */
  151. {
  152.     char s[10];
  153.     int i,n,j;
  154.     n=(modstat & 0xF0) | ((linstat>>1) & 0x0F) ;
  155.     for(i=1,j=2;i<256;i*=2,j++)
  156.         if(n & i)
  157.             s[j]=7;
  158.         else
  159.             s[j]=250;
  160.     s[0]=rd;
  161.     s[1]=tx;
  162.     for(i=0,j=0;i<10;i++,j+=2)
  163.         pokeb(0xb800,140+j,s[i]);
  164. }
  165.  
  166. void comout(char c) /* que character in buffer */
  167. {
  168.     if((inportb(mdmsta) & mdmtbe) && !ou_c_ct)
  169.         outportb(dataport,tx=c); /* if status is clear then just send */
  170.     else {                    /* load it in the buffer */
  171.         disable();
  172.         if(ou_c_ct<bufsiz) {  /* if buffer is full ignore character */
  173.             *ou_c_in=c;
  174.             ou_c_ct++;
  175.             ou_c_in = ou_c_in==ou_c_top ? ou_c_buf : (char *)ou_c_in+1;
  176.         }
  177.         enable();
  178.  
  179.     }
  180. }
  181.  
  182.  
  183. /* char inp_char()        return a character from the input */
  184. /*                        buffer. assumes you have called */
  185. /* inp_cnt() to see if theres any characters to get. */
  186.  
  187. char inp_char(void)                /* get one char from buffer, */
  188. {
  189.     char cin;
  190.     disable();
  191.     cin=*in_c_cur;
  192.     if(inp_cnt()) {
  193.         in_c_ct--;
  194.         in_c_cur = in_c_cur==in_c_top ? in_c_buf : (char *)in_c_cur+1;
  195.     }
  196.     enable();
  197.     if(xon_sent && (in_c_ct<128)) {
  198.         comout(xon);
  199.         xon_sent=false;
  200.     }
  201.     return cin;
  202. }
  203.  
  204. /* receive interrupt handler (changed to place characters in in_c_buf */
  205. void interrupt inthdlr(void)
  206. {
  207.     disable();
  208.     switch(inportb(irr)) {
  209.     case intrd: /* recieve data */
  210.         if(in_c_ct<bufsiz) { /* if buffer is full ignore character */
  211.             *in_c_in=inportb(dataport);
  212.             rd=*in_c_in;
  213.             in_c_ct++;
  214.             in_c_in = in_c_in==in_c_top ? in_c_buf : (char *)in_c_in+1;
  215.         }
  216.         break;
  217.     case intms:
  218.         modstat=inportb(mdmmsr);
  219.         break; /* modem status */
  220.     case intls:
  221.         linstat=inportb(mdmsta);
  222.         break; /* line status */
  223.     case inttx: /* transmitter empty */
  224.         if(ou_c_ct>0) { /* if there is a character */
  225.             outportb(dataport,*ou_c_cur);
  226.             tx=*ou_c_cur;
  227.             ou_c_ct--;         /* decrement in_c_buf count */
  228.             ou_c_cur = ou_c_cur==ou_c_top ? ou_c_buf : (char *)ou_c_cur+1;
  229.         }
  230.     } /* switch */
  231.     outportb(rs8259,rstint);
  232.     /*   scrstat(); */
  233.     if(in_c_ct>(bufsiz*3/4)) {
  234. /*        pokeb(0xB800,0,7); */ /* if xon xoff screen report is needed */
  235.         comout(xoff);
  236.         xon_sent=true;
  237.     }
  238.     enable();
  239. }
  240.  
  241. /*  --------- init ----------------------------------- */
  242. /*  program initialization: */
  243. /*    --  set up vector for rs232 interrupt */
  244. /*    --  enbl irq */
  245. /*    --  enbl rs232 interrupt on dr,tx,ms,ls */
  246.  
  247. /*  --------------------------------------------------- */
  248.  
  249. void init_com(void)       /* initialize the comm port, */
  250. {
  251.     disable();
  252.     flush_port();
  253.     oldhold=getvect(comint);
  254.     setvect(comint,inthdlr);
  255.     outportb(intctlr,inportb(intctlr) & enblirq);
  256.     outport(lcr,inportb(lcr) & 0x7f); /* reset dlab for ier access */
  257.     outportb(ier,enbldrdy+enbllrdy+enblmrdy+enbltrdy);
  258.     outportb(mcr,0xf); /*  modem control register enable out2 out1 dtr rts */
  259.     linstat=inportb(mdmsta);
  260.     modstat=inportb(mdmmsr);
  261.     enable();
  262. }
  263.  
  264. void comok(void)
  265. {
  266.     outportb(mcr,0xf); /* enable modem */
  267. }
  268.  
  269.