1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8
9 /*
10 * 8250 UART and compatibles.
11 */
12 enum {
13 Uart0 = 0x3F8, /* COM1 */
14 Uart0IRQ = 4,
15 Uart1 = 0x2F8, /* COM2 */
16 Uart1IRQ = 3,
17
18 UartFREQ = 1843200,
19 };
20
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 */
34 };
35
36 enum { /* Ier */
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 */
41 };
42
43 enum { /* Iir */
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 */
50 IirMASK = 0x3F,
51 Ifena = 0xC0, /* FIFOs enabled */
52 };
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
64 enum { /* Lcr */
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 */
69 WlsMASK = 0x03,
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 */
76 };
77
78 enum { /* Mcr */
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 */
84 };
85
86 enum { /* Lsr */
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 */
95 };
96
97 enum { /* Msr */
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 */
106 };
107
108 typedef struct Ctlr {
109 int io;
110 int irq;
111 int tbdf;
112 int iena;
113
114 uchar sticky[8];
115
116 Lock;
117 int hasfifo;
118 int checkfifo;
119 int fena;
120 } Ctlr;
121
122 extern PhysUart i8250physuart;
123
124 static Ctlr i8250ctlr[2] = {
125 { .io = Uart0,
126 .irq = Uart0IRQ,
127 .tbdf = BUSUNKNOWN, },
128
129 { .io = Uart1,
130 .irq = Uart1IRQ,
131 .tbdf = BUSUNKNOWN, },
132 };
133
134 static Uart i8250uart[2] = {
135 { .regs = &i8250ctlr[0],
136 .name = "COM1",
137 .freq = UartFREQ,
138 .phys = &i8250physuart,
139 .special= 0,
140 .next = &i8250uart[1], },
141
142 { .regs = &i8250ctlr[1],
143 .name = "COM2",
144 .freq = UartFREQ,
145 .phys = &i8250physuart,
146 .special= 0,
147 .next = nil, },
148 };
149
150 #define csr8r(c, r) inb((c)->io+(r))
151 #define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v))
152
153 static long
i8250status(Uart * uart,void * buf,long n,long offset)154 i8250status(Uart* uart, void* buf, long n, long offset)
155 {
156 char *p;
157 Ctlr *ctlr;
158 uchar ier, lcr, mcr, msr;
159
160 p = malloc(READSTR);
161 if(p == nil)
162 error(Enomem);
163 ctlr = uart->regs;
164 mcr = ctlr->sticky[Mcr];
165 msr = csr8r(ctlr, Msr);
166 ier = ctlr->sticky[Ier];
167 lcr = ctlr->sticky[Lcr];
168 snprint(p, READSTR,
169 "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
170 "dev(%d) type(%d) framing(%d) overruns(%d) "
171 "berr(%d) serr(%d)%s%s%s%s\n",
172
173 uart->baud,
174 uart->hup_dcd,
175 (msr & Dsr) != 0,
176 uart->hup_dsr,
177 (lcr & WlsMASK) + 5,
178 (ier & Ems) != 0,
179 (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
180 (mcr & Rts) != 0,
181 (lcr & Stb) ? 2: 1,
182 ctlr->fena,
183
184 uart->dev,
185 uart->type,
186 uart->ferr,
187 uart->oerr,
188 uart->berr,
189 uart->serr,
190 (msr & Cts) ? " cts": "",
191 (msr & Dsr) ? " dsr": "",
192 (msr & Dcd) ? " dcd": "",
193 (msr & Ri) ? " ring": ""
194 );
195 n = readstr(offset, buf, n, p);
196 free(p);
197
198 return n;
199 }
200
201 static void
i8250fifo(Uart * uart,int level)202 i8250fifo(Uart* uart, int level)
203 {
204 Ctlr *ctlr;
205
206 ctlr = uart->regs;
207 if(ctlr->hasfifo == 0)
208 return;
209
210 /*
211 * Changing the FIFOena bit in Fcr flushes data
212 * from both receive and transmit FIFOs; there's
213 * no easy way to guarantee not losing data on
214 * the receive side, but it's possible to wait until
215 * the transmitter is really empty.
216 */
217 ilock(ctlr);
218 while(!(csr8r(ctlr, Lsr) & Temt))
219 ;
220
221 /*
222 * Set the trigger level, default is the max.
223 * value.
224 * Some UARTs require FIFOena to be set before
225 * other bits can take effect, so set it twice.
226 */
227 ctlr->fena = level;
228 switch(level){
229 case 0:
230 break;
231 case 1:
232 level = FIFO1|FIFOena;
233 break;
234 case 4:
235 level = FIFO4|FIFOena;
236 break;
237 case 8:
238 level = FIFO8|FIFOena;
239 break;
240 default:
241 level = FIFO14|FIFOena;
242 break;
243 }
244 csr8w(ctlr, Fcr, level);
245 csr8w(ctlr, Fcr, level);
246 iunlock(ctlr);
247 }
248
249 static void
i8250dtr(Uart * uart,int on)250 i8250dtr(Uart* uart, int on)
251 {
252 Ctlr *ctlr;
253
254 /*
255 * Toggle DTR.
256 */
257 ctlr = uart->regs;
258 if(on)
259 ctlr->sticky[Mcr] |= Dtr;
260 else
261 ctlr->sticky[Mcr] &= ~Dtr;
262 csr8w(ctlr, Mcr, 0);
263 }
264
265 static void
i8250rts(Uart * uart,int on)266 i8250rts(Uart* uart, int on)
267 {
268 Ctlr *ctlr;
269
270 /*
271 * Toggle RTS.
272 */
273 ctlr = uart->regs;
274 if(on)
275 ctlr->sticky[Mcr] |= Rts;
276 else
277 ctlr->sticky[Mcr] &= ~Rts;
278 csr8w(ctlr, Mcr, 0);
279 }
280
281 static void
i8250modemctl(Uart * uart,int on)282 i8250modemctl(Uart* uart, int on)
283 {
284 Ctlr *ctlr;
285
286 ctlr = uart->regs;
287 ilock(&uart->tlock);
288 if(on){
289 ctlr->sticky[Ier] |= Ems;
290 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
291 uart->modem = 1;
292 uart->cts = csr8r(ctlr, Msr) & Cts;
293 }
294 else{
295 ctlr->sticky[Ier] &= ~Ems;
296 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
297 uart->modem = 0;
298 uart->cts = 1;
299 }
300 iunlock(&uart->tlock);
301
302 /* modem needs fifo */
303 (*uart->phys->fifo)(uart, on);
304 }
305
306 static int
i8250parity(Uart * uart,int parity)307 i8250parity(Uart* uart, int parity)
308 {
309 int lcr;
310 Ctlr *ctlr;
311
312 ctlr = uart->regs;
313 lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
314
315 switch(parity){
316 case 'e':
317 lcr |= Eps|Pen;
318 break;
319 case 'o':
320 lcr |= Pen;
321 break;
322 case 'n':
323 break;
324 default:
325 return -1;
326 }
327 ctlr->sticky[Lcr] = lcr;
328 csr8w(ctlr, Lcr, 0);
329
330 uart->parity = parity;
331
332 return 0;
333 }
334
335 static int
i8250stop(Uart * uart,int stop)336 i8250stop(Uart* uart, int stop)
337 {
338 int lcr;
339 Ctlr *ctlr;
340
341 ctlr = uart->regs;
342 lcr = ctlr->sticky[Lcr] & ~Stb;
343
344 switch(stop){
345 case 1:
346 break;
347 case 2:
348 lcr |= Stb;
349 break;
350 default:
351 return -1;
352 }
353 ctlr->sticky[Lcr] = lcr;
354 csr8w(ctlr, Lcr, 0);
355
356 uart->stop = stop;
357
358 return 0;
359 }
360
361 static int
i8250bits(Uart * uart,int bits)362 i8250bits(Uart* uart, int bits)
363 {
364 int lcr;
365 Ctlr *ctlr;
366
367 ctlr = uart->regs;
368 lcr = ctlr->sticky[Lcr] & ~WlsMASK;
369
370 switch(bits){
371 case 5:
372 lcr |= Wls5;
373 break;
374 case 6:
375 lcr |= Wls6;
376 break;
377 case 7:
378 lcr |= Wls7;
379 break;
380 case 8:
381 lcr |= Wls8;
382 break;
383 default:
384 return -1;
385 }
386 ctlr->sticky[Lcr] = lcr;
387 csr8w(ctlr, Lcr, 0);
388
389 uart->bits = bits;
390
391 return 0;
392 }
393
394 static int
i8250baud(Uart * uart,int baud)395 i8250baud(Uart* uart, int baud)
396 {
397 ulong bgc;
398 Ctlr *ctlr;
399
400 /*
401 * Set the Baud rate by calculating and setting the Baud rate
402 * Generator Constant. This will work with fairly non-standard
403 * Baud rates.
404 */
405 if(uart->freq == 0 || baud <= 0)
406 return -1;
407 bgc = (uart->freq+8*baud-1)/(16*baud);
408
409 ctlr = uart->regs;
410 csr8w(ctlr, Lcr, Dlab);
411 outb(ctlr->io+Dlm, bgc>>8);
412 outb(ctlr->io+Dll, bgc);
413 csr8w(ctlr, Lcr, 0);
414
415 uart->baud = baud;
416
417 return 0;
418 }
419
420 static void
i8250break(Uart * uart,int ms)421 i8250break(Uart* uart, int ms)
422 {
423 Ctlr *ctlr;
424
425 /*
426 * Send a break.
427 */
428 if(ms <= 0)
429 ms = 200;
430
431 ctlr = uart->regs;
432 csr8w(ctlr, Lcr, Brk);
433 tsleep(&up->sleep, return0, 0, ms);
434 csr8w(ctlr, Lcr, 0);
435 }
436
437 static void
i8250kick(Uart * uart)438 i8250kick(Uart* uart)
439 {
440 int i;
441 Ctlr *ctlr;
442
443 if(uart->cts == 0 || uart->blocked)
444 return;
445
446 /*
447 * 128 here is an arbitrary limit to make sure
448 * we don't stay in this loop too long. If the
449 * chip's output queue is longer than 128, too
450 * bad -- presotto
451 */
452 ctlr = uart->regs;
453 for(i = 0; i < 128; i++){
454 if(!(csr8r(ctlr, Lsr) & Thre))
455 break;
456 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
457 break;
458 outb(ctlr->io+Thr, *(uart->op++));
459 }
460 }
461
462 static void
i8250interrupt(Ureg *,void * arg)463 i8250interrupt(Ureg*, void* arg)
464 {
465 Ctlr *ctlr;
466 Uart *uart;
467 int iir, lsr, old, r;
468
469 uart = arg;
470
471 ctlr = uart->regs;
472 for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
473 switch(iir & IirMASK){
474 case Ims: /* Ms interrupt */
475 r = csr8r(ctlr, Msr);
476 if(r & Dcts){
477 ilock(&uart->tlock);
478 old = uart->cts;
479 uart->cts = r & Cts;
480 if(old == 0 && uart->cts)
481 uart->ctsbackoff = 2;
482 iunlock(&uart->tlock);
483 }
484 if(r & Ddsr){
485 old = r & Dsr;
486 if(uart->hup_dsr && uart->dsr && !old)
487 uart->dohup = 1;
488 uart->dsr = old;
489 }
490 if(r & Ddcd){
491 old = r & Dcd;
492 if(uart->hup_dcd && uart->dcd && !old)
493 uart->dohup = 1;
494 uart->dcd = old;
495 }
496 break;
497 case Ithre: /* Thr Empty */
498 uartkick(uart);
499 break;
500 case Irda: /* Received Data Available */
501 case Irls: /* Receiver Line Status */
502 case Ictoi: /* Character Time-out Indication */
503 /*
504 * Consume any received data.
505 * If the received byte came in with a break,
506 * parity or framing error, throw it away;
507 * overrun is an indication that something has
508 * already been tossed.
509 */
510 while((lsr = csr8r(ctlr, Lsr)) & Dr){
511 if(lsr & (FIFOerr|Oe))
512 uart->oerr++;
513 if(lsr & Pe)
514 uart->perr++;
515 if(lsr & Fe)
516 uart->ferr++;
517 r = csr8r(ctlr, Rbr);
518 if(!(lsr & (Bi|Fe|Pe)))
519 uartrecv(uart, r);
520 }
521 break;
522
523 default:
524 iprint("weird uart interrupt 0x%2.2uX\n", iir);
525 break;
526 }
527 }
528 }
529
530 static void
i8250disable(Uart * uart)531 i8250disable(Uart* uart)
532 {
533 Ctlr *ctlr;
534
535 /*
536 * Turn off DTR and RTS, disable interrupts and fifos.
537 */
538 (*uart->phys->dtr)(uart, 0);
539 (*uart->phys->rts)(uart, 0);
540 (*uart->phys->fifo)(uart, 0);
541
542 ctlr = uart->regs;
543 ctlr->sticky[Ier] = 0;
544 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
545
546 if(ctlr->iena != 0){
547 if(intrdisable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name) == 0)
548 ctlr->iena = 0;
549 }
550 }
551
552 static void
i8250enable(Uart * uart,int ie)553 i8250enable(Uart* uart, int ie)
554 {
555 Ctlr *ctlr;
556
557 ctlr = uart->regs;
558
559 /*
560 * Check if there is a FIFO.
561 * Changing the FIFOena bit in Fcr flushes data
562 * from both receive and transmit FIFOs; there's
563 * no easy way to guarantee not losing data on
564 * the receive side, but it's possible to wait until
565 * the transmitter is really empty.
566 * Also, reading the Iir outwith i8250interrupt()
567 * can be dangerous, but this should only happen
568 * once before interrupts are enabled.
569 */
570 ilock(ctlr);
571 if(!ctlr->checkfifo){
572 /*
573 * Wait until the transmitter is really empty.
574 */
575 while(!(csr8r(ctlr, Lsr) & Temt))
576 ;
577 csr8w(ctlr, Fcr, FIFOena);
578 if(csr8r(ctlr, Iir) & Ifena)
579 ctlr->hasfifo = 1;
580 csr8w(ctlr, Fcr, 0);
581 ctlr->checkfifo = 1;
582 }
583 iunlock(ctlr);
584
585 /*
586 * Enable interrupts and turn on DTR and RTS.
587 * Be careful if this is called to set up a polled serial line
588 * early on not to try to enable interrupts as interrupt-
589 * -enabling mechanisms might not be set up yet.
590 */
591 if(ie){
592 if(ctlr->iena == 0){
593 intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
594 ctlr->iena = 1;
595 }
596 ctlr->sticky[Ier] = Ethre|Erda;
597 ctlr->sticky[Mcr] |= Ie;
598 }
599 else{
600 ctlr->sticky[Ier] = 0;
601 ctlr->sticky[Mcr] = 0;
602 }
603 csr8w(ctlr, Ier, ctlr->sticky[Ier]);
604 csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);
605
606 (*uart->phys->dtr)(uart, 1);
607 (*uart->phys->rts)(uart, 1);
608
609 /*
610 * During startup, the i8259 interrupt controller is reset.
611 * This may result in a lost interrupt from the i8250 uart.
612 * The i8250 thinks the interrupt is still outstanding and does not
613 * generate any further interrupts. The workaround is to call the
614 * interrupt handler to clear any pending interrupt events.
615 * Note: this must be done after setting Ier.
616 */
617 if(ie)
618 i8250interrupt(nil, uart);
619 }
620
621 void*
i8250alloc(int io,int irq,int tbdf)622 i8250alloc(int io, int irq, int tbdf)
623 {
624 Ctlr *ctlr;
625
626 if((ctlr = malloc(sizeof(Ctlr))) != nil){
627 ctlr->io = io;
628 ctlr->irq = irq;
629 ctlr->tbdf = tbdf;
630 }
631
632 return ctlr;
633 }
634
635 static Uart*
i8250pnp(void)636 i8250pnp(void)
637 {
638 return i8250uart;
639 }
640
641 static int
i8250getc(Uart * uart)642 i8250getc(Uart *uart)
643 {
644 Ctlr *ctlr;
645
646 ctlr = uart->regs;
647 while(!(csr8r(ctlr, Lsr)&Dr))
648 delay(1);
649 return csr8r(ctlr, Rbr);
650 }
651
652 static void
i8250putc(Uart * uart,int c)653 i8250putc(Uart *uart, int c)
654 {
655 int i;
656 Ctlr *ctlr;
657
658 ctlr = uart->regs;
659 for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
660 delay(1);
661 outb(ctlr->io+Thr, c);
662 for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
663 delay(1);
664 }
665
666 PhysUart i8250physuart = {
667 .name = "i8250",
668 .pnp = i8250pnp,
669 .enable = i8250enable,
670 .disable = i8250disable,
671 .kick = i8250kick,
672 .dobreak = i8250break,
673 .baud = i8250baud,
674 .bits = i8250bits,
675 .stop = i8250stop,
676 .parity = i8250parity,
677 .modemctl = i8250modemctl,
678 .rts = i8250rts,
679 .dtr = i8250dtr,
680 .status = i8250status,
681 .fifo = i8250fifo,
682 .getc = i8250getc,
683 .putc = i8250putc,
684 };
685
686 void
i8250config(char * p)687 i8250config(char *p)
688 {
689 Uart *uart;
690 int n;
691 char *cmd;
692
693 if(p == nil)
694 return;
695 n = strtoul(p, &cmd, 0);
696 if(p == cmd)
697 return;
698 switch(n){
699 default:
700 return;
701 case 0:
702 uart = &i8250uart[0];
703 break;
704 case 1:
705 uart = &i8250uart[1];
706 break;
707 }
708
709 if(!uart->enabled)
710 (*uart->phys->enable)(uart, 0);
711 uartctl(uart, "b9600 l8 pn s1");
712 if(*cmd != '\0')
713 uartctl(uart, cmd);
714
715 consuart = uart;
716 uart->console = 1;
717 }
718
719 void
i8250console(void)720 i8250console(void)
721 {
722 i8250config(getconf("console"));
723 }
724
725 void
i8250mouse(char * which,int (* putc)(Queue *,int),int setb1200)726 i8250mouse(char* which, int (*putc)(Queue*, int), int setb1200)
727 {
728 char *p;
729 int port;
730
731 port = strtol(which, &p, 0);
732 if(p == which || port < 0 || port > 1)
733 error(Ebadarg);
734 uartmouse(&i8250uart[port], putc, setb1200);
735 }
736
737 void
i8250setmouseputc(char * which,int (* putc)(Queue *,int))738 i8250setmouseputc(char* which, int (*putc)(Queue*, int))
739 {
740 char *p;
741 int port;
742
743 port = strtol(which, &p, 0);
744 if(p == which || port < 0 || port > 1)
745 error(Ebadarg);
746 uartsetmouseputc(&i8250uart[port], putc);
747
748 }
749