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