2 #include "../port/lib.h"
7 #include "../port/error.h"
10 * 8250 UART and compatibles.
13 Uart0 = 0x3F8, /* COM1 */
15 Uart1 = 0x2F8, /* COM2 */
17 Uart2 = 0x200, /* COM3 */
23 enum { /* I/O ports */
24 Rbr = 0, /* Receiver Buffer (RO) */
25 Thr = 0, /* Transmitter Holding (WO) */
26 Ier = 1, /* Interrupt Enable */
27 Iir = 2, /* Interrupt Identification (RO) */
28 Fcr = 2, /* FIFO Control (WO) */
29 Lcr = 3, /* Line Control */
30 Mcr = 4, /* Modem Control */
31 Lsr = 5, /* Line Status */
32 Msr = 6, /* Modem Status */
33 Scr = 7, /* Scratch Pad */
34 Dll = 0, /* Divisor Latch LSB */
35 Dlm = 1, /* Divisor Latch MSB */
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 */
46 Ims = 0x00, /* Ms interrupt */
47 Ip = 0x01, /* Interrupt Pending (not) */
48 Ithre = 0x02, /* Thr Empty */
49 Irda = 0x04, /* Received Data Available */
50 Irls = 0x06, /* Receiver Line Status */
51 Ictoi = 0x0C, /* Character Time-out Indication */
53 Ifena = 0xC0, /* FIFOs enabled */
57 FIFOena = 0x01, /* FIFO enable */
58 FIFOrclr = 0x02, /* clear Rx FIFO */
59 FIFOtclr = 0x04, /* clear Tx FIFO */
60 FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */
61 FIFO4 = 0x40, /* 4 bytes */
62 FIFO8 = 0x80, /* 8 bytes */
63 FIFO14 = 0xC0, /* 14 bytes */
67 Wls5 = 0x00, /* Word Length Select 5 bits/byte */
68 Wls6 = 0x01, /* 6 bits/byte */
69 Wls7 = 0x02, /* 7 bits/byte */
70 Wls8 = 0x03, /* 8 bits/byte */
72 Stb = 0x04, /* 2 stop bits */
73 Pen = 0x08, /* Parity Enable */
74 Eps = 0x10, /* Even Parity Select */
75 Stp = 0x20, /* Stick Parity */
76 Brk = 0x40, /* Break */
77 Dlab = 0x80, /* Divisor Latch Access Bit */
81 Dtr = 0x01, /* Data Terminal Ready */
82 Rts = 0x02, /* Ready To Send */
83 Out1 = 0x04, /* no longer in use */
84 Ie = 0x08, /* IRQ Enable */
85 Dm = 0x10, /* Diagnostic Mode loopback */
89 Dr = 0x01, /* Data Ready */
90 Oe = 0x02, /* Overrun Error */
91 Pe = 0x04, /* Parity Error */
92 Fe = 0x08, /* Framing Error */
93 Bi = 0x10, /* Break Interrupt */
94 Thre = 0x20, /* Thr Empty */
95 Temt = 0x40, /* Tramsmitter Empty */
96 FIFOerr = 0x80, /* error in receiver FIFO */
100 Dcts = 0x01, /* Delta Cts */
101 Ddsr = 0x02, /* Delta Dsr */
102 Teri = 0x04, /* Trailing Edge of Ri */
103 Ddcd = 0x08, /* Delta Dcd */
104 Cts = 0x10, /* Clear To Send */
105 Dsr = 0x20, /* Data Set Ready */
106 Ri = 0x40, /* Ring Indicator */
107 Dcd = 0x80, /* Data Set Ready */
110 typedef struct Ctlr {
124 extern PhysUart i8250physuart;
126 static Ctlr i8250ctlr[3] = {
129 .tbdf = BUSUNKNOWN, },
133 .tbdf = BUSUNKNOWN, },
137 .tbdf = BUSUNKNOWN, },
140 static Uart i8250uart[3] = {
141 { .regs = &i8250ctlr[0],
144 .phys = &i8250physuart,
146 .next = &i8250uart[1], },
148 { .regs = &i8250ctlr[1],
151 .phys = &i8250physuart,
153 .next = &i8250uart[2], },
155 { .regs = &i8250ctlr[2],
158 .phys = &i8250physuart,
163 #define csr8r(c, r) inb((c)->io+(r))
164 #define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v))
167 i8250status(Uart* uart, void* buf, long n, long offset)
171 uchar ier, lcr, mcr, msr;
174 p = smalloc(READSTR);
175 mcr = ctlr->sticky[Mcr];
176 msr = csr8r(ctlr, Msr);
177 ier = ctlr->sticky[Ier];
178 lcr = ctlr->sticky[Lcr];
180 "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
181 "dev(%d) type(%d) framing(%d) overruns(%d) "
182 "berr(%d) serr(%d)%s%s%s%s\n",
190 (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
201 (msr & Cts) ? " cts": "",
202 (msr & Dsr) ? " dsr": "",
203 (msr & Dcd) ? " dcd": "",
204 (msr & Ri) ? " ring": ""
206 n = readstr(offset, buf, n, p);
213 i8250fifo(Uart* uart, int level)
218 if(ctlr->hasfifo == 0)
222 * Changing the FIFOena bit in Fcr flushes data
223 * from both receive and transmit FIFOs; there's
224 * no easy way to guarantee not losing data on
225 * the receive side, but it's possible to wait until
226 * the transmitter is really empty.
229 while(!(csr8r(ctlr, Lsr) & Temt))
233 * Set the trigger level, default is the max.
235 * Some UARTs require FIFOena to be set before
236 * other bits can take effect, so set it twice.
243 level = FIFO1|FIFOena;
246 level = FIFO4|FIFOena;
249 level = FIFO8|FIFOena;
252 level = FIFO14|FIFOena;
255 csr8w(ctlr, Fcr, level);
256 csr8w(ctlr, Fcr, level);
261 i8250dtr(Uart* uart, int on)
270 ctlr->sticky[Mcr] |= Dtr;
272 ctlr->sticky[Mcr] &= ~Dtr;
277 i8250rts(Uart* uart, int on)
286 ctlr->sticky[Mcr] |= Rts;
288 ctlr->sticky[Mcr] &= ~Rts;
293 i8250modemctl(Uart* uart, int on)
300 ctlr->sticky[Ier] |= Ems;
301 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
303 uart->cts = csr8r(ctlr, Msr) & Cts;
306 ctlr->sticky[Ier] &= ~Ems;
307 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
311 iunlock(&uart->tlock);
313 /* modem needs fifo */
314 (*uart->phys->fifo)(uart, on);
318 i8250parity(Uart* uart, int parity)
324 lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
338 ctlr->sticky[Lcr] = lcr;
341 uart->parity = parity;
347 i8250stop(Uart* uart, int stop)
353 lcr = ctlr->sticky[Lcr] & ~Stb;
364 ctlr->sticky[Lcr] = lcr;
373 i8250bits(Uart* uart, int bits)
379 lcr = ctlr->sticky[Lcr] & ~WlsMASK;
397 ctlr->sticky[Lcr] = lcr;
406 i8250baud(Uart* uart, int baud)
412 * Set the Baud rate by calculating and setting the Baud rate
413 * Generator Constant. This will work with fairly non-standard
416 if(uart->freq == 0 || baud <= 0)
418 bgc = (uart->freq+8*baud-1)/(16*baud);
421 csr8w(ctlr, Lcr, Dlab);
422 outb(ctlr->io+Dlm, bgc>>8);
423 outb(ctlr->io+Dll, bgc);
432 i8250break(Uart* uart, int ms)
443 csr8w(ctlr, Lcr, Brk);
444 tsleep(&up->sleep, return0, 0, ms);
449 i8250kick(Uart* uart)
454 if(uart->cts == 0 || uart->blocked)
458 * 128 here is an arbitrary limit to make sure
459 * we don't stay in this loop too long. If the
460 * chip's output queue is longer than 128, too
464 for(i = 0; i < 128; i++){
465 if(!(csr8r(ctlr, Lsr) & Thre))
467 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
469 outb(ctlr->io+Thr, *(uart->op++));
474 i8250interrupt(Ureg*, void* arg)
478 int iir, lsr, old, r;
483 for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
484 switch(iir & IirMASK){
485 case Ims: /* Ms interrupt */
486 r = csr8r(ctlr, Msr);
491 if(old == 0 && uart->cts)
492 uart->ctsbackoff = 2;
493 iunlock(&uart->tlock);
497 if(uart->hup_dsr && uart->dsr && !old)
503 if(uart->hup_dcd && uart->dcd && !old)
508 case Ithre: /* Thr Empty */
511 case Irda: /* Received Data Available */
512 case Irls: /* Receiver Line Status */
513 case Ictoi: /* Character Time-out Indication */
515 * Consume any received data.
516 * If the received byte came in with a break,
517 * parity or framing error, throw it away;
518 * overrun is an indication that something has
519 * already been tossed.
521 while((lsr = csr8r(ctlr, Lsr)) & Dr){
522 if(lsr & (FIFOerr|Oe))
528 r = csr8r(ctlr, Rbr);
529 if(!(lsr & (Bi|Fe|Pe)))
535 iprint("weird uart interrupt 0x%2.2uX\n", iir);
542 i8250disable(Uart* uart)
547 * Turn off DTR and RTS, disable interrupts and fifos.
549 (*uart->phys->dtr)(uart, 0);
550 (*uart->phys->rts)(uart, 0);
551 (*uart->phys->fifo)(uart, 0);
554 ctlr->sticky[Ier] = 0;
555 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
558 if(intrdisable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name) == 0)
564 i8250enable(Uart* uart, int ie)
571 * Check if there is a FIFO.
572 * Changing the FIFOena bit in Fcr flushes data
573 * from both receive and transmit FIFOs; there's
574 * no easy way to guarantee not losing data on
575 * the receive side, but it's possible to wait until
576 * the transmitter is really empty.
577 * Also, reading the Iir outwith i8250interrupt()
578 * can be dangerous, but this should only happen
579 * once before interrupts are enabled.
582 if(!ctlr->checkfifo){
584 * Wait until the transmitter is really empty.
586 while(!(csr8r(ctlr, Lsr) & Temt))
588 csr8w(ctlr, Fcr, FIFOena);
589 if(csr8r(ctlr, Iir) & Ifena)
597 * Enable interrupts and turn on DTR and RTS.
598 * Be careful if this is called to set up a polled serial line
599 * early on not to try to enable interrupts as interrupt-
600 * -enabling mechanisms might not be set up yet.
604 intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
607 ctlr->sticky[Ier] = Ethre|Erda;
608 ctlr->sticky[Mcr] |= Ie;
611 ctlr->sticky[Ier] = 0;
612 ctlr->sticky[Mcr] = 0;
614 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
615 csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);
617 (*uart->phys->dtr)(uart, 1);
618 (*uart->phys->rts)(uart, 1);
621 * During startup, the i8259 interrupt controller is reset.
622 * This may result in a lost interrupt from the i8250 uart.
623 * The i8250 thinks the interrupt is still outstanding and does not
624 * generate any further interrupts. The workaround is to call the
625 * interrupt handler to clear any pending interrupt events.
626 * Note: this must be done after setting Ier.
629 i8250interrupt(nil, uart);
633 i8250alloc(int io, int irq, int tbdf)
637 if((ctlr = malloc(sizeof(Ctlr))) != nil){
653 i8250getc(Uart *uart)
658 while(!(csr8r(ctlr, Lsr)&Dr))
660 return csr8r(ctlr, Rbr);
664 i8250putc(Uart *uart, int c)
670 for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
672 outb(ctlr->io+Thr, c);
673 for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
677 PhysUart i8250physuart = {
680 .enable = i8250enable,
681 .disable = i8250disable,
683 .dobreak = i8250break,
687 .parity = i8250parity,
688 .modemctl = i8250modemctl,
691 .status = i8250status,
704 if((p = getconf("console")) == nil)
706 n = strtoul(p, &cmd, 0);
713 uart = &i8250uart[0];
716 uart = &i8250uart[1];
719 uart = &i8250uart[2];
723 (*uart->phys->enable)(uart, 0);
724 uartctl(uart, "b9600 l8 pn s1");
733 i8250mouse(char* which, int (*putc)(Queue*, int), int setb1200)
738 port = strtol(which, &p, 0);
739 if(p == which || port < 0 || port > 1)
741 uartmouse(&i8250uart[port], putc, setb1200);
745 i8250setmouseputc(char* which, int (*putc)(Queue*, int))
750 port = strtol(which, &p, 0);
751 if(p == which || port < 0 || port > 1)
753 uartsetmouseputc(&i8250uart[port], putc);