2 #include "../port/lib.h"
7 #include "../port/error.h"
10 * 8250 UART and compatibles.
13 Uart0 = 0x3F8, /* COM1 */
15 Uart1 = 0x2F8, /* COM2 */
21 enum { /* I/O ports */
22 Rbr = 0, /* Receiver Buffer (RO) */
23 Thr = 0, /* Transmitter Holding (WO) */
24 Ier = 1, /* Interrupt Enable */
25 Iir = 2, /* Interrupt Identification (RO) */
26 Fcr = 2, /* FIFO Control (WO) */
27 Lcr = 3, /* Line Control */
28 Mcr = 4, /* Modem Control */
29 Lsr = 5, /* Line Status */
30 Msr = 6, /* Modem Status */
31 Scr = 7, /* Scratch Pad */
32 Dll = 0, /* Divisor Latch LSB */
33 Dlm = 1, /* Divisor Latch MSB */
37 Erda = 0x01, /* Enable Received Data Available */
38 Ethre = 0x02, /* Enable Thr Empty */
39 Erls = 0x04, /* Enable Receiver Line Status */
40 Ems = 0x08, /* Enable Modem Status */
44 Ims = 0x00, /* Ms interrupt */
45 Ip = 0x01, /* Interrupt Pending (not) */
46 Ithre = 0x02, /* Thr Empty */
47 Irda = 0x04, /* Received Data Available */
48 Irls = 0x06, /* Receiver Line Status */
49 Ictoi = 0x0C, /* Character Time-out Indication */
51 Ife = 0xC0, /* FIFOs enabled */
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 */
65 Wls5 = 0x00, /* Word Length Select 5 bits/byte */
66 Wls6 = 0x01, /* 6 bits/byte */
67 Wls7 = 0x02, /* 7 bits/byte */
68 Wls8 = 0x03, /* 8 bits/byte */
70 Stb = 0x04, /* 2 stop bits */
71 Pen = 0x08, /* Parity Enable */
72 Eps = 0x10, /* Even Parity Select */
73 Stp = 0x20, /* Stick Parity */
74 Brk = 0x40, /* Break */
75 Dlab = 0x80, /* Divisor Latch Access Bit */
79 Dtr = 0x01, /* Data Terminal Ready */
80 Rts = 0x02, /* Ready To Send */
81 Out1 = 0x04, /* no longer in use */
82 Ie = 0x08, /* IRQ Enable */
83 Dm = 0x10, /* Diagnostic Mode loopback */
87 Dr = 0x01, /* Data Ready */
88 Oe = 0x02, /* Overrun Error */
89 Pe = 0x04, /* Parity Error */
90 Fe = 0x08, /* Framing Error */
91 Bi = 0x10, /* Break Interrupt */
92 Thre = 0x20, /* Thr Empty */
93 Temt = 0x40, /* Tramsmitter Empty */
94 FIFOerr = 0x80, /* error in receiver FIFO */
98 Dcts = 0x01, /* Delta Cts */
99 Ddsr = 0x02, /* Delta Dsr */
100 Teri = 0x04, /* Trailing Edge of Ri */
101 Ddcd = 0x08, /* Delta Dcd */
102 Cts = 0x10, /* Clear To Send */
103 Dsr = 0x20, /* Data Set Ready */
104 Ri = 0x40, /* Ring Indicator */
105 Dcd = 0x80, /* Data Set Ready */
108 typedef struct Ctlr {
121 extern PhysUart i8250physuart;
123 static Ctlr i8250ctlr[2] = {
126 .tbdf = BUSUNKNOWN, },
130 .tbdf = BUSUNKNOWN, },
133 static Uart i8250uart[2] = {
134 { .regs = &i8250ctlr[0],
137 .phys = &i8250physuart,
139 .next = &i8250uart[1], },
141 { .regs = &i8250ctlr[1],
144 .phys = &i8250physuart,
149 #define csr8r(c, r) inb((c)->io+(r))
150 #define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v))
153 i8250status(Uart* uart, void* buf, long n, long offset)
157 uchar ier, lcr, mcr, msr;
161 mcr = ctlr->sticky[Mcr];
162 msr = csr8r(ctlr, Msr);
163 ier = ctlr->sticky[Ier];
164 lcr = ctlr->sticky[Lcr];
166 "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
167 "dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",
175 (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
184 (msr & Cts) ? " cts": "",
185 (msr & Dsr) ? " dsr": "",
186 (msr & Dcd) ? " dcd": "",
187 (msr & Ri) ? " ring": ""
189 n = readstr(offset, buf, n, p);
196 i8250fifo(Uart* uart, int on)
203 * if none, do nothing;
204 * reset the Rx and Tx FIFOs;
205 * empty the Rx buffer and clear any interrupt conditions;
206 * if enabling, try to turn them on.
212 csr8w(ctlr, Fcr, FIFOtclr|FIFOrclr);
213 for(i = 0; i < 16; i++){
220 csr8w(ctlr, Fcr, FIFO4|FIFOena);
221 if(!(csr8r(ctlr, Iir) & Ife))
230 i8250dtr(Uart* uart, int on)
239 ctlr->sticky[Mcr] |= Dtr;
241 ctlr->sticky[Mcr] &= ~Dtr;
246 i8250rts(Uart* uart, int on)
255 ctlr->sticky[Mcr] |= Rts;
257 ctlr->sticky[Mcr] &= ~Rts;
262 i8250modemctl(Uart* uart, int on)
269 ctlr->sticky[Ier] |= Ems;
272 uart->cts = csr8r(ctlr, Msr) & Cts;
275 ctlr->sticky[Ier] &= ~Ems;
280 iunlock(&uart->tlock);
282 /* modem needs fifo */
283 (*uart->phys->fifo)(uart, on);
287 i8250parity(Uart* uart, int parity)
293 lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
306 ctlr->sticky[Lcr] = lcr;
309 uart->parity = parity;
315 i8250stop(Uart* uart, int stop)
321 lcr = ctlr->sticky[Lcr] & ~Stb;
332 ctlr->sticky[Lcr] = lcr;
341 i8250bits(Uart* uart, int bits)
347 lcr = ctlr->sticky[Lcr] & ~WlsMASK;
365 ctlr->sticky[Lcr] = lcr;
374 i8250baud(Uart* uart, int baud)
380 * Set the Baud rate by calculating and setting the Baud rate
381 * Generator Constant. This will work with fairly non-standard
384 if(uart->freq == 0 || baud <= 0)
386 bgc = (uart->freq+8*baud-1)/(16*baud);
389 csr8w(ctlr, Lcr, Dlab);
390 outb(ctlr->io+Dlm, bgc>>8);
391 outb(ctlr->io+Dll, bgc);
400 i8250break(Uart* uart, int ms)
411 csr8w(ctlr, Lcr, Brk);
412 tsleep(&up->sleep, return0, 0, ms);
417 i8250kick(Uart* uart)
422 if(uart->cts == 0 || uart->blocked)
426 * 128 here is an arbitrary limit to make sure
427 * we don't stay in this loop too long. If the
428 * chip's output queue is longer than 128, too
432 for(i = 0; i < 128; i++){
433 if(!(csr8r(ctlr, Lsr) & Thre))
435 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
437 outb(ctlr->io+Thr, *(uart->op++));
442 i8250interrupt(Ureg*, void* arg)
446 int iir, lsr, old, r;
451 for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
452 switch(iir & IirMASK){
453 case Ims: /* Ms interrupt */
454 r = csr8r(ctlr, Msr);
459 if(old == 0 && uart->cts)
460 uart->ctsbackoff = 2;
461 iunlock(&uart->tlock);
465 if(uart->hup_dsr && uart->dsr && !old)
471 if(uart->hup_dcd && uart->dcd && !old)
476 case Ithre: /* Thr Empty */
479 case Irda: /* Received Data Available */
480 case Ictoi: /* Character Time-out Indication */
482 * Consume any received data.
483 * If the received byte came in with a break,
484 * parity or framing error, throw it away;
485 * overrun is an indication that something has
486 * already been tossed.
488 while((lsr = csr8r(ctlr, Lsr)) & Dr){
495 r = csr8r(ctlr, Rbr);
496 if(!(lsr & (Bi|Fe|Pe)))
501 iprint("weird uart interrupt 0x%2.2uX\n", iir);
508 i8250disable(Uart* uart)
513 * Turn off DTR and RTS, disable interrupts and fifos.
515 (*uart->phys->dtr)(uart, 0);
516 (*uart->phys->rts)(uart, 0);
517 (*uart->phys->fifo)(uart, 0);
520 ctlr->sticky[Ier] = 0;
525 i8250enable(Uart* uart, int ie)
530 * Enable interrupts and turn on DTR and RTS.
531 * Be careful if this is called to set up a polled serial line
532 * early on not to try to enable interrupts as interrupt-
533 * -enabling mechanisms might not be set up yet.
538 intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
541 ctlr->sticky[Ier] = Ethre|Erda;
542 ctlr->sticky[Mcr] |= Ie;
545 ctlr->sticky[Ier] = 0;
546 ctlr->sticky[Mcr] = 0;
548 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
549 csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);
551 (*uart->phys->dtr)(uart, 1);
552 (*uart->phys->rts)(uart, 1);
562 i8250getc(Uart *uart)
567 while(!(csr8r(ctlr, Lsr)&Dr))
569 return csr8r(ctlr, Rbr);
573 i8250putc(Uart *uart, int c)
579 for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
581 outb(ctlr->io+Thr, c);
582 for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
586 PhysUart i8250physuart = {
589 .enable = i8250enable,
590 .disable = i8250disable,
592 .dobreak = i8250break,
596 .parity = i8250parity,
597 .modemctl = i8250modemctl,
600 .status = i8250status,
613 if((p = getconf("console")) == nil)
615 n = strtoul(p, &cmd, 0);
622 uart = &i8250uart[0];
625 uart = &i8250uart[1];
629 uartctl(uart, "b9600 l8 pn s1");
632 (*uart->phys->enable)(uart, 0);