xref: /inferno-os/os/pxa/devuart.c (revision 5d0c4cf3fc288434c41cba52dd998ab1d7375a7b)
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 #include	"../port/netif.h"
10 
11 /*
12  *  Driver for the uart.
13  *	TO DO: replace by uartpxa.c
14  */
15 enum
16 {
17 	/*
18 	 *  register numbers
19 	 */
20 	Data=	0,		/* xmit/rcv buffer */
21 	Iena=	1,		/* interrupt enable */
22 	 Ircv=	(1<<0),		/*  for char rcv'd */
23 	 Ixmt=	(1<<1),		/*  for xmit buffer empty */
24 	 Irstat=(1<<2),		/*  for change in rcv'er status */
25 	 Imstat=(1<<3),		/*  for change in modem status */
26 	 Rtoie=	1<<4,	/* character timeout indication */
27 	 Nrze=	1<<5,	/* NRZ encoding enabled */
28 	 Uue=	1<<6,	/* Uart unit enabled */
29 	 Dmae=	1<<7,	/* DMA requests enabled */
30 	Istat=	2,		/* interrupt flag (read) */
31 	 Ipend=	1,		/* interrupt pending (not) */
32 	 Fenabd=(3<<6),   		/*  on if fifo's enabled */
33 	Fifoctl=2,		/* fifo control (write) */
34 	 Fena=	(1<<0),		/*  enable xmit/rcv fifos */
35 	 Fdma=	(1<<3),		/* dma on */
36 	 Ftrig=	(1<<6),		/*  trigger after 4 input characters */
37 	 Fclear=(3<<1),		/*  clear xmit & rcv fifos */
38 	Format=	3,		/* byte format */
39 	 Bits8=	(3<<0),		/*  8 bits/byte */
40 	 Stop2=	(1<<2),		/*  2 stop bits */
41 	 Pena=	(1<<3),		/*  generate parity */
42 	 Peven=	(1<<4),		/*  even parity */
43 	 Pforce=(1<<5),		/*  force parity */
44 	 Break=	(1<<6),		/*  generate a break */
45 	 Dra=	(1<<7),		/*  address the divisor */
46 	Mctl=	4,		/* modem control */
47 	 Dtr=	(1<<0),		/*  data terminal ready */
48 	 Rts=	(1<<1),		/*  request to send */
49 	 Ri=	(1<<2),		/*  ring */
50 	 Inton=	(1<<3),		/*  turn on interrupts */
51 	 Loop=	(1<<4),		/*  loop back */
52 	Lstat=	5,		/* line status */
53 	 Inready=(1<<0),	/*  receive buffer full */
54 	 Oerror=(1<<1),		/*  receiver overrun */
55 	 Perror=(1<<2),		/*  receiver parity error */
56 	 Ferror=(1<<3),		/*  rcv framing error */
57 	 Berror=(1<<4),		/* break alarm */
58 	 Outready=(1<<5),	/*  output buffer full */
59 	Mstat=	6,		/* modem status */
60 	 Ctsc=	(1<<0),		/*  clear to send changed */
61 	 Dsrc=	(1<<1),		/*  data set ready changed */
62 	 Rire=	(1<<2),		/*  rising edge of ring indicator */
63 	 Dcdc=	(1<<3),		/*  data carrier detect changed */
64 	 Cts=	(1<<4),		/*  complement of clear to send line */
65 	 Dsr=	(1<<5),		/*  complement of data set ready line */
66 	 Ringl=	(1<<6),		/*  complement of ring indicator line */
67 	 Dcd=	(1<<7),		/*  complement of data carrier detect line */
68 	Scratch=7,		/* scratchpad */
69 	Dlsb=	0,		/* divisor lsb */
70 	Dmsb=	1,		/* divisor msb */
71 
72 	CTLS= 023,
73 	CTLQ= 021,
74 
75 	Stagesize= 1024,
76 	Nuart=	4,		/* max per machine */
77 };
78 
79 typedef struct Uart Uart;
80 struct Uart
81 {
82 	QLock;
83 	int	opens;
84 
85 	int	enabled;
86 	Uart	*elist;			/* next enabled interface */
87 	char	name[KNAMELEN];
88 
89 	ulong	sticky[8];		/* sticky write register values */
90 	void*	regs;
91 	ulong	port;
92 	ulong	freq;			/* clock frequency */
93 	uchar	mask;			/* bits/char */
94 	int	dev;
95 	int	baud;			/* baud rate */
96 
97 	uchar	istat;			/* last istat read */
98 	int	frame;			/* framing errors */
99 	int	overrun;		/* rcvr overruns */
100 
101 	/* buffers */
102 	int	(*putc)(Queue*, int);
103 	Queue	*iq;
104 	Queue	*oq;
105 
106 	Lock	flock;			/* fifo */
107 	uchar	fifoon;			/* fifo's enabled */
108 	uchar	nofifo;			/* earlier chip version with nofifo */
109 
110 	Lock	rlock;			/* receive */
111 	uchar	istage[Stagesize];
112 	uchar	*ip;
113 	uchar	*ie;
114 
115 	int	haveinput;
116 
117 	Lock	tlock;			/* transmit */
118 	uchar	ostage[Stagesize];
119 	uchar	*op;
120 	uchar	*oe;
121 
122 	int	modem;			/* hardware flow control on */
123 	int	xonoff;			/* software flow control on */
124 	int	blocked;
125 	int	cts, dsr, dcd;		/* keep track of modem status */
126 	int	ctsbackoff;
127 	int	hup_dsr, hup_dcd;	/* send hangup upstream? */
128 	int	dohup;
129 
130 	Rendez	r;
131 };
132 
133 static Uart *uart[Nuart];
134 static int nuart;
135 
136 struct Uartalloc {
137 	Lock;
138 	Uart *elist;	/* list of enabled interfaces */
139 } uartalloc;
140 
141 static void uartintr(Uart*);
142 
143 /*
144  *  pick up architecture specific routines and definitions
145  */
146 #include "uart.h"
147 
148 /*
149  *  set the baud rate by calculating and setting the baudrate
150  *  generator constant.  This will work with fairly non-standard
151  *  baud rates.
152  */
153 static void
154 uartsetbaud(Uart *p, int rate)
155 {
156 	ulong brconst;
157 
158 	if(rate <= 0)
159 		return;
160 
161 	p->freq = archuartclock(p->port, rate);
162 	if(p->freq == 0)
163 		return;
164 
165 	brconst = (p->freq+8*rate-1)/(16*rate);
166 
167 	uartwrreg(p, Format, Dra);
168 	uartwr(p, Dmsb, (brconst>>8) & 0xff);
169 	uartwr(p, Dlsb, brconst & 0xff);
170 	uartwrreg(p, Format, 0);
171 
172 	p->baud = rate;
173 }
174 
175 /*
176  * decide if we should hangup when dsr or dcd drops.
177  */
178 static void
179 uartdsrhup(Uart *p, int n)
180 {
181 	p->hup_dsr = n;
182 }
183 
184 static void
185 uartdcdhup(Uart *p, int n)
186 {
187 	p->hup_dcd = n;
188 }
189 
190 static void
191 uartparity(Uart *p, char type)
192 {
193 	switch(type){
194 	case 'e':
195 		p->sticky[Format] |= Pena|Peven;
196 		break;
197 	case 'o':
198 		p->sticky[Format] &= ~Peven;
199 		p->sticky[Format] |= Pena;
200 		break;
201 	default:
202 		p->sticky[Format] &= ~(Pena|Peven);
203 		break;
204 	}
205 	uartwrreg(p, Format, 0);
206 }
207 
208 /*
209  *  set bits/character, default 8
210  */
211 void
212 uartbits(Uart *p, int bits)
213 {
214 	if(bits < 5 || bits > 8)
215 		error(Ebadarg);
216 
217 	p->sticky[Format] &= ~3;
218 	p->sticky[Format] |= bits-5;
219 
220 	uartwrreg(p, Format, 0);
221 }
222 
223 
224 /*
225  *  toggle DTR
226  */
227 void
228 uartdtr(Uart *p, int n)
229 {
230 	if(n)
231 		p->sticky[Mctl] |= Dtr;
232 	else
233 		p->sticky[Mctl] &= ~Dtr;
234 
235 	uartwrreg(p, Mctl, 0);
236 }
237 
238 /*
239  *  toggle RTS
240  */
241 void
242 uartrts(Uart *p, int n)
243 {
244 	if(n)
245 		p->sticky[Mctl] |= Rts;
246 	else
247 		p->sticky[Mctl] &= ~Rts;
248 
249 	uartwrreg(p, Mctl, 0);
250 }
251 
252 /*
253  *  send break
254  */
255 static void
256 uartbreak(Uart *p, int ms)
257 {
258 	if(ms == 0)
259 		ms = 200;
260 
261 	uartwrreg(p, Format, Break);
262 	tsleep(&up->sleep, return0, 0, ms);
263 	uartwrreg(p, Format, 0);
264 }
265 
266 static void
267 uartfifoon(Uart *p)
268 {
269 	ulong i, x;
270 
271 	if(p->nofifo || uartrdreg(p, Istat) & Fenabd)
272 		return;
273 
274 	x = splhi();
275 
276 	/* reset fifos */
277 	p->sticky[Fifoctl] = 0;
278 	uartwrreg(p, Fifoctl, Fclear);
279 
280 	/* empty buffer and interrupt conditions */
281 	for(i = 0; i < 16; i++){
282 		if(uartrdreg(p, Istat)){
283 			/* nothing to do */
284 		}
285 		if(uartrdreg(p, Data)){
286 			/* nothing to do */
287 		}
288 	}
289 
290 	/* turn on fifo */
291 	p->fifoon = 1;
292 	p->sticky[Fifoctl] = Fena|Ftrig;
293 	uartwrreg(p, Fifoctl, 0);
294 	p->istat = uartrdreg(p, Istat);
295 	if((p->istat & Fenabd) == 0) {
296 		/* didn't work, must be an earlier chip type */
297 		p->nofifo = 1;
298 	}
299 
300 	splx(x);
301 }
302 
303 /*
304  *  modem flow control on/off (rts/cts)
305  */
306 static void
307 uartmflow(Uart *p, int n)
308 {
309 	ilock(&p->tlock);
310 	if(n){
311 		p->sticky[Iena] |= Imstat;
312 		uartwrreg(p, Iena, 0);
313 		p->modem = 1;
314 		p->cts = uartrdreg(p, Mstat) & Cts;
315 	} else {
316 		p->sticky[Iena] &= ~Imstat;
317 		uartwrreg(p, Iena, 0);
318 		p->modem = 0;
319 		p->cts = 1;
320 	}
321 	iunlock(&p->tlock);
322 
323 //	ilock(&p->flock);
324 //	if(1)
325 //		/* turn on fifo's */
326 //		uartfifoon(p);
327 //	else {
328 //		/* turn off fifo's */
329 //		p->fifoon = 0;
330 //		p->sticky[Fifoctl] = 0;
331 //		uartwrreg(p, Fifoctl, Fclear);
332 //	}
333 //	iunlock(&p->flock);
334 }
335 
336 /*
337  *  turn on a port's interrupts.  set DTR and RTS
338  */
339 static void
340 uartenable(Uart *p)
341 {
342 	Uart **l;
343 
344 	if(p->enabled)
345 		return;
346 
347 	uartportpower(p, 1);
348 
349 	p->hup_dsr = p->hup_dcd = 0;
350 	p->cts = p->dsr = p->dcd = 0;
351 
352 	/*
353  	 *  turn on interrupts
354 	 */
355 	p->sticky[Iena] = Ircv | Ixmt | Irstat | Uue;
356 	uartwrreg(p, Iena, 0);
357 
358 	/*
359 	 *  turn on DTR and RTS
360 	 */
361 	uartdtr(p, 1);
362 	uartrts(p, 1);
363 
364 	uartfifoon(p);
365 
366 	/*
367 	 *  assume we can send
368 	 */
369 	ilock(&p->tlock);
370 	p->cts = 1;
371 	p->blocked = 0;
372 	iunlock(&p->tlock);
373 
374 	/*
375 	 *  set baud rate to the last used
376 	 */
377 	uartsetbaud(p, p->baud);
378 
379 	lock(&uartalloc);
380 	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
381 		if(*l == p)
382 			break;
383 	}
384 	if(*l == 0){
385 		p->elist = uartalloc.elist;
386 		uartalloc.elist = p;
387 	}
388 	p->enabled = 1;
389 	unlock(&uartalloc);
390 }
391 
392 /*
393  *  turn off a port's interrupts.  reset DTR and RTS
394  */
395 static void
396 uartdisable(Uart *p)
397 {
398 	Uart **l;
399 
400 	/*
401  	 *  turn off interrupts
402 	 */
403 	p->sticky[Iena] = Uue;
404 	uartwrreg(p, Iena, 0);
405 
406 	/*
407 	 *  revert to default settings
408 	 */
409 	p->sticky[Format] = Bits8;
410 	uartwrreg(p, Format, 0);
411 
412 	/*
413 	 *  turn off DTR, RTS, hardware flow control & fifo's
414 	 */
415 	uartdtr(p, 0);
416 	uartrts(p, 0);
417 	uartmflow(p, 0);
418 	ilock(&p->tlock);
419 	p->xonoff = p->blocked = 0;
420 	iunlock(&p->tlock);
421 
422 	uartportpower(p, 0);
423 
424 	lock(&uartalloc);
425 	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
426 		if(*l == p){
427 			*l = p->elist;
428 			break;
429 		}
430 	}
431 	p->enabled = 0;
432 	unlock(&uartalloc);
433 }
434 
435 /*
436  *  put some bytes into the local queue to avoid calling
437  *  qconsume for every character
438  */
439 static int
440 stageoutput(Uart *p)
441 {
442 	int n;
443 
444 	n = qconsume(p->oq, p->ostage, Stagesize);
445 	if(n <= 0)
446 		return 0;
447 	p->op = p->ostage;
448 	p->oe = p->ostage + n;
449 	return n;
450 }
451 
452 /*
453  *  (re)start output
454  */
455 static void
456 uartkick0(Uart *p)
457 {
458 	int i;
459 	if((p->modem && (p->cts == 0)) || p->blocked)
460 		return;
461 
462 	/*
463 	 *  128 here is an arbitrary limit to make sure
464 	 *  we don't stay in this loop too long.  If the
465 	 *  chips output queue is longer than 128, too
466 	 *  bad -- presotto
467 	 */
468 	for(i = 0; i < 128; i++){
469 		if(!(uartrdreg(p, Lstat) & Outready))
470 			break;
471 		if(p->op >= p->oe && stageoutput(p) == 0)
472 			break;
473 		uartwr(p, Data, *p->op++);
474 	}
475 }
476 
477 static void
478 uartkick(void *v)
479 {
480 	Uart *p;
481 
482 	p = v;
483 	ilock(&p->tlock);
484 	uartkick0(p);
485 	iunlock(&p->tlock);
486 }
487 
488 /*
489  *  restart input if it's off
490  */
491 static void
492 uartflow(void *v)
493 {
494 	Uart *p;
495 
496 	p = v;
497 	if(p->modem)
498 		uartrts(p, 1);
499 	ilock(&p->rlock);
500 	p->haveinput = 1;
501 	iunlock(&p->rlock);
502 }
503 
504 /*
505  *  default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts,
506  *  transmit and receive enabled, interrupts disabled.
507  */
508 static void
509 uartsetup0(Uart *p)
510 {
511 	memset(p->sticky, 0, sizeof(p->sticky));
512 	/*
513 	 *  set rate to 9600 baud.
514 	 *  8 bits/character.
515 	 *  1 stop bit.
516 	 *  interrupts enabled.
517 	 */
518 	p->sticky[Format] = Bits8;
519 	uartwrreg(p, Format, 0);
520 	p->sticky[Mctl] |= Inton;
521 	uartwrreg(p, Mctl, 0x0);
522 
523 //	uartsetbaud(p, 9600);
524 	uartsetbaud(p, 38400);
525 
526 	p->iq = qopen(4*1024, 0, uartflow, p);
527 	p->oq = qopen(4*1024, 0, uartkick, p);
528 	if(p->iq == nil || p->oq == nil)
529 		panic("uartsetup0");
530 
531 	p->ip = p->istage;
532 	p->ie = &p->istage[Stagesize];
533 	p->op = p->ostage;
534 	p->oe = p->ostage;
535 }
536 
537 /*
538  *  called by uartinstall() to create a new duart
539  */
540 void
541 uartsetup(ulong port, void *regs, ulong freq, char *name)
542 {
543 	Uart *p;
544 
545 	if(nuart >= Nuart)
546 		return;
547 
548 	p = xalloc(sizeof(Uart));
549 	uart[nuart] = p;
550 	strcpy(p->name, name);
551 	p->dev = nuart;
552 	nuart++;
553 	p->port = port;
554 	p->regs = regs;
555 	p->freq = freq;
556 	uartsetup0(p);
557 }
558 
559 /*
560  *  called by main() to configure a duart port as a console or a mouse
561  */
562 void
563 uartspecial(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int))
564 {
565 	Uart *p = uart[port];
566 	uartenable(p);
567 	if(baud)
568 		uartsetbaud(p, baud);
569 	p->putc = putc;
570 	if(in)
571 		*in = p->iq;
572 	if(out)
573 		*out = p->oq;
574 	p->opens++;
575 }
576 
577 /*
578  *  handle an interrupt to a single uart
579  */
580 static void
581 uartintr(Uart *p)
582 {
583 	uchar ch;
584 	int s, l;
585 
586 	for (s = uartrdreg(p, Istat); !(s&Ipend); s = uartrdreg(p, Istat)) {
587 		switch(s&0x3f){
588 		case 4:	/* received data available */
589 		case 6:	/* receiver line status (alarm or error) */
590 		case 12:	/* character timeout indication */
591 			while ((l = uartrdreg(p, Lstat)) & Inready) {
592 				if(l & Ferror)
593 					p->frame++;
594 				if(l & Oerror)
595 					p->overrun++;
596 				ch = uartrdreg(p, Data) & 0xff;
597 				if (l & (Berror|Perror|Ferror)) {
598 					/* ch came with break, parity or framing error - consume */
599 					continue;
600 				}
601 				if (ch == CTLS || ch == CTLQ) {
602 					ilock(&p->tlock);
603 					if(p->xonoff){
604 						if(ch == CTLS)
605 							p->blocked = 1;
606 						else
607 							p->blocked = 0;	/* clock gets output going again */
608 					}
609 					iunlock(&p->tlock);
610 				}
611 				if(p->putc)
612 					p->putc(p->iq, ch);
613 				else {
614 					ilock(&p->rlock);
615 					if(p->ip < p->ie)
616 						*p->ip++ = ch;
617 					else
618 						p->overrun++;
619 					p->haveinput = 1;
620 					iunlock(&p->rlock);
621 				}
622 			}
623 			break;
624 
625 		case 2:	/* transmitter not full */
626 			uartkick(p);
627 			break;
628 
629 		case 0:	/* modem status */
630 			ch = uartrdreg(p, Mstat);
631 			if(ch & Ctsc){
632 				ilock(&p->tlock);
633 				l = p->cts;
634 				p->cts = ch & Cts;
635 				if(l == 0 && p->cts)
636 					p->ctsbackoff = 2; /* clock gets output going again */
637 				iunlock(&p->tlock);
638 			}
639 	 		if (ch & Dsrc) {
640 				l = ch & Dsr;
641 				if(p->hup_dsr && p->dsr && !l){
642 					ilock(&p->rlock);
643 					p->dohup = 1;
644 					iunlock(&p->rlock);
645 				}
646 				p->dsr = l;
647 			}
648 	 		if (ch & Dcdc) {
649 				l = ch & Dcd;
650 				if(p->hup_dcd && p->dcd && !l){
651 					ilock(&p->rlock);
652 					p->dohup = 1;
653 					iunlock(&p->rlock);
654 				}
655 				p->dcd = l;
656 			}
657 			break;
658 
659 		default:
660 			iprint("weird uart interrupt #%2.2ux\n", s);
661 			break;
662 		}
663 	}
664 	p->istat = s;
665 }
666 
667 /*
668  *  we save up input characters till clock time
669  *
670  *  There's also a bit of code to get a stalled print going.
671  *  It shouldn't happen, but it does.  Obviously I don't
672  *  understand something.  Since it was there, I bundled a
673  *  restart after flow control with it to give some hysteresis
674  *  to the hardware flow control.  This makes compressing
675  *  modems happier but will probably bother something else.
676  *	 -- presotto
677  */
678 void
679 uartclock(void)
680 {
681 	int n;
682 	Uart *p;
683 
684 	for(p = uartalloc.elist; p; p = p->elist){
685 
686 		/* this amortizes cost of qproduce to many chars */
687 		if(p->haveinput){
688 			ilock(&p->rlock);
689 			if(p->haveinput){
690 				n = p->ip - p->istage;
691 				if(n > 0 && p->iq){
692 					if(n > Stagesize)
693 						panic("uartclock");
694 					if(qproduce(p->iq, p->istage, n) < 0)
695 						uartrts(p, 0);
696 					else
697 						p->ip = p->istage;
698 				}
699 				p->haveinput = 0;
700 			}
701 			iunlock(&p->rlock);
702 		}
703 		if(p->dohup){
704 			ilock(&p->rlock);
705 			if(p->dohup){
706 				qhangup(p->iq, 0);
707 				qhangup(p->oq, 0);
708 			}
709 			p->dohup = 0;
710 			iunlock(&p->rlock);
711 		}
712 
713 		/* this adds hysteresis to hardware flow control */
714 		if(p->ctsbackoff){
715 			ilock(&p->tlock);
716 			if(p->ctsbackoff){
717 				if(--(p->ctsbackoff) == 0)
718 					uartkick0(p);
719 			}
720 			iunlock(&p->tlock);
721 		}
722 	}
723 }
724 
725 Dirtab *uartdir;
726 int ndir;
727 
728 static void
729 setlength(int i)
730 {
731 	Uart *p;
732 
733 	if(i >= 0){
734 		p = uart[i];
735 		if(p && p->opens && p->iq)
736 			uartdir[1+3*i].length = qlen(p->iq);
737 	} else for(i = 0; i < nuart; i++){
738 		p = uart[i];
739 		if(p && p->opens && p->iq)
740 			uartdir[1+3*i].length = qlen(p->iq);
741 	}
742 }
743 
744 /*
745  *  all uarts must be uartsetup() by this point or inside of uartinstall()
746  */
747 static void
748 uartreset(void)
749 {
750 	int i;
751 	Dirtab *dp;
752 	uartinstall();	/* architecture specific */
753 
754 	ndir = 1+3*nuart;
755 	uartdir = xalloc(ndir * sizeof(Dirtab));
756 	dp = uartdir;
757 	strcpy(dp->name, ".");
758 	mkqid(&dp->qid, 0, 0, QTDIR);
759 	dp->length = 0;
760 	dp->perm = DMDIR|0555;
761 	dp++;
762 	for(i = 0; i < nuart; i++){
763 		/* 3 directory entries per port */
764 		strcpy(dp->name, uart[i]->name);
765 		dp->qid.path = NETQID(i, Ndataqid);
766 		dp->perm = 0666;
767 		dp++;
768 		sprint(dp->name, "%sctl", uart[i]->name);
769 		dp->qid.path = NETQID(i, Nctlqid);
770 		dp->perm = 0666;
771 		dp++;
772 		sprint(dp->name, "%sstatus", uart[i]->name);
773 		dp->qid.path = NETQID(i, Nstatqid);
774 		dp->perm = 0444;
775 		dp++;
776 	}
777 }
778 
779 static Chan*
780 uartattach(char *spec)
781 {
782 	return devattach('t', spec);
783 }
784 
785 static Walkqid*
786 uartwalk(Chan *c, Chan *nc, char **name, int nname)
787 {
788 	return devwalk(c, nc, name, nname, uartdir, ndir, devgen);
789 }
790 
791 static int
792 uartstat(Chan *c, uchar *dp, int n)
793 {
794 	if(NETTYPE(c->qid.path) == Ndataqid)
795 		setlength(NETID(c->qid.path));
796 	return devstat(c, dp, n, uartdir, ndir, devgen);
797 }
798 
799 static Chan*
800 uartopen(Chan *c, int omode)
801 {
802 	Uart *p;
803 
804 	c = devopen(c, omode, uartdir, ndir, devgen);
805 
806 	switch(NETTYPE(c->qid.path)){
807 	case Nctlqid:
808 	case Ndataqid:
809 		p = uart[NETID(c->qid.path)];
810 		qlock(p);
811 		if(p->opens++ == 0){
812 			uartenable(p);
813 			qreopen(p->iq);
814 			qreopen(p->oq);
815 		}
816 		qunlock(p);
817 		break;
818 	}
819 
820 	return c;
821 }
822 
823 static void
824 uartclose(Chan *c)
825 {
826 	Uart *p;
827 
828 	if(c->qid.type & QTDIR)
829 		return;
830 	if((c->flag & COPEN) == 0)
831 		return;
832 	switch(NETTYPE(c->qid.path)){
833 	case Ndataqid:
834 	case Nctlqid:
835 		p = uart[NETID(c->qid.path)];
836 		qlock(p);
837 		if(--(p->opens) == 0){
838 			uartdisable(p);
839 			qclose(p->iq);
840 			qclose(p->oq);
841 			p->ip = p->istage;
842 			p->dcd = p->dsr = p->dohup = 0;
843 		}
844 		qunlock(p);
845 		break;
846 	}
847 }
848 
849 static long
850 uartstatus(Chan*, Uart *p, void *buf, long n, long offset)
851 {
852 	uchar mstat, fstat, istat, tstat;
853 	char str[256];
854 
855 	str[0] = 0;
856 	tstat = p->sticky[Mctl];
857 	mstat = uartrdreg(p, Mstat);
858 	istat = p->sticky[Iena];
859 	fstat = p->sticky[Format];
860 	snprint(str, sizeof str,
861 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d\n"
862 		"%d %d %d%s%s%s%s%s\n",
863 
864 		p->baud,
865 		p->hup_dcd,
866 		(tstat & Dtr) != 0,
867 		p->hup_dsr,
868 		(fstat & Bits8) + 5,
869 		(istat & Imstat) != 0,
870 		(fstat & Pena) ? ((fstat & Peven) ? 'e' : 'o') : 'n',
871 		(tstat & Rts) != 0,
872 		(fstat & Stop2) ? 2 : 1,
873 
874 		p->dev,
875 		p->frame,
876 		p->overrun,
877 		uartrdreg(p, Istat) & Fenabd       ? " fifo" : "",
878 		(mstat & Cts)    ? " cts"  : "",
879 		(mstat & Dsr)    ? " dsr"  : "",
880 		(mstat & Dcd)    ? " dcd"  : "",
881 		(mstat & Ringl)   ? " ring" : ""
882 	);
883 	return readstr(offset, buf, n, str);
884 }
885 
886 static long
887 uartread(Chan *c, void *buf, long n, vlong off)
888 {
889 	Uart *p;
890 	ulong offset = off;
891 
892 	if(c->qid.type & QTDIR){
893 		setlength(-1);
894 		return devdirread(c, buf, n, uartdir, ndir, devgen);
895 	}
896 
897 	p = uart[NETID(c->qid.path)];
898 	switch(NETTYPE(c->qid.path)){
899 	case Ndataqid:
900 		return qread(p->iq, buf, n);
901 	case Nctlqid:
902 		return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
903 	case Nstatqid:
904 		return uartstatus(c, p, buf, n, offset);
905 	}
906 
907 	return 0;
908 }
909 
910 static void
911 uartctl(Uart *p, char *cmd)
912 {
913 	int i, n;
914 
915 	/* let output drain for a while */
916 	for(i = 0; i < 16 && qlen(p->oq); i++)
917 		tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125);
918 
919 	if(strncmp(cmd, "break", 5) == 0){
920 		uartbreak(p, 0);
921 		return;
922 	}
923 
924 
925 	n = atoi(cmd+1);
926 	switch(*cmd){
927 	case 'B':
928 	case 'b':
929 		uartsetbaud(p, n);
930 		break;
931 	case 'C':
932 	case 'c':
933 		uartdcdhup(p, n);
934 		break;
935 	case 'D':
936 	case 'd':
937 		uartdtr(p, n);
938 		break;
939 	case 'E':
940 	case 'e':
941 		uartdsrhup(p, n);
942 		break;
943 	case 'f':
944 	case 'F':
945 		qflush(p->oq);
946 		break;
947 	case 'H':
948 	case 'h':
949 		qhangup(p->iq, 0);
950 		qhangup(p->oq, 0);
951 		break;
952 	case 'L':
953 	case 'l':
954 		uartbits(p, n);
955 		break;
956 	case 'm':
957 	case 'M':
958 		uartmflow(p, n);
959 		break;
960 	case 'n':
961 	case 'N':
962 		qnoblock(p->oq, n);
963 		break;
964 	case 'P':
965 	case 'p':
966 		uartparity(p, *(cmd+1));
967 		break;
968 	case 'K':
969 	case 'k':
970 		uartbreak(p, n);
971 		break;
972 	case 'R':
973 	case 'r':
974 		uartrts(p, n);
975 		break;
976 	case 'Q':
977 	case 'q':
978 		qsetlimit(p->iq, n);
979 		qsetlimit(p->oq, n);
980 		break;
981 	case 'W':
982 	case 'w':
983 		/* obsolete */
984 		break;
985 	case 'X':
986 	case 'x':
987 		ilock(&p->tlock);
988 		p->xonoff = n;
989 		iunlock(&p->tlock);
990 		break;
991 	}
992 }
993 
994 static long
995 uartwrite(Chan *c, void *buf, long n, vlong)
996 {
997 	Uart *p;
998 	char cmd[32];
999 
1000 	if(c->qid.type & QTDIR)
1001 		error(Eperm);
1002 
1003 	p = uart[NETID(c->qid.path)];
1004 
1005 	/*
1006 	 *  The fifo's turn themselves off sometimes.
1007 	 *  It must be something I don't understand. -- presotto
1008 	 */
1009 	lock(&p->flock);
1010 	if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0)
1011 		uartfifoon(p);
1012 	unlock(&p->flock);
1013 
1014 	switch(NETTYPE(c->qid.path)){
1015 	case Ndataqid:
1016 		return qwrite(p->oq, buf, n);
1017 	case Nctlqid:
1018 		if(n >= sizeof(cmd))
1019 			n = sizeof(cmd)-1;
1020 		memmove(cmd, buf, n);
1021 		cmd[n] = 0;
1022 		uartctl(p, cmd);
1023 		return n;
1024 	default:
1025 		error(Egreg);
1026 		return n;
1027 	}
1028 }
1029 
1030 static int
1031 uartwstat(Chan *c, uchar *dp, int n)
1032 {
1033 	Dir d;
1034 	Dirtab *dt;
1035 
1036 	if(!iseve())
1037 		error(Eperm);
1038 	if(c->qid.type & QTDIR)
1039 		error(Eperm);
1040 	if(NETTYPE(c->qid.path) == Nstatqid)
1041 		error(Eperm);
1042 
1043 	dt = &uartdir[1+3 * NETID(c->qid.path)];
1044 	n = convM2D(dp, n, &d, nil);
1045 	if(n == 0)
1046 		error(Eshortstat);
1047 	if(d.mode != ~0UL){
1048 		d.mode &= 0666;
1049 		dt[0].perm = dt[1].perm = d.mode;
1050 	}
1051 	return n;
1052 }
1053 
1054 Dev uartdevtab = {
1055 	't',
1056 	"uart",
1057 
1058 	uartreset,
1059 	devinit,
1060 	devshutdown,
1061 	uartattach,
1062 	uartwalk,
1063 	uartstat,
1064 	uartopen,
1065 	devcreate,
1066 	uartclose,
1067 	uartread,
1068 	devbread,
1069 	uartwrite,
1070 	devbwrite,
1071 	devremove,
1072 	uartwstat,
1073 };
1074