8250.c 6.8 KB

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