xref: /plan9/sys/src/9/pc/uarti8250.c (revision 3d8d68dd17293a991eef0262bb22083c92b38140)
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