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