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