uarti8250.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. /*
  15. * 8250 UART and compatibles.
  16. */
  17. enum {
  18. Uart0 = 0x3F8, /* COM1 */
  19. Uart0IRQ = 4,
  20. Uart1 = 0x2F8, /* COM2 */
  21. Uart1IRQ = 3,
  22. UartFREQ = 1843200,
  23. };
  24. enum { /* registers */
  25. Rbr = 0, /* Receiver Buffer (RO) */
  26. Thr = 0, /* Transmitter Holding (WO) */
  27. Ier = 1, /* Interrupt Enable */
  28. Iir = 2, /* Interrupt Identification (RO) */
  29. Fcr = 2, /* FIFO Control (WO) */
  30. Lcr = 3, /* Line Control */
  31. Mcr = 4, /* Modem Control */
  32. Lsr = 5, /* Line Status */
  33. Msr = 6, /* Modem Status */
  34. Scr = 7, /* Scratch Pad */
  35. Dll = 0, /* Divisor Latch LSB */
  36. Dlm = 1, /* Divisor Latch MSB */
  37. };
  38. enum { /* Ier */
  39. Erda = 0x01, /* Enable Received Data Available */
  40. Ethre = 0x02, /* Enable Thr Empty */
  41. Erls = 0x04, /* Enable Receiver Line Status */
  42. Ems = 0x08, /* Enable Modem Status */
  43. };
  44. enum { /* Iir */
  45. Ims = 0x00, /* Ms interrupt */
  46. Ip = 0x01, /* Interrupt Pending (not) */
  47. Ithre = 0x02, /* Thr Empty */
  48. Irda = 0x04, /* Received Data Available */
  49. Irls = 0x06, /* Receiver Line Status */
  50. Ictoi = 0x0C, /* Character Time-out Indication */
  51. IirMASK = 0x3F,
  52. Ifena = 0xC0, /* FIFOs enabled */
  53. };
  54. enum { /* Fcr */
  55. FIFOena = 0x01, /* FIFO enable */
  56. FIFOrclr = 0x02, /* clear Rx FIFO */
  57. FIFOtclr = 0x04, /* clear Tx FIFO */
  58. FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */
  59. FIFO4 = 0x40, /* 4 bytes */
  60. FIFO8 = 0x80, /* 8 bytes */
  61. FIFO14 = 0xC0, /* 14 bytes */
  62. };
  63. enum { /* Lcr */
  64. Wls5 = 0x00, /* Word Length Select 5 bits/byte */
  65. Wls6 = 0x01, /* 6 bits/byte */
  66. Wls7 = 0x02, /* 7 bits/byte */
  67. Wls8 = 0x03, /* 8 bits/byte */
  68. WlsMASK = 0x03,
  69. Stb = 0x04, /* 2 stop bits */
  70. Pen = 0x08, /* Parity Enable */
  71. Eps = 0x10, /* Even Parity Select */
  72. Stp = 0x20, /* Stick Parity */
  73. Brk = 0x40, /* Break */
  74. Dlab = 0x80, /* Divisor Latch Access Bit */
  75. };
  76. enum { /* Mcr */
  77. Dtr = 0x01, /* Data Terminal Ready */
  78. Rts = 0x02, /* Ready To Send */
  79. Out1 = 0x04, /* no longer in use */
  80. Ie = 0x08, /* IRQ Enable */
  81. Dm = 0x10, /* Diagnostic Mode loopback */
  82. };
  83. enum { /* Lsr */
  84. Dr = 0x01, /* Data Ready */
  85. Oe = 0x02, /* Overrun Error */
  86. Pe = 0x04, /* Parity Error */
  87. Fe = 0x08, /* Framing Error */
  88. Bi = 0x10, /* Break Interrupt */
  89. Thre = 0x20, /* Thr Empty */
  90. Temt = 0x40, /* Tramsmitter Empty */
  91. FIFOerr = 0x80, /* error in receiver FIFO */
  92. };
  93. enum { /* Msr */
  94. Dcts = 0x01, /* Delta Cts */
  95. Ddsr = 0x02, /* Delta Dsr */
  96. Teri = 0x04, /* Trailing Edge of Ri */
  97. Ddcd = 0x08, /* Delta Dcd */
  98. Cts = 0x10, /* Clear To Send */
  99. Dsr = 0x20, /* Data Set Ready */
  100. Ri = 0x40, /* Ring Indicator */
  101. Dcd = 0x80, /* Data Set Ready */
  102. };
  103. typedef struct Ctlr {
  104. int io;
  105. int irq;
  106. int tbdf;
  107. int iena;
  108. void* vector;
  109. int poll;
  110. unsigned char sticky[8];
  111. Lock Lock;
  112. int hasfifo;
  113. int checkfifo;
  114. int fena;
  115. } Ctlr;
  116. extern PhysUart i8250physuart;
  117. static Ctlr i8250ctlr[2] = {
  118. { .io = Uart0,
  119. .irq = Uart0IRQ,
  120. .tbdf = -1,
  121. .poll = 1 | 0, },
  122. { .io = Uart1,
  123. .irq = Uart1IRQ,
  124. .tbdf = -1,
  125. .poll = 1, },
  126. };
  127. static Uart i8250uart[2] = {
  128. { .regs = &i8250ctlr[0],
  129. .name = "COM1",
  130. .freq = UartFREQ,
  131. .phys = &i8250physuart,
  132. .special= 0,
  133. .next = &i8250uart[1], },
  134. { .regs = &i8250ctlr[1],
  135. .name = "COM2",
  136. .freq = UartFREQ,
  137. .phys = &i8250physuart,
  138. .special= 0,
  139. .next = nil, },
  140. };
  141. #define csr8r(c, r) inb((c)->io+(r))
  142. #define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v))
  143. #define csr8o(c, r, v) outb((c)->io+(r), (v))
  144. static int32_t
  145. i8250status(Uart* uart, void* buf, int32_t n, int32_t offset)
  146. {
  147. char *p;
  148. Ctlr *ctlr;
  149. uint8_t ier, lcr, mcr, msr;
  150. ctlr = uart->regs;
  151. p = malloc(READSTR);
  152. mcr = ctlr->sticky[Mcr];
  153. msr = csr8r(ctlr, Msr);
  154. ier = ctlr->sticky[Ier];
  155. lcr = ctlr->sticky[Lcr];
  156. snprint(p, READSTR,
  157. "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
  158. "dev(%d) type(%d) framing(%d) overruns(%d) "
  159. "berr(%d) serr(%d)%s%s%s%s\n",
  160. uart->baud,
  161. uart->hup_dcd,
  162. (msr & Dsr) != 0,
  163. uart->hup_dsr,
  164. (lcr & WlsMASK) + 5,
  165. (ier & Ems) != 0,
  166. (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
  167. (mcr & Rts) != 0,
  168. (lcr & Stb) ? 2: 1,
  169. ctlr->fena,
  170. uart->dev,
  171. uart->type,
  172. uart->ferr,
  173. uart->oerr,
  174. uart->berr,
  175. uart->serr,
  176. (msr & Cts) ? " cts": "",
  177. (msr & Dsr) ? " dsr": "",
  178. (msr & Dcd) ? " dcd": "",
  179. (msr & Ri) ? " ring": ""
  180. );
  181. n = readstr(offset, buf, n, p);
  182. free(p);
  183. return n;
  184. }
  185. static void
  186. i8250fifo(Uart* uart, int level)
  187. {
  188. Ctlr *ctlr;
  189. ctlr = uart->regs;
  190. if(ctlr->hasfifo == 0)
  191. return;
  192. /*
  193. * Changing the FIFOena bit in Fcr flushes data
  194. * from both receive and transmit FIFOs; there's
  195. * no easy way to guarantee not losing data on
  196. * the receive side, but it's possible to wait until
  197. * the transmitter is really empty.
  198. */
  199. ilock(&ctlr->Lock);
  200. while(!(csr8r(ctlr, Lsr) & Temt))
  201. ;
  202. /*
  203. * Set the trigger level, default is the max.
  204. * value.
  205. * Some UARTs require FIFOena to be set before
  206. * other bits can take effect, so set it twice.
  207. */
  208. ctlr->fena = level;
  209. switch(level){
  210. case 0:
  211. break;
  212. case 1:
  213. level = FIFO1|FIFOena;
  214. break;
  215. case 4:
  216. level = FIFO4|FIFOena;
  217. break;
  218. case 8:
  219. level = FIFO8|FIFOena;
  220. break;
  221. default:
  222. level = FIFO14|FIFOena;
  223. break;
  224. }
  225. csr8w(ctlr, Fcr, level);
  226. csr8w(ctlr, Fcr, level);
  227. iunlock(&ctlr->Lock);
  228. }
  229. static void
  230. i8250dtr(Uart* uart, int on)
  231. {
  232. Ctlr *ctlr;
  233. /*
  234. * Toggle DTR.
  235. */
  236. ctlr = uart->regs;
  237. if(on)
  238. ctlr->sticky[Mcr] |= Dtr;
  239. else
  240. ctlr->sticky[Mcr] &= ~Dtr;
  241. csr8w(ctlr, Mcr, 0);
  242. }
  243. static void
  244. i8250rts(Uart* uart, int on)
  245. {
  246. Ctlr *ctlr;
  247. /*
  248. * Toggle RTS.
  249. */
  250. ctlr = uart->regs;
  251. if(on)
  252. ctlr->sticky[Mcr] |= Rts;
  253. else
  254. ctlr->sticky[Mcr] &= ~Rts;
  255. csr8w(ctlr, Mcr, 0);
  256. }
  257. static void
  258. i8250modemctl(Uart* uart, int on)
  259. {
  260. Ctlr *ctlr;
  261. ctlr = uart->regs;
  262. ilock(&uart->tlock);
  263. if(on){
  264. ctlr->sticky[Ier] |= Ems;
  265. csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  266. uart->modem = 1;
  267. uart->cts = csr8r(ctlr, Msr) & Cts;
  268. }
  269. else{
  270. ctlr->sticky[Ier] &= ~Ems;
  271. csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  272. uart->modem = 0;
  273. uart->cts = 1;
  274. }
  275. iunlock(&uart->tlock);
  276. /* modem needs fifo */
  277. (*uart->phys->fifo)(uart, on);
  278. }
  279. static int
  280. i8250parity(Uart* uart, int parity)
  281. {
  282. int lcr;
  283. Ctlr *ctlr;
  284. ctlr = uart->regs;
  285. lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
  286. switch(parity){
  287. case 'e':
  288. lcr |= Eps|Pen;
  289. break;
  290. case 'o':
  291. lcr |= Pen;
  292. break;
  293. case 'n':
  294. break;
  295. default:
  296. return -1;
  297. }
  298. ctlr->sticky[Lcr] = lcr;
  299. csr8w(ctlr, Lcr, 0);
  300. uart->parity = parity;
  301. return 0;
  302. }
  303. static int
  304. i8250stop(Uart* uart, int stop)
  305. {
  306. int lcr;
  307. Ctlr *ctlr;
  308. ctlr = uart->regs;
  309. lcr = ctlr->sticky[Lcr] & ~Stb;
  310. switch(stop){
  311. case 1:
  312. break;
  313. case 2:
  314. lcr |= Stb;
  315. break;
  316. default:
  317. return -1;
  318. }
  319. ctlr->sticky[Lcr] = lcr;
  320. csr8w(ctlr, Lcr, 0);
  321. uart->stop = stop;
  322. return 0;
  323. }
  324. static int
  325. i8250bits(Uart* uart, int bits)
  326. {
  327. int lcr;
  328. Ctlr *ctlr;
  329. ctlr = uart->regs;
  330. lcr = ctlr->sticky[Lcr] & ~WlsMASK;
  331. switch(bits){
  332. case 5:
  333. lcr |= Wls5;
  334. break;
  335. case 6:
  336. lcr |= Wls6;
  337. break;
  338. case 7:
  339. lcr |= Wls7;
  340. break;
  341. case 8:
  342. lcr |= Wls8;
  343. break;
  344. default:
  345. return -1;
  346. }
  347. ctlr->sticky[Lcr] = lcr;
  348. csr8w(ctlr, Lcr, 0);
  349. uart->bits = bits;
  350. return 0;
  351. }
  352. static int
  353. i8250baud(Uart* uart, int baud)
  354. {
  355. uint32_t bgc;
  356. Ctlr *ctlr;
  357. /*
  358. * Set the Baud rate by calculating and setting the Baud rate
  359. * Generator Constant. This will work with fairly non-standard
  360. * Baud rates.
  361. */
  362. if(uart->freq == 0 || baud <= 0)
  363. return -1;
  364. bgc = (uart->freq+8*baud-1)/(16*baud);
  365. ctlr = uart->regs;
  366. csr8w(ctlr, Lcr, Dlab);
  367. csr8o(ctlr, Dlm, bgc>>8);
  368. csr8o(ctlr, Dll, bgc);
  369. csr8w(ctlr, Lcr, 0);
  370. uart->baud = baud;
  371. return 0;
  372. }
  373. static void
  374. i8250break(Uart* uart, int ms)
  375. {
  376. Proc *up = externup();
  377. Ctlr *ctlr;
  378. /*
  379. * Send a break.
  380. */
  381. if(ms <= 0)
  382. ms = 200;
  383. ctlr = uart->regs;
  384. csr8w(ctlr, Lcr, Brk);
  385. tsleep(&up->sleep, return0, 0, ms);
  386. csr8w(ctlr, Lcr, 0);
  387. }
  388. static void
  389. i8250kick(Uart* uart)
  390. {
  391. int i;
  392. Ctlr *ctlr;
  393. if(uart->cts == 0 || uart->blocked)
  394. return;
  395. /*
  396. * 128 here is an arbitrary limit to make sure
  397. * we don't stay in this loop too long. If the
  398. * chip's output queue is longer than 128, too
  399. * bad -- presotto
  400. */
  401. ctlr = uart->regs;
  402. for(i = 0; i < 128; i++){
  403. if(!(csr8r(ctlr, Lsr) & Thre))
  404. break;
  405. if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
  406. break;
  407. csr8o(ctlr, Thr, *(uart->op++));
  408. }
  409. }
  410. static void
  411. i8250interrupt(Ureg* ureg, void* arg)
  412. {
  413. Ctlr *ctlr;
  414. Uart *uart;
  415. int iir, lsr, old, r;
  416. uart = arg;
  417. ctlr = uart->regs;
  418. outb(0x3f8, '.');
  419. for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
  420. switch(iir & IirMASK){
  421. case Ims: /* Ms interrupt */
  422. r = csr8r(ctlr, Msr);
  423. if(r & Dcts){
  424. ilock(&uart->tlock);
  425. old = uart->cts;
  426. uart->cts = r & Cts;
  427. if(old == 0 && uart->cts)
  428. uart->ctsbackoff = 2;
  429. iunlock(&uart->tlock);
  430. }
  431. if(r & Ddsr){
  432. old = r & Dsr;
  433. if(uart->hup_dsr && uart->dsr && !old)
  434. uart->dohup = 1;
  435. uart->dsr = old;
  436. }
  437. if(r & Ddcd){
  438. old = r & Dcd;
  439. if(uart->hup_dcd && uart->dcd && !old)
  440. uart->dohup = 1;
  441. uart->dcd = old;
  442. }
  443. break;
  444. case Ithre: /* Thr Empty */
  445. uartkick(uart);
  446. break;
  447. case Irda: /* Received Data Available */
  448. case Irls: /* Receiver Line Status */
  449. case Ictoi: /* Character Time-out Indication */
  450. /*
  451. * Consume any received data.
  452. * If the received byte came in with a break,
  453. * parity or framing error, throw it away;
  454. * overrun is an indication that something has
  455. * already been tossed.
  456. */
  457. while((lsr = csr8r(ctlr, Lsr)) & Dr){
  458. if(lsr & (FIFOerr|Oe))
  459. uart->oerr++;
  460. if(lsr & Pe)
  461. uart->perr++;
  462. if(lsr & Fe)
  463. uart->ferr++;
  464. r = csr8r(ctlr, Rbr);
  465. outb(0x3f8, 'u');
  466. if(!(lsr & (Bi|Fe|Pe)))
  467. uartrecv(uart, r);
  468. }
  469. break;
  470. default:
  471. iprint("weird uart interrupt 0x%2.2X\n", iir);
  472. break;
  473. }
  474. }
  475. }
  476. static void
  477. i8250disable(Uart* uart)
  478. {
  479. Ctlr *ctlr;
  480. /*
  481. * Turn off DTR and RTS, disable interrupts and fifos.
  482. */
  483. (*uart->phys->dtr)(uart, 0);
  484. (*uart->phys->rts)(uart, 0);
  485. (*uart->phys->fifo)(uart, 0);
  486. ctlr = uart->regs;
  487. ctlr->sticky[Ier] = 0;
  488. csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  489. if(ctlr->iena != 0){
  490. if(intrdisable(ctlr->vector) == 0)
  491. ctlr->iena = 0;
  492. }
  493. }
  494. static void
  495. i8250enable(Uart* uart, int ie)
  496. {
  497. Ctlr *ctlr;
  498. ctlr = uart->regs;
  499. // old school uarts, with poll or tbdf = -1, can no longer
  500. // be supported for interrupts. Sorry.
  501. if (ctlr->poll || (ctlr->tbdf == -1))
  502. ie = 0;
  503. /*
  504. * Check if there is a FIFO.
  505. * Changing the FIFOena bit in Fcr flushes data
  506. * from both receive and transmit FIFOs; there's
  507. * no easy way to guarantee not losing data on
  508. * the receive side, but it's possible to wait until
  509. * the transmitter is really empty.
  510. * Also, reading the Iir outwith i8250interrupt()
  511. * can be dangerous, but this should only happen
  512. * once, before interrupts are enabled.
  513. */
  514. ilock(&ctlr->Lock);
  515. if(!ctlr->checkfifo){
  516. /*
  517. * Wait until the transmitter is really empty.
  518. */
  519. while(!(csr8r(ctlr, Lsr) & Temt))
  520. ;
  521. csr8w(ctlr, Fcr, FIFOena);
  522. if(csr8r(ctlr, Iir) & Ifena)
  523. ctlr->hasfifo = 1;
  524. csr8w(ctlr, Fcr, 0);
  525. ctlr->checkfifo = 1;
  526. }
  527. iunlock(&ctlr->Lock);
  528. /*
  529. * Enable interrupts and turn on DTR and RTS.
  530. * Be careful if this is called to set up a polled serial line
  531. * early on not to try to enable interrupts as interrupt-
  532. * -enabling mechanisms might not be set up yet.
  533. */
  534. if(ie){
  535. if(ctlr->iena == 0 && !ctlr->poll){
  536. ctlr->vector = intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
  537. ctlr->iena = 1;
  538. }
  539. ctlr->sticky[Ier] = Ethre|Erda;
  540. ctlr->sticky[Mcr] |= Ie;
  541. }
  542. else{
  543. ctlr->sticky[Ier] = 0;
  544. ctlr->sticky[Mcr] = 0;
  545. }
  546. csr8w(ctlr, Ier, ctlr->sticky[Ier]);
  547. csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);
  548. (*uart->phys->dtr)(uart, 1);
  549. (*uart->phys->rts)(uart, 1);
  550. /*
  551. * During startup, the i8259 interrupt controller is reset.
  552. * This may result in a lost interrupt from the i8250 uart.
  553. * The i8250 thinks the interrupt is still outstanding and does not
  554. * generate any further interrupts. The workaround is to call the
  555. * interrupt handler to clear any pending interrupt events.
  556. * Note: this must be done after setting Ier.
  557. */
  558. if(ie)
  559. i8250interrupt(nil, uart);
  560. }
  561. void*
  562. i8250alloc(int io, int irq, int tbdf)
  563. {
  564. Ctlr *ctlr;
  565. if((ctlr = malloc(sizeof(Ctlr))) != nil){
  566. ctlr->io = io;
  567. ctlr->irq = irq;
  568. ctlr->tbdf = tbdf;
  569. }
  570. return ctlr;
  571. }
  572. static Uart*
  573. i8250pnp(void)
  574. {
  575. int i, found = 0;
  576. Ctlr *ctlr;
  577. // first is invariant; it points to the first uart
  578. // in the least. Head points to the head of known
  579. // good uarts. uart is the iterator.
  580. Uart *first, *head = nil, *uart;
  581. print("i8250pnp\n");
  582. first = i8250uart;
  583. for(i = 0; i < nelem(i8250uart); i++){
  584. /*
  585. * Does it exist?
  586. * Should be able to write/read the Scratch Pad
  587. * and reserve the I/O space.
  588. */
  589. uart = &i8250uart[i];
  590. print("Check i8250 %s:", uart->name);
  591. ctlr = uart->regs;
  592. csr8o(ctlr, Scr, 0x55);
  593. if(csr8r(ctlr, Scr) != 0x55) {
  594. print("Scr test failed, ignoring it\n");
  595. // Take it out of the list, iff it is not the first.
  596. if (uart != first)
  597. (uart-1)->next = uart->next;
  598. continue;
  599. }
  600. if(ioalloc(ctlr->io, 8, 0, uart->name) < 0) {
  601. print("ioalloc(%#x, 8) failed; ignoring it\n", ctlr->io);
  602. // Take it out of the list, iff it is not the first.
  603. if (uart != first)
  604. (uart-1)->next = uart->next;
  605. continue;
  606. }
  607. if (head == nil)
  608. head = uart;
  609. found++;
  610. }
  611. print("Found %d i8250 uarts, returning %p\n", found, head);
  612. return head;
  613. }
  614. static int
  615. i8250getc(Uart* uart)
  616. {
  617. Ctlr *ctlr;
  618. ctlr = uart->regs;
  619. while(!(csr8r(ctlr, Lsr) & Dr))
  620. delay(1);
  621. return csr8r(ctlr, Rbr);
  622. }
  623. static void
  624. i8250putc(Uart* uart, int c)
  625. {
  626. int i;
  627. Ctlr *ctlr;
  628. ctlr = uart->regs;
  629. for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++)
  630. delay(1);
  631. csr8o(ctlr, Thr, c);
  632. for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++)
  633. delay(1);
  634. }
  635. static void
  636. i8250poll(Uart* uart)
  637. {
  638. Ctlr *ctlr;
  639. /*
  640. * If PhysUart has a non-nil .poll member, this
  641. * routine will be called from the uartclock timer.
  642. * If the Ctlr .poll member is non-zero, when the
  643. * Uart is enabled interrupts will not be enabled
  644. * and the result is polled input and output.
  645. * Not very useful here, but ports to new hardware
  646. * or simulators can use this to get serial I/O
  647. * without setting up the interrupt mechanism.
  648. */
  649. ctlr = uart->regs;
  650. if(ctlr->iena || !ctlr->poll)
  651. return;
  652. i8250interrupt(nil, uart);
  653. }
  654. PhysUart i8250physuart = {
  655. .name = "i8250",
  656. .pnp = i8250pnp,
  657. .enable = i8250enable,
  658. .disable = i8250disable,
  659. .kick = i8250kick,
  660. .dobreak = i8250break,
  661. .baud = i8250baud,
  662. .bits = i8250bits,
  663. .stop = i8250stop,
  664. .parity = i8250parity,
  665. .modemctl = i8250modemctl,
  666. .rts = i8250rts,
  667. .dtr = i8250dtr,
  668. .status = i8250status,
  669. .fifo = i8250fifo,
  670. .getc = i8250getc,
  671. .putc = i8250putc,
  672. .poll = i8250poll,
  673. };
  674. extern void (*consuartputs)(char*, int);
  675. static Uart *i8250consuart;
  676. static void
  677. i8250consputs(char *s, int n)
  678. {
  679. int i;
  680. for(i = 0; i < n; i++)
  681. i8250putc(i8250consuart, s[i]);
  682. }
  683. void
  684. i8250console(char* cfg)
  685. {
  686. int i;
  687. Uart *uart;
  688. Ctlr *ctlr;
  689. char *cmd, *p;
  690. /*
  691. * Before i8250pnp() is run can only set the console
  692. * to 0 or 1 because those are the only uart structs which
  693. * will be the same before and after that.
  694. */
  695. if(/*(p = getconf("console")) == nil &&*/ (p = cfg) == nil)
  696. return;
  697. i = strtoul(p, &cmd, 0);
  698. if(p == cmd)
  699. return;
  700. if(consuartputs != nil){
  701. return;
  702. }
  703. switch(i){
  704. default:
  705. return;
  706. case 0:
  707. uart = &i8250uart[0];
  708. break;
  709. case 1:
  710. uart = &i8250uart[1];
  711. break;
  712. }
  713. /*
  714. * Does it exist?
  715. * Should be able to write/read
  716. * the Scratch Pad.
  717. */
  718. ctlr = uart->regs;
  719. csr8o(ctlr, Scr, 0x55);
  720. if(csr8r(ctlr, Scr) != 0x55)
  721. return;
  722. (*uart->phys->enable)(uart, 0);
  723. uartctl(uart, "b115200 l8 pn s1 i1");
  724. if(*cmd != '\0')
  725. uartctl(uart, cmd);
  726. i8250consuart = uart;
  727. consuartputs = i8250consputs;
  728. uart->console = 1;
  729. }