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