8250.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. /*
  8. * INS8250 uart
  9. */
  10. enum
  11. {
  12. /*
  13. * register numbers
  14. */
  15. Data= 0, /* xmit/rcv buffer */
  16. Iena= 1, /* interrupt enable */
  17. Ircv= (1<<0), /* for char rcv'd */
  18. Ixmt= (1<<1), /* for xmit buffer empty */
  19. Irstat=(1<<2), /* for change in rcv'er status */
  20. Imstat=(1<<3), /* for change in modem status */
  21. Istat= 2, /* interrupt flag (read) */
  22. Tctl= 2, /* test control (write) */
  23. Format= 3, /* byte format */
  24. Bits8= (3<<0), /* 8 bits/byte */
  25. Stop2= (1<<2), /* 2 stop bits */
  26. Pena= (1<<3), /* generate parity */
  27. Peven= (1<<4), /* even parity */
  28. Pforce=(1<<5), /* force parity */
  29. Break= (1<<6), /* generate a break */
  30. Dra= (1<<7), /* address the divisor */
  31. Mctl= 4, /* modem control */
  32. Dtr= (1<<0), /* data terminal ready */
  33. Rts= (1<<1), /* request to send */
  34. Ri= (1<<2), /* ring */
  35. Inton= (1<<3), /* turn on interrupts */
  36. Loop= (1<<4), /* loop back */
  37. Lstat= 5, /* line status */
  38. Inready=(1<<0), /* receive buffer full */
  39. Oerror=(1<<1), /* receiver overrun */
  40. Perror=(1<<2), /* receiver parity error */
  41. Ferror=(1<<3), /* rcv framing error */
  42. Outready=(1<<5), /* output buffer empty */
  43. Mstat= 6, /* modem status */
  44. Ctsc= (1<<0), /* clear to send changed */
  45. Dsrc= (1<<1), /* data set ready changed */
  46. Rire= (1<<2), /* rising edge of ring indicator */
  47. Dcdc= (1<<3), /* data carrier detect changed */
  48. Cts= (1<<4), /* complement of clear to send line */
  49. Dsr= (1<<5), /* complement of data set ready line */
  50. Ring= (1<<6), /* complement of ring indicator line */
  51. Dcd= (1<<7), /* complement of data carrier detect line */
  52. Scratch=7, /* scratchpad */
  53. Dlsb= 0, /* divisor lsb */
  54. Dmsb= 1, /* divisor msb */
  55. Serial= 0,
  56. Modem= 1,
  57. };
  58. typedef struct Uart Uart;
  59. struct Uart
  60. {
  61. int port;
  62. uchar sticky[8]; /* sticky write register values */
  63. uchar txbusy;
  64. void (*rx)(int); /* routine to take a received character */
  65. int (*tx)(void); /* routine to get a character to transmit */
  66. ulong frame;
  67. ulong overrun;
  68. };
  69. static Uart com[2];
  70. static Uart* uart;
  71. #define UartFREQ 1843200
  72. #define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
  73. #define uartrdreg(u,r) inb((u)->port + r)
  74. /*
  75. * set the baud rate by calculating and setting the baudrate
  76. * generator constant. This will work with fairly non-standard
  77. * baud rates.
  78. */
  79. static void
  80. uartsetbaud(Uart *up, int rate)
  81. {
  82. ulong brconst;
  83. brconst = (UartFREQ+8*rate-1)/(16*rate);
  84. uartwrreg(up, Format, Dra);
  85. outb(up->port+Dmsb, (brconst>>8) & 0xff);
  86. outb(up->port+Dlsb, brconst & 0xff);
  87. uartwrreg(up, Format, 0);
  88. }
  89. /*
  90. * toggle DTR
  91. */
  92. static void
  93. uartdtr(Uart *up, int n)
  94. {
  95. if(n)
  96. up->sticky[Mctl] |= Dtr;
  97. else
  98. up->sticky[Mctl] &= ~Dtr;
  99. uartwrreg(up, Mctl, 0);
  100. }
  101. /*
  102. * toggle RTS
  103. */
  104. static void
  105. uartrts(Uart *up, int n)
  106. {
  107. if(n)
  108. up->sticky[Mctl] |= Rts;
  109. else
  110. up->sticky[Mctl] &= ~Rts;
  111. uartwrreg(up, Mctl, 0);
  112. }
  113. static void
  114. uartintr(Ureg*, void *arg)
  115. {
  116. Uart *up;
  117. int ch;
  118. int s, l, loops;
  119. up = arg;
  120. for(loops = 0; loops < 1024; loops++){
  121. s = uartrdreg(up, Istat);
  122. switch(s & 0x3F){
  123. case 6: /* receiver line status */
  124. l = uartrdreg(up, Lstat);
  125. if(l & Ferror)
  126. up->frame++;
  127. if(l & Oerror)
  128. up->overrun++;
  129. break;
  130. case 4: /* received data available */
  131. case 12:
  132. ch = inb(up->port+Data);
  133. if(up->rx)
  134. (*up->rx)(ch);
  135. break;
  136. case 2: /* transmitter empty */
  137. ch = -1;
  138. if(up->tx)
  139. ch = (*up->tx)();
  140. if(ch != -1)
  141. outb(up->port+Data, ch);
  142. else
  143. up->txbusy = 0;
  144. break;
  145. case 0: /* modem status */
  146. uartrdreg(up, Mstat);
  147. break;
  148. default:
  149. if(s&1)
  150. return;
  151. print("weird modem interrupt #%2.2ux\n", s);
  152. break;
  153. }
  154. }
  155. panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
  156. }
  157. /*
  158. * turn on a port's interrupts. set DTR and RTS
  159. */
  160. static void
  161. uartenable(Uart *up)
  162. {
  163. /*
  164. * turn on interrupts
  165. */
  166. up->sticky[Iena] = 0;
  167. if(up->tx)
  168. up->sticky[Iena] |= Ixmt;
  169. if(up->rx)
  170. up->sticky[Iena] |= Ircv|Irstat;
  171. uartwrreg(up, Iena, 0);
  172. /*
  173. * turn on DTR and RTS
  174. */
  175. uartdtr(up, 1);
  176. uartrts(up, 1);
  177. }
  178. static void
  179. uartdisable(Uart* up)
  180. {
  181. /*
  182. * Disable interrupts.
  183. */
  184. up->sticky[Iena] = 0;
  185. uartwrreg(up, Iena, 0);
  186. uartdtr(up, 0);
  187. uartrts(up, 0);
  188. }
  189. void
  190. uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
  191. {
  192. Uart *up;
  193. int vector;
  194. switch(port){
  195. case 0:
  196. port = 0x3F8;
  197. vector = VectorUART0;
  198. up = &com[0];
  199. break;
  200. case 1:
  201. port = 0x2F8;
  202. vector = VectorUART1;
  203. up = &com[1];
  204. break;
  205. default:
  206. return;
  207. }
  208. if(uart != nil && uart != up)
  209. uartdisable(uart);
  210. uart = up;
  211. if(up->port == 0){
  212. up->port = port;
  213. setvec(vector, uartintr, up);
  214. }
  215. /*
  216. * set rate to 9600 baud.
  217. * 8 bits/character.
  218. * 1 stop bit.
  219. * interrupts enabled.
  220. */
  221. uartsetbaud(up, 9600);
  222. up->sticky[Format] = Bits8;
  223. uartwrreg(up, Format, 0);
  224. up->sticky[Mctl] |= Inton;
  225. uartwrreg(up, Mctl, 0x0);
  226. up->rx = rx;
  227. up->tx = tx;
  228. uartenable(up);
  229. if(baud)
  230. uartsetbaud(up, baud);
  231. }
  232. void
  233. uartputc(int c)
  234. {
  235. int i;
  236. Uart *up;
  237. if((up = uart) == nil)
  238. return;
  239. for(i = 0; i < 100; i++){
  240. if(uartrdreg(up, Lstat) & Outready)
  241. break;
  242. delay(1);
  243. }
  244. outb(up->port+Data, c);
  245. }
  246. void
  247. uartputs(IOQ *q, char *s, int n)
  248. {
  249. Uart *up;
  250. int c, x;
  251. if((up = uart) == nil)
  252. return;
  253. while(n--){
  254. if(*s == '\n')
  255. q->putc(q, '\r');
  256. q->putc(q, *s++);
  257. }
  258. x = splhi();
  259. if(up->txbusy == 0 && (c = q->getc(q)) != -1){
  260. uartputc(c & 0xFF);
  261. up->txbusy = 1;
  262. }
  263. splx(x);
  264. }
  265. void
  266. uartdrain(void)
  267. {
  268. Uart *up;
  269. int timeo;
  270. if((up = uart) == nil)
  271. return;
  272. for(timeo = 0; timeo < 10000 && up->txbusy; timeo++)
  273. delay(1);
  274. }