1 /*
2 * 8250-like UART
3 */
4
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11
12 enum {
13 CONSOLE = 0, /* first uart */
14 Pollstuckoutput = 1,
15 };
16
17 enum { /* registers */
18 Rbr = 0, /* Receiver Buffer (RO) */
19 Thr = 0, /* Transmitter Holding (WO) */
20 Ier = 1, /* Interrupt Enable */
21 Iir = 2, /* Interrupt Identification (RO) */
22 Fcr = 2, /* FIFO Control (WO) */
23 Lcr = 3, /* Line Control */
24 Mcr = 4, /* Modem Control */
25 Lsr = 5, /* Line Status */
26 Msr = 6, /* Modem Status */
27
28 Scr = 7, /* Scratch Pad */
29 // Mdr = 8, /* Mode Def'n (omap rw) */
30 Usr = 31, /* Uart Status Register */
31 Stickyend,
32
33 Dll = 0, /* Divisor Latch LSB */
34 Dlm = 1, /* Divisor Latch MSB */
35 };
36
37 enum { /* Usr */
38 Busy = 0x01,
39 };
40
41 enum { /* Ier */
42 Erda = 0x01, /* Enable Received Data Available */
43 Ethre = 0x02, /* Enable Thr Empty */
44 Erls = 0x04, /* Enable Receiver Line Status */
45 Ems = 0x08, /* Enable Modem Status */
46 };
47
48 enum { /* Iir */
49 Ims = 0x00, /* Ms interrupt */
50 Ip = 0x01, /* Interrupt Pending (not) */
51 Ithre = 0x02, /* Thr Empty */
52 Irda = 0x04, /* Received Data Available */
53 Irls = 0x06, /* Receiver Line Status */
54 Ictoi = 0x0C, /* Character Time-out Indication */
55 IirMASK = 0x3F,
56 Ifena = 0xC0, /* FIFOs enabled */
57 };
58
59 enum { /* Fcr */
60 FIFOena = 0x01, /* FIFO enable */
61 FIFOrclr = 0x02, /* clear Rx FIFO */
62 FIFOtclr = 0x04, /* clear Tx FIFO */
63 // FIFOdma = 0x08,
64 FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */
65 FIFO4 = 0x40, /* 4 bytes */
66 FIFO8 = 0x80, /* 8 bytes */
67 FIFO14 = 0xC0, /* 14 bytes */
68 };
69
70 enum { /* Lcr */
71 Wls5 = 0x00, /* Word Length Select 5 bits/byte */
72 Wls6 = 0x01, /* 6 bits/byte */
73 Wls7 = 0x02, /* 7 bits/byte */
74 Wls8 = 0x03, /* 8 bits/byte */
75 WlsMASK = 0x03,
76 Stb = 0x04, /* 2 stop bits */
77 Pen = 0x08, /* Parity Enable */
78 Eps = 0x10, /* Even Parity Select */
79 Stp = 0x20, /* Stick Parity */
80 Brk = 0x40, /* Break */
81 Dlab = 0x80, /* Divisor Latch Access Bit */
82 };
83
84 enum { /* Mcr */
85 Dtr = 0x01, /* Data Terminal Ready */
86 Rts = 0x02, /* Ready To Send */
87 Out1 = 0x04, /* no longer in use */
88 Ie = 0x08, /* IRQ Enable (cd_sts_ch on omap) */
89 Dm = 0x10, /* Diagnostic Mode loopback */
90 };
91
92 enum { /* Lsr */
93 Dr = 0x01, /* Data Ready */
94 Oe = 0x02, /* Overrun Error */
95 Pe = 0x04, /* Parity Error */
96 Fe = 0x08, /* Framing Error */
97 Bi = 0x10, /* Break Interrupt */
98 Thre = 0x20, /* Thr Empty */
99 Temt = 0x40, /* Transmitter Empty */
100 FIFOerr = 0x80, /* error in receiver FIFO */
101 };
102
103 enum { /* Msr */
104 Dcts = 0x01, /* Delta Cts */
105 Ddsr = 0x02, /* Delta Dsr */
106 Teri = 0x04, /* Trailing Edge of Ri */
107 Ddcd = 0x08, /* Delta Dcd */
108 Cts = 0x10, /* Clear To Send */
109 Dsr = 0x20, /* Data Set Ready */
110 Ri = 0x40, /* Ring Indicator */
111 Dcd = 0x80, /* Carrier Detect */
112 };
113
114 enum { /* Mdr */
115 Modemask = 7,
116 Modeuart = 0,
117 };
118
119
120 typedef struct Ctlr {
121 u32int* io;
122 int irq;
123 int tbdf;
124 int iena;
125 int poll;
126
127 uchar sticky[Stickyend];
128
129 Lock;
130 int hasfifo;
131 int checkfifo;
132 int fena;
133 } Ctlr;
134
135 extern PhysUart i8250physuart;
136
137 static Ctlr i8250ctlr[] = {
138 { .io = (u32int*)PHYSCONS,
139 .irq = ILduart0,
140 .tbdf = -1,
141 .poll = 0, },
142 };
143
144 static Uart i8250uart[] = {
145 { .regs = &i8250ctlr[0],
146 .name = "cons",
147 .freq = 3686000, /* Not used, we use the global i8250freq */
148 .phys = &i8250physuart,
149 .console= 1,
150 .next = nil, },
151 };
152
153 #define csr8r(c, r) ((c)->io[r])
154 #define csr8w(c, r, v) ((c)->io[r] = (uchar)((c)->sticky[r] | (v)))
155 #define csr8o(c, r, v) ((c)->io[r] = (uchar)(v))
156
157 static long
i8250status(Uart * uart,void * buf,long n,long offset)158 i8250status(Uart* uart, void* buf, long n, long offset)
159 {
160 char *p;
161 Ctlr *ctlr;
162 uchar ier, lcr, mcr, msr;
163
164 ctlr = uart->regs;
165 p = smalloc(READSTR);
166 mcr = ctlr->sticky[Mcr];
167 msr = csr8r(ctlr, Msr);
168 ier = ctlr->sticky[Ier];
169 lcr = ctlr->sticky[Lcr];
170 snprint(p, READSTR,
171 "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
172 "dev(%d) type(%d) framing(%d) overruns(%d) "
173 "berr(%d) serr(%d)%s%s%s%s\n",
174
175 uart->baud,
176 uart->hup_dcd,
177 (msr & Dsr) != 0,
178 uart->hup_dsr,
179 (lcr & WlsMASK) + 5,
180 (ier & Ems) != 0,
181 (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
182 (mcr & Rts) != 0,
183 (lcr & Stb) ? 2: 1,
184 ctlr->fena,
185
186 uart->dev,
187 uart->type,
188 uart->ferr,
189 uart->oerr,
190 uart->berr,
191 uart->serr,
192 (msr & Cts) ? " cts": "",
193 (msr & Dsr) ? " dsr": "",
194 (msr & Dcd) ? " dcd": "",
195 (msr & Ri) ? " ring": ""
196 );
197 n = readstr(offset, buf, n, p);
198 free(p);
199
200 return n;
201 }
202
203 static void
i8250fifo(Uart * uart,int level)204 i8250fifo(Uart* uart, int level)
205 {
206 Ctlr *ctlr;
207
208 ctlr = uart->regs;
209 if(ctlr->hasfifo == 0)
210 return;
211
212 /*
213 * Changing the FIFOena bit in Fcr flushes data
214 * from both receive and transmit FIFOs; there's
215 * no easy way to guarantee not losing data on
216 * the receive side, but it's possible to wait until
217 * the transmitter is really empty.
218 */
219 ilock(ctlr);
220 while(!(csr8r(ctlr, Lsr) & Temt))
221 ;
222
223 /*
224 * Set the trigger level, default is the max.
225 * value.
226 * Some UARTs require FIFOena to be set before
227 * other bits can take effect, so set it twice.
228 */
229 ctlr->fena = level;
230 switch(level){
231 case 0:
232 break;
233 case 1:
234 level = FIFO1|FIFOena;
235 break;
236 case 4:
237 level = FIFO4|FIFOena;
238 break;
239 case 8:
240 level = FIFO8|FIFOena;
241 break;
242 default:
243 level = FIFO14|FIFOena;
244 break;
245 }
246 csr8w(ctlr, Fcr, level);
247 csr8w(ctlr, Fcr, level);
248 iunlock(ctlr);
249 }
250
251 static void
i8250dtr(Uart * uart,int on)252 i8250dtr(Uart* uart, int on)
253 {
254 Ctlr *ctlr;
255
256 /*
257 * Toggle DTR.
258 */
259 ctlr = uart->regs;
260 if(on)
261 ctlr->sticky[Mcr] |= Dtr;
262 else
263 ctlr->sticky[Mcr] &= ~Dtr;
264 csr8w(ctlr, Mcr, 0);
265 }
266
267 static void
i8250rts(Uart * uart,int on)268 i8250rts(Uart* uart, int on)
269 {
270 Ctlr *ctlr;
271
272 /*
273 * Toggle RTS.
274 */
275 ctlr = uart->regs;
276 if(on)
277 ctlr->sticky[Mcr] |= Rts;
278 else
279 ctlr->sticky[Mcr] &= ~Rts;
280 csr8w(ctlr, Mcr, 0);
281 }
282
283 static void
i8250modemctl(Uart * uart,int on)284 i8250modemctl(Uart* uart, int on)
285 {
286 Ctlr *ctlr;
287
288 ctlr = uart->regs;
289 ilock(&uart->tlock);
290 if(on){
291 ctlr->sticky[Ier] |= Ems;
292 csr8w(ctlr, Ier, 0);
293 uart->modem = 1;
294 uart->cts = csr8r(ctlr, Msr) & Cts;
295 }
296 else{
297 ctlr->sticky[Ier] &= ~Ems;
298 csr8w(ctlr, Ier, 0);
299 uart->modem = 0;
300 uart->cts = 1;
301 }
302 iunlock(&uart->tlock);
303
304 /* modem needs fifo */
305 (*uart->phys->fifo)(uart, on);
306 }
307
308 static int
i8250parity(Uart * uart,int parity)309 i8250parity(Uart* uart, int parity)
310 {
311 int lcr;
312 Ctlr *ctlr;
313
314 ctlr = uart->regs;
315 lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
316
317 switch(parity){
318 case 'e':
319 lcr |= Eps|Pen;
320 break;
321 case 'o':
322 lcr |= Pen;
323 break;
324 case 'n':
325 break;
326 default:
327 return -1;
328 }
329 ctlr->sticky[Lcr] = lcr;
330 csr8w(ctlr, Lcr, 0);
331
332 uart->parity = parity;
333
334 return 0;
335 }
336
337 static int
i8250stop(Uart * uart,int stop)338 i8250stop(Uart* uart, int stop)
339 {
340 int lcr;
341 Ctlr *ctlr;
342
343 ctlr = uart->regs;
344 lcr = ctlr->sticky[Lcr] & ~Stb;
345
346 switch(stop){
347 case 1:
348 break;
349 case 2:
350 lcr |= Stb;
351 break;
352 default:
353 return -1;
354 }
355 ctlr->sticky[Lcr] = lcr;
356 csr8w(ctlr, Lcr, 0);
357
358 uart->stop = stop;
359
360 return 0;
361 }
362
363 static int
i8250bits(Uart * uart,int bits)364 i8250bits(Uart* uart, int bits)
365 {
366 int lcr;
367 Ctlr *ctlr;
368
369 ctlr = uart->regs;
370 lcr = ctlr->sticky[Lcr] & ~WlsMASK;
371
372 switch(bits){
373 case 5:
374 lcr |= Wls5;
375 break;
376 case 6:
377 lcr |= Wls6;
378 break;
379 case 7:
380 lcr |= Wls7;
381 break;
382 case 8:
383 lcr |= Wls8;
384 break;
385 default:
386 return -1;
387 }
388 ctlr->sticky[Lcr] = lcr;
389 csr8w(ctlr, Lcr, 0);
390
391 uart->bits = bits;
392
393 return 0;
394 }
395
396 static int
i8250baud(Uart * uart,int baud)397 i8250baud(Uart* uart, int baud)
398 {
399 #ifdef notdef /* don't change the speed */
400 ulong bgc;
401 Ctlr *ctlr;
402 extern int i8250freq; /* In the config file */
403
404 /*
405 * Set the Baud rate by calculating and setting the Baud rate
406 * Generator Constant. This will work with fairly non-standard
407 * Baud rates.
408 */
409 if(i8250freq == 0 || baud <= 0)
410 return -1;
411 bgc = (i8250freq+8*baud-1)/(16*baud);
412
413 ctlr = uart->regs;
414 while(csr8r(ctlr, Usr) & Busy)
415 delay(1);
416 csr8w(ctlr, Lcr, Dlab); /* begin kludge */
417 csr8o(ctlr, Dlm, bgc>>8);
418 csr8o(ctlr, Dll, bgc);
419 csr8w(ctlr, Lcr, 0);
420 #endif
421 uart->baud = baud;
422 return 0;
423 }
424
425 static void
i8250break(Uart * uart,int ms)426 i8250break(Uart* uart, int ms)
427 {
428 Ctlr *ctlr;
429
430 if (up == nil)
431 panic("i8250break: nil up");
432 /*
433 * Send a break.
434 */
435 if(ms <= 0)
436 ms = 200;
437
438 ctlr = uart->regs;
439 csr8w(ctlr, Lcr, Brk);
440 tsleep(&up->sleep, return0, 0, ms);
441 csr8w(ctlr, Lcr, 0);
442 }
443
444 static void
emptyoutstage(Uart * uart,int n)445 emptyoutstage(Uart *uart, int n)
446 {
447 _uartputs((char *)uart->op, n);
448 uart->op = uart->oe = uart->ostage;
449 }
450
451 static void
i8250kick(Uart * uart)452 i8250kick(Uart* uart)
453 {
454 int i;
455 Ctlr *ctlr;
456
457 if(/* uart->cts == 0 || */ uart->blocked)
458 return;
459
460 if(!normalprint) { /* early */
461 if (uart->op < uart->oe)
462 emptyoutstage(uart, uart->oe - uart->op);
463 while ((i = uartstageoutput(uart)) > 0)
464 emptyoutstage(uart, i);
465 return;
466 }
467
468 /* nothing more to send? then disable xmit intr */
469 ctlr = uart->regs;
470 if (uart->op >= uart->oe && qlen(uart->oq) == 0 &&
471 (1 || csr8r(ctlr, Lsr) & Temt)) { /* could try ignoring Temt */
472 ctlr->sticky[Ier] &= ~Ethre;
473 csr8w(ctlr, Ier, 0);
474 return;
475 }
476
477 /*
478 * 128 here is an arbitrary limit to make sure
479 * we don't stay in this loop too long. If the
480 * chip's output queue is longer than 128, too
481 * bad -- presotto
482 */
483 for(i = 0; i < 128; i++){
484 if(!(csr8r(ctlr, Lsr) & Thre))
485 break;
486 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
487 break;
488 csr8o(ctlr, Thr, *uart->op++); /* start tx */
489 ctlr->sticky[Ier] |= Ethre;
490 csr8w(ctlr, Ier, 0); /* intr when done */
491 }
492 }
493
494 void
serialkick(void)495 serialkick(void)
496 {
497 uartkick(&i8250uart[CONSOLE]);
498 }
499
500 static Lock i8250intrlock;
501
502 static void
i8250interrupt(void * arg)503 i8250interrupt(void* arg)
504 {
505 Ctlr *ctlr;
506 Uart *uart;
507 int iir, lsr, old, r;
508
509 uart = arg;
510 ctlr = uart->regs;
511 ilock(&i8250intrlock);
512
513 /* force Ethre on. don't know why this is needed, but it is. */
514 ctlr->sticky[Ier] |= Ethre;
515 csr8w(ctlr, Ier, 0);
516 /* this is probably optional. maybe it helps fast input. */
517 ctlr->sticky[Mcr] |= Ie;
518 csr8w(ctlr, Mcr, 0);
519
520 for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
521 switch(iir & IirMASK){
522 case Ims: /* Ms interrupt */
523 r = csr8r(ctlr, Msr);
524 if(r & Dcts){
525 ilock(&uart->tlock);
526 old = uart->cts;
527 uart->cts = r & Cts;
528 if(old == 0 && uart->cts)
529 uart->ctsbackoff = 2;
530 iunlock(&uart->tlock);
531 }
532 if(r & Ddsr){
533 old = r & Dsr;
534 if(uart->hup_dsr && uart->dsr && !old)
535 uart->dohup = 1;
536 uart->dsr = old;
537 }
538 if(r & Ddcd){
539 old = r & Dcd;
540 if(uart->hup_dcd && uart->dcd && !old)
541 uart->dohup = 1;
542 uart->dcd = old;
543 }
544 break;
545 case Ithre: /* Thr Empty */
546 uartkick(uart);
547 break;
548 case Irda: /* Received Data Available */
549 case Irls: /* Receiver Line Status */
550 case Ictoi: /* Character Time-out Indication */
551 /*
552 * Consume any received data.
553 * If the received byte came in with a break,
554 * parity or framing error, throw it away;
555 * overrun is an indication that something has
556 * already been tossed.
557 */
558 while((lsr = csr8r(ctlr, Lsr)) & Dr){
559 if(lsr & (FIFOerr|Oe))
560 uart->oerr++;
561 if(lsr & Pe)
562 uart->perr++;
563 if(lsr & Fe)
564 uart->ferr++;
565 r = csr8r(ctlr, Rbr);
566 if(!(lsr & (Bi|Fe|Pe)))
567 uartrecv(uart, r);
568 }
569 break;
570
571 default:
572 iprint("weird uart interrupt type %#2.2uX\n", iir);
573 break;
574 }
575 }
576 iunlock(&i8250intrlock);
577 }
578
579 static void
i8250disable(Uart * uart)580 i8250disable(Uart* uart)
581 {
582 Ctlr *ctlr;
583
584 /*
585 * Turn off DTR and RTS, disable interrupts and fifos.
586 */
587 (*uart->phys->dtr)(uart, 0);
588 (*uart->phys->rts)(uart, 0);
589 (*uart->phys->fifo)(uart, 0);
590
591 ctlr = uart->regs;
592 ctlr->sticky[Ier] = 0;
593 csr8w(ctlr, Ier, 0);
594
595 if(ctlr->iena != 0){
596 /* bad idea if the IRQ is shared */
597 // introff(1 << (ILshift + ctlr->irq));
598 ctlr->iena = 0;
599 }
600 }
601
602 static void
i8250clock(void)603 i8250clock(void)
604 {
605 i8250interrupt(&i8250uart[CONSOLE]);
606 }
607
608 static void
i8250enable(Uart * uart,int ie)609 i8250enable(Uart* uart, int ie)
610 {
611 Ctlr *ctlr;
612
613 ctlr = uart->regs;
614 ctlr->sticky[Lcr] = Wls8; /* no parity */
615 csr8w(ctlr, Lcr, 0);
616
617 /*
618 * Check if there is a FIFO.
619 * Changing the FIFOena bit in Fcr flushes data
620 * from both receive and transmit FIFOs; there's
621 * no easy way to guarantee not losing data on
622 * the receive side, but it's possible to wait until
623 * the transmitter is really empty.
624 * Also, reading the Iir outwith i8250interrupt()
625 * can be dangerous, but this should only happen
626 * once, before interrupts are enabled.
627 */
628 ilock(ctlr);
629 if(!ctlr->checkfifo){
630 /*
631 * Wait until the transmitter is really empty.
632 */
633 while(!(csr8r(ctlr, Lsr) & Temt))
634 ;
635 csr8w(ctlr, Fcr, FIFOena);
636 if(csr8r(ctlr, Iir) & Ifena)
637 ctlr->hasfifo = 1;
638 csr8w(ctlr, Fcr, 0);
639 ctlr->checkfifo = 1;
640 }
641 iunlock(ctlr);
642
643 /*
644 * Enable interrupts and turn on DTR and RTS.
645 * Be careful if this is called to set up a polled serial line
646 * early on not to try to enable interrupts as interrupt-
647 * -enabling mechanisms might not be set up yet.
648 */
649 if(ie){
650 if(ctlr->iena == 0 && !ctlr->poll){
651 intrenable(ctlr->irq, i8250interrupt, uart);
652 ctlr->iena = 1;
653 }
654 ctlr->sticky[Ier] = Erda;
655 ctlr->sticky[Mcr] |= Ie;
656 }
657 else{
658 ctlr->sticky[Ier] = 0;
659 ctlr->sticky[Mcr] = 0;
660 }
661 csr8w(ctlr, Ier, 0);
662 csr8w(ctlr, Mcr, 0);
663
664 (*uart->phys->dtr)(uart, 1);
665 (*uart->phys->rts)(uart, 1);
666
667 /*
668 * During startup, the i8259 interrupt controller is reset.
669 * This may result in a lost interrupt from the i8250 uart.
670 * The i8250 thinks the interrupt is still outstanding and does not
671 * generate any further interrupts. The workaround is to call the
672 * interrupt handler to clear any pending interrupt events.
673 * Note: this must be done after setting Ier.
674 */
675 if(ie) {
676 i8250interrupt(uart);
677 /*
678 * force output to resume if stuck. shouldn't be needed.
679 */
680 if (Pollstuckoutput)
681 addclock0link(i8250clock, 10);
682 }
683 }
684
685 static Uart*
i8250pnp(void)686 i8250pnp(void)
687 {
688 return i8250uart;
689 }
690
691 static int
i8250getc(Uart * uart)692 i8250getc(Uart* uart)
693 {
694 Ctlr *ctlr;
695
696 ctlr = uart->regs;
697 while(!(csr8r(ctlr, Lsr) & Dr))
698 delay(1);
699 return csr8r(ctlr, Rbr);
700 }
701
702 static void
i8250putc(Uart * uart,int c)703 i8250putc(Uart* uart, int c)
704 {
705 int i, s;
706 Ctlr *ctlr;
707
708 if (!normalprint) { /* too early; use brute force */
709 s = splhi();
710 while (!(((ulong *)PHYSCONS)[Lsr] & Thre))
711 ;
712 ((ulong *)PHYSCONS)[Thr] = (uchar)c;
713 splx(s);
714 return;
715 }
716
717 ctlr = uart->regs;
718 s = splhi();
719 for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 200; i++)
720 delay(5);
721 csr8o(ctlr, Thr, c);
722 for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 200; i++)
723 delay(5);
724 splx(s);
725 }
726
727 void
serialputc(int c)728 serialputc(int c)
729 {
730 i8250putc(&i8250uart[CONSOLE], c);
731 }
732
733 void
serialputs(char * s,int n)734 serialputs(char* s, int n)
735 {
736 _uartputs(s, n);
737 }
738
739 #ifdef PLAN9K
740 static void
i8250poll(Uart * uart)741 i8250poll(Uart* uart)
742 {
743 Ctlr *ctlr;
744
745 /*
746 * If PhysUart has a non-nil .poll member, this
747 * routine will be called from the uartclock timer.
748 * If the Ctlr .poll member is non-zero, when the
749 * Uart is enabled interrupts will not be enabled
750 * and the result is polled input and output.
751 * Not very useful here, but ports to new hardware
752 * or simulators can use this to get serial I/O
753 * without setting up the interrupt mechanism.
754 */
755 ctlr = uart->regs;
756 if(ctlr->iena || !ctlr->poll)
757 return;
758 i8250interrupt(uart);
759 }
760 #endif
761
762 PhysUart i8250physuart = {
763 .name = "i8250",
764 .pnp = i8250pnp,
765 .enable = i8250enable,
766 .disable = i8250disable,
767 .kick = i8250kick,
768 .dobreak = i8250break,
769 .baud = i8250baud,
770 .bits = i8250bits,
771 .stop = i8250stop,
772 .parity = i8250parity,
773 .modemctl = i8250modemctl,
774 .rts = i8250rts,
775 .dtr = i8250dtr,
776 .status = i8250status,
777 .fifo = i8250fifo,
778 .getc = i8250getc,
779 .putc = i8250putc,
780 #ifdef PLAN9K
781 .poll = i8250poll,
782 #endif
783 };
784
785 static void
i8250dumpregs(Ctlr * ctlr)786 i8250dumpregs(Ctlr* ctlr)
787 {
788 int dlm, dll;
789 int _uartprint(char*, ...);
790
791 csr8w(ctlr, Lcr, Dlab);
792 dlm = csr8r(ctlr, Dlm);
793 dll = csr8r(ctlr, Dll);
794 csr8w(ctlr, Lcr, 0);
795
796 _uartprint("dlm %#ux dll %#ux\n", dlm, dll);
797 }
798
799 Uart* uartenable(Uart *p);
800
801 /* must call this from a process's context */
802 int
i8250console(void)803 i8250console(void)
804 {
805 Uart *uart;
806
807 if (up == nil)
808 return -1; /* too early */
809
810 uart = &i8250uart[CONSOLE];
811 if(uartenable(uart) != nil && uart->console){
812 kbdq = uart->iq;
813 assert(kbdq);
814 serialoq = uart->oq;
815 assert(serialoq);
816 uart->putc = kbdcr2nl;
817 uart->opens++;
818 consuart = uart;
819 /* up wasn't set when chandevreset ran, so enable it now */
820 i8250disable(uart);
821 i8250enable(uart, 1);
822 }
823 uartctl(uart, "b115200 l8 pn m0 s1 i128 w100");
824 return 0;
825 }
826
827 void
_uartputs(char * s,int n)828 _uartputs(char* s, int n)
829 {
830 char *e;
831
832 for(e = s+n; s < e; s++){
833 if(*s == '\n')
834 i8250putc(&i8250uart[CONSOLE], '\r');
835 i8250putc(&i8250uart[CONSOLE], *s);
836 }
837 }
838
839 int
_uartprint(char * fmt,...)840 _uartprint(char* fmt, ...)
841 {
842 int n;
843 va_list arg;
844 char buf[PRINTSIZE];
845
846 va_start(arg, fmt);
847 n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
848 va_end(arg);
849 _uartputs(buf, n);
850
851 return n;
852 }
853
854 void (*lprint)(char *, int) = _uartputs;
855