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