xref: /plan9/sys/src/9/pc/uartaxp.c (revision e06f534bbaa4097bc6f4764ef1dd2dc3338fbd40)
1 /*
2  * Avanstar Xp pci uart driver
3  */
4 #include "u.h"
5 #include "../port/lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "io.h"
10 #include "../port/error.h"
11 
12 #include "uartaxp.i"
13 
14 typedef struct Cc Cc;
15 typedef struct Ccb Ccb;
16 typedef struct Ctlr Ctlr;
17 typedef struct Gcb Gcb;
18 
19 /*
20  * Global Control Block.
21  * Service Request fields must be accessed using XCHG.
22  */
23 struct Gcb {
24 	u16int	gcw;				/* Global Command Word */
25 	u16int	gsw;				/* Global Status Word */
26 	u16int	gsr;				/* Global Service Request */
27 	u16int	abs;				/* Available Buffer Space */
28 	u16int	bt;				/* Board Type */
29 	u16int	cpv;				/* Control Program Version */
30 	u16int	ccbn;				/* Ccb count */
31 	u16int	ccboff;				/* Ccb offset */
32 	u16int	ccbsz;				/* Ccb size */
33 	u16int	gcw2;				/* Global Command Word 2 */
34 	u16int	gsw2;				/* Global Status Word 2 */
35 	u16int	esr;				/* Error Service Request */
36 	u16int	isr;				/* Input Service Request */
37 	u16int	osr;				/* Output Service Request */
38 	u16int	msr;				/* Modem Service Request */
39 	u16int	csr;				/* Command Service Request */
40 };
41 
42 /*
43  * Channel Control Block.
44  */
45 struct Ccb {
46 	u16int	br;				/* Baud Rate */
47 	u16int	df;				/* Data Format */
48 	u16int	lp;				/* Line Protocol */
49 	u16int	ibs;				/* Input Buffer Size */
50 	u16int	obs;				/* Output Buffer Size */
51 	u16int 	ibtr;				/* Ib Trigger Rate */
52 	u16int	oblw;				/* Ob Low Watermark */
53 	u8int	ixon[2];			/* IXON characters */
54 	u16int	ibhw;				/* Ib High Watermark */
55 	u16int	iblw;				/* Ib Low Watermark */
56 	u16int	cc;				/* Channel Command */
57 	u16int	cs;				/* Channel Status */
58 	u16int	ibsa;				/* Ib Start Addr */
59 	u16int 	ibea;				/* Ib Ending Addr */
60 	u16int	obsa;				/* Ob Start Addr */
61 	u16int 	obea;				/* Ob Ending Addr */
62 	u16int	ibwp;				/* Ib write pointer (RO) */
63 	u16int	ibrp;				/* Ib read pointer (R/W) */
64 	u16int	obwp;				/* Ob write pointer (R/W) */
65 	u16int	obrp;				/* Ob read pointer (RO) */
66 	u16int	ces;				/* Communication Error Status */
67 	u16int	bcp;				/* Bad Character Pointer */
68 	u16int	mc;				/* Modem Control */
69 	u16int	ms;				/* Modem Status */
70 	u16int	bs;				/* Blocking Status */
71 	u16int	crf;				/* Character Received Flag */
72 	u8int	ixoff[2];			/* IXOFF characters */
73 	u16int	cs2;				/* Channel Status 2 */
74 	u8int	sec[2];				/* Strip/Error Characters */
75 };
76 
77 enum {						/* br */
78 	Br76800		= 0xFF00,
79 	Br115200	= 0xFF01,
80 };
81 
82 enum {						/* df */
83 	Db5		= 0x0000,		/* Data Bits - 5 bits/byte */
84 	Db6		= 0x0001,		/*	6 bits/byte */
85 	Db7		= 0x0002,		/*	7 bits/byte */
86 	Db8		= 0x0003,		/*	8 bits/byte */
87 	DbMASK		= 0x0003,
88 	Sb1		= 0x0000,		/* 1 Stop Bit */
89 	Sb2		= 0x0004,		/* 2 Stop Bit */
90 	SbMASK		= 0x0004,
91 	Np		= 0x0000,		/* No Parity */
92 	Op		= 0x0008,		/* Odd Parity */
93 	Ep		= 0x0010,		/* Even Parity */
94 	Mp		= 0x0020,		/* Mark Parity */
95 	Sp		= 0x0030,		/* Space Parity */
96 	PMASK		= 0x0038,
97 	Cmn		= 0x0000,		/* Channel Mode Normal */
98 	Cme		= 0x0040,		/* CM Echo */
99 	Cmll		= 0x0080,		/* CM Local Loopback */
100 	Cmrl		= 0x00C0,		/* CM Remote Loopback */
101 };
102 
103 enum {						/* lp */
104 	Ixon		= 0x0001,		/* Obey IXON/IXOFF */
105 	Ixany		= 0x0002,		/* Any character retarts Tx */
106 	Ixgen		= 0x0004,		/* Generate IXON/IXOFF  */
107 	Cts		= 0x0008,		/* CTS controls Tx */
108 	Dtr		= 0x0010,		/* Rx controls DTR */
109 	½d		= 0x0020,		/* RTS off during Tx */
110 	Rts		= 0x0040,		/* generate RTS */
111 	Emcs		= 0x0080,		/* Enable Modem Control */
112 	Ecs		= 0x1000,		/* Enable Character Stripping */
113 	Eia422		= 0x2000,		/* EIA422 */
114 };
115 
116 enum {						/* cc */
117 	Ccu		= 0x0001,		/* Configure Channel and UART */
118 	Cco		= 0x0002,		/* Configure Channel Only */
119 	Fib		= 0x0004,		/* Flush Input Buffer */
120 	Fob		= 0x0008,		/* Flush Output Buffer */
121 	Er		= 0x0010,		/* Enable Receiver */
122 	Dr		= 0x0020,		/* Disable Receiver */
123 	Et		= 0x0040,		/* Enable Transmitter */
124 	Dt		= 0x0080,		/* Disable Transmitter */
125 };
126 
127 enum {						/* ces */
128 	Oe		= 0x0001,		/* Overrun Error */
129 	Pe		= 0x0002,		/* Parity Error */
130 	Fe		= 0x0004,		/* Framing Error */
131 	Br		= 0x0008,		/* Break Received */
132 };
133 
134 enum {						/* mc */
135 	Adtr		= 0x0001,		/* Assert DTR */
136 	Arts		= 0x0002,		/* Assert RTS */
137 	Ab		= 0x0010,		/* Assert BREAK */
138 };
139 
140 enum {						/* ms */
141 	Scts		= 0x0001,		/* Status od CTS */
142 	Sdsr		= 0x0002,		/* Status of DSR */
143 	Sri		= 0x0004,		/* Status of RI */
144 	Sdcd		= 0x0008,		/* Status of DCD */
145 };
146 
147 enum {						/* bs */
148 	Rd		= 0x0001,		/* Receiver Disabled */
149 	Td		= 0x0002,		/* Transmitter Disabled */
150 	Tbxoff		= 0x0004,		/* Tx Blocked by XOFF */
151 	Tbcts		= 0x0008,		/* Tx Blocked by CTS */
152 	Rbxoff		= 0x0010,		/* Rx Blocked by XOFF */
153 	Rbrts		= 0x0020,		/* Rx Blocked by RTS */
154 };
155 
156 enum {						/* Local Configuration */
157 	Range		= 0x00,
158 	Remap		= 0x04,
159 	Region		= 0x18,
160 	Mb0		= 0x40,			/* Mailbox 0 */
161 	Ldb		= 0x60,			/* PCI to Local Doorbell */
162 	Pdb		= 0x64,			/* Local to PCI Doorbell */
163 	Ics		= 0x68,			/* Interrupt Control/Status */
164 	Mcc		= 0x6C,			/* Misc. Command and Control */
165 };
166 
167 enum {						/* Mb0 */
168 	Edcc		= 1,			/* exec. downloaded code cmd */
169 	Aic		= 0x10,			/* adapter init'zed correctly */
170 	Cpr		= 1ul << 31,		/* control program ready */
171 };
172 
173 enum {						/* Mcc */
174 	Rcr		= 1ul << 29,		/* reload config. reg.s */
175 	Asr		= 1ul << 30,		/* pci adapter sw reset */
176 	Lis		= 1ul << 31,		/* local init status */
177 };
178 
179 typedef struct Cc Cc;
180 typedef struct Ccb Ccb;
181 typedef struct Ctlr Ctlr;
182 
183 /*
184  * Channel Control, one per uart.
185  * Devuart communicates via the PhysUart functions with
186  * a Uart* argument. Uart.regs is filled in by this driver
187  * to point to a Cc, and Cc.ctlr points to the Axp board
188  * controller.
189  */
190 struct Cc {
191 	int	uartno;
192 	Ccb*	ccb;
193 	Ctlr*	ctlr;
194 
195 	Rendez;
196 
197 	Uart;
198 };
199 
200 typedef struct Ctlr {
201 	char*	name;
202 	Pcidev*	pcidev;
203 	int	ctlrno;
204 	Ctlr*	next;
205 
206 	u32int*	reg;
207 	uchar*	mem;
208 	Gcb*	gcb;
209 
210 	int	im;		/* interrupt mask */
211 	Cc	cc[16];
212 } Ctlr;
213 
214 #define csr32r(c, r)	(*((c)->reg+((r)/4)))
215 #define csr32w(c, r, v)	(*((c)->reg+((r)/4)) = (v))
216 
217 static Ctlr* axpctlrhead;
218 static Ctlr* axpctlrtail;
219 
220 extern PhysUart axpphysuart;
221 
222 static int
223 axpccdone(void* ccb)
224 {
225 	return !((Ccb*)ccb)->cc;	/* hw sets ccb->cc to zero */
226 }
227 
228 static void
229 axpcc(Cc* cc, int cmd)
230 {
231 	Ccb *ccb;
232 	int timeo;
233 	u16int cs;
234 
235 	ccb = cc->ccb;
236 	ccb->cc = cmd;
237 
238 	if(!cc->ctlr->im)
239 		for(timeo = 0; timeo < 1000000; timeo++){
240 			if(!ccb->cc)
241 				break;
242 			microdelay(1);
243 		}
244 	else
245 		tsleep(cc, axpccdone, ccb, 1000);
246 
247 	cs = ccb->cs;
248 	if(ccb->cc || cs){
249 		print("%s: cmd %#ux didn't terminate: %#ux %#ux\n",
250 			cc->name, cmd, ccb->cc, cs);
251 		if(cc->ctlr->im)
252 			error(Eio);
253 	}
254 }
255 
256 static long
257 axpstatus(Uart* uart, void* buf, long n, long offset)
258 {
259 	char *p;
260 	Ccb *ccb;
261 	u16int bs, fstat, ms;
262 
263 	ccb = ((Cc*)(uart->regs))->ccb;
264 
265 	p = malloc(READSTR);
266 	bs = ccb->bs;
267 	fstat = ccb->df;
268 	ms = ccb->ms;
269 
270 	snprint(p, READSTR,
271 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
272 		"dev(%d) type(%d) framing(%d) overruns(%d) "
273 		"berr(%d) serr(%d)%s%s%s%s\n",
274 
275 		uart->baud,
276 		uart->hup_dcd,
277 		ms & Sdsr,
278 		uart->hup_dsr,
279 		(fstat & DbMASK) + 5,
280 		0,
281 		(fstat & PMASK) ? ((fstat & Ep) == Ep? 'e': 'o'): 'n',
282 		(bs & Rbrts) ? 1 : 0,
283 		(fstat & Sb2) ? 2 : 1,
284 		0,
285 
286 		uart->dev,
287 		uart->type,
288 		uart->ferr,
289 		uart->oerr,
290 		uart->berr,
291 		uart->serr,
292 		(ms & Scts) ? " cts"  : "",
293 		(ms & Sdsr) ? " dsr"  : "",
294 		(ms & Sdcd) ? " dcd"  : "",
295 		(ms & Sri) ? " ring" : ""
296 	);
297 	n = readstr(offset, buf, n, p);
298 	free(p);
299 
300 	return n;
301 }
302 
303 static void
304 axpfifo(Uart*, int)
305 {
306 }
307 
308 static void
309 axpdtr(Uart* uart, int on)
310 {
311 	Ccb *ccb;
312 	u16int mc;
313 
314 	ccb = ((Cc*)(uart->regs))->ccb;
315 
316 	mc = ccb->mc;
317 	if(on)
318 		mc |= Adtr;
319 	else
320 		mc &= ~Adtr;
321 	ccb->mc = mc;
322 }
323 
324 /*
325  * can be called from uartstageinput() during an input interrupt,
326  * with uart->rlock ilocked or the uart qlocked, sometimes both.
327  */
328 static void
329 axprts(Uart* uart, int on)
330 {
331 	Ccb *ccb;
332 	u16int mc;
333 
334 	ccb = ((Cc*)(uart->regs))->ccb;
335 
336 	mc = ccb->mc;
337 	if(on)
338 		mc |= Arts;
339 	else
340 		mc &= ~Arts;
341 	ccb->mc = mc;
342 }
343 
344 static void
345 axpmodemctl(Uart* uart, int on)
346 {
347 	Ccb *ccb;
348 	u16int lp;
349 
350 	ccb = ((Cc*)(uart->regs))->ccb;
351 
352 	ilock(&uart->tlock);
353 	lp = ccb->lp;
354 	if(on){
355 		lp |= Cts|Rts;
356 		lp &= ~Emcs;
357 		uart->cts = ccb->ms & Scts;
358 	}
359 	else{
360 		lp &= ~(Cts|Rts);
361 		lp |= Emcs;
362 		uart->cts = 1;
363 	}
364 	uart->modem = on;
365 	iunlock(&uart->tlock);
366 
367 	ccb->lp = lp;
368 	axpcc(uart->regs, Ccu);
369 }
370 
371 static int
372 axpparity(Uart* uart, int parity)
373 {
374 	Ccb *ccb;
375 	u16int df;
376 
377 	switch(parity){
378 	default:
379 		return -1;
380 	case 'e':
381 		parity = Ep;
382 		break;
383 	case 'o':
384 		parity = Op;
385 		break;
386 	case 'n':
387 		parity = Np;
388 		break;
389 	}
390 
391 	ccb = ((Cc*)(uart->regs))->ccb;
392 
393 	df = ccb->df & ~PMASK;
394 	ccb->df = df|parity;
395 	axpcc(uart->regs, Ccu);
396 
397 	return 0;
398 }
399 
400 static int
401 axpstop(Uart* uart, int stop)
402 {
403 	Ccb *ccb;
404 	u16int df;
405 
406 	switch(stop){
407 	default:
408 		return -1;
409 	case 1:
410 		stop = Sb1;
411 		break;
412 	case 2:
413 		stop = Sb2;
414 		break;
415 	}
416 
417 	ccb = ((Cc*)(uart->regs))->ccb;
418 
419 	df = ccb->df & ~SbMASK;
420 	ccb->df = df|stop;
421 	axpcc(uart->regs, Ccu);
422 
423 	return 0;
424 }
425 
426 static int
427 axpbits(Uart* uart, int bits)
428 {
429 	Ccb *ccb;
430 	u16int df;
431 
432 	bits -= 5;
433 	if(bits < 0 || bits > 3)
434 		return -1;
435 
436 	ccb = ((Cc*)(uart->regs))->ccb;
437 
438 	df = ccb->df & ~DbMASK;
439 	ccb->df = df|bits;
440 	axpcc(uart->regs, Ccu);
441 
442 	return 0;
443 }
444 
445 static int
446 axpbaud(Uart* uart, int baud)
447 {
448 	Ccb *ccb;
449 	int i, ibtr;
450 
451 	/*
452 	 * Set baud rate (high rates are special - only 16 bits).
453 	 */
454 	if(baud <= 0)
455 		return -1;
456 	uart->baud = baud;
457 
458 	ccb = ((Cc*)(uart->regs))->ccb;
459 
460 	switch(baud){
461 	default:
462 		ccb->br = baud;
463 		break;
464 	case 76800:
465 		ccb->br = Br76800;
466 		break;
467 	case 115200:
468 		ccb->br = Br115200;
469 		break;
470 	}
471 
472 	/*
473 	 * Set trigger level to about 50 per second.
474 	 */
475 	ibtr = baud/500;
476 	i = (ccb->ibea - ccb->ibsa)/2;
477 	if(ibtr > i)
478 		ibtr = i;
479 	ccb->ibtr = ibtr;
480 	axpcc(uart->regs, Ccu);
481 
482 	return 0;
483 }
484 
485 static void
486 axpbreak(Uart* uart, int ms)
487 {
488 	Ccb *ccb;
489 	u16int mc;
490 
491 	/*
492 	 * Send a break.
493 	 */
494 	if(ms <= 0)
495 		ms = 200;
496 
497 	ccb = ((Cc*)(uart->regs))->ccb;
498 
499 	mc = ccb->mc;
500 	ccb->mc = Ab|mc;
501 	tsleep(&up->sleep, return0, 0, ms);
502 	ccb->mc = mc & ~Ab;
503 }
504 
505 /* only called from interrupt service */
506 static void
507 axpmc(Cc* cc)
508 {
509 	int old;
510 	Ccb *ccb;
511 	u16int ms;
512 
513 	ccb = cc->ccb;
514 
515 	ms = ccb->ms;
516 
517 	if(ms & Scts){
518 		ilock(&cc->tlock);
519 		old = cc->cts;
520 		cc->cts = ms & Scts;
521 		if(old == 0 && cc->cts)
522 			cc->ctsbackoff = 2;
523 		iunlock(&cc->tlock);
524 	}
525 	if(ms & Sdsr){
526 		old = ms & Sdsr;
527 		if(cc->hup_dsr && cc->dsr && !old)
528 			cc->dohup = 1;
529 		cc->dsr = old;
530 	}
531 	if(ms & Sdcd){
532 		old = ms & Sdcd;
533 		if(cc->hup_dcd && cc->dcd && !old)
534 			cc->dohup = 1;
535 		cc->dcd = old;
536 	}
537 }
538 
539 /* called from uartkick() with uart->tlock ilocked */
540 static void
541 axpkick(Uart* uart)
542 {
543 	Cc *cc;
544 	Ccb *ccb;
545 	uchar *ep, *mem, *rp, *wp, *bp;
546 
547 	if(uart->cts == 0 || uart->blocked)
548 		return;
549 
550 	cc = uart->regs;
551 	ccb = cc->ccb;
552 
553 	mem = (uchar*)cc->ctlr->gcb;
554 	bp = mem + ccb->obsa;
555 	rp = mem + ccb->obrp;
556 	wp = mem + ccb->obwp;
557 	ep = mem + ccb->obea;
558 	while(wp != rp-1 && (rp != bp || wp != ep)){
559 		/*
560 		 * if we've exhausted the uart's output buffer,
561 		 * ask for more from the output queue, and quit if there
562 		 * isn't any.
563 		 */
564 		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
565 			break;
566 		*wp++ = *(uart->op++);
567 		if(wp > ep)
568 			wp = bp;
569 		ccb->obwp = wp - mem;
570 	}
571 }
572 
573 /* only called from interrupt service */
574 static void
575 axprecv(Cc* cc)
576 {
577 	Ccb *ccb;
578 	uchar *ep, *mem, *rp, *wp;
579 
580 	ccb = cc->ccb;
581 
582 	mem = (uchar*)cc->ctlr->gcb;
583 	rp = mem + ccb->ibrp;
584 	wp = mem + ccb->ibwp;
585 	ep = mem + ccb->ibea;
586 
587 	while(rp != wp){
588 		uartrecv(cc, *rp++);		/* ilocks cc->tlock */
589 		if(rp > ep)
590 			rp = mem + ccb->ibsa;
591 		ccb->ibrp = rp - mem;
592 	}
593 }
594 
595 static void
596 axpinterrupt(Ureg*, void* arg)
597 {
598 	int work;
599 	Cc *cc;
600 	Ctlr *ctlr;
601 	u32int ics;
602 	u16int r, sr;
603 
604 	work = 0;
605 	ctlr = arg;
606 	ics = csr32r(ctlr, Ics);
607 	if(ics & 0x0810C000)
608 		print("%s: unexpected interrupt %#ux\n", ctlr->name, ics);
609 	if(!(ics & 0x00002000)) {
610 		print("%s: non-doorbell interrupt\n", ctlr->name);
611 		// ctlr->gcb->gcw2 = 0x0001;	/* set Gintack */
612 		return;
613 	}
614 
615 //	while(work to do){
616 		cc = ctlr->cc;
617 		for(sr = xchgw(&ctlr->gcb->isr, 0); sr != 0; sr >>= 1){
618 			if(sr & 0x0001)
619 				work++, axprecv(cc);
620 			cc++;
621 		}
622 		cc = ctlr->cc;
623 		for(sr = xchgw(&ctlr->gcb->osr, 0); sr != 0; sr >>= 1){
624 			if(sr & 0x0001)
625 				work++, uartkick(&cc->Uart);
626 			cc++;
627 		}
628 		cc = ctlr->cc;
629 		for(sr = xchgw(&ctlr->gcb->csr, 0); sr != 0; sr >>= 1){
630 			if(sr & 0x0001)
631 				work++, wakeup(cc);
632 			cc++;
633 		}
634 		cc = ctlr->cc;
635 		for(sr = xchgw(&ctlr->gcb->msr, 0); sr != 0; sr >>= 1){
636 			if(sr & 0x0001)
637 				work++, axpmc(cc);
638 			cc++;
639 		}
640 		cc = ctlr->cc;
641 		for(sr = xchgw(&ctlr->gcb->esr, 0); sr != 0; sr >>= 1){
642 			if(sr & 0x0001){
643 				r = cc->ccb->ms;
644 				if(r & Oe)
645 					cc->oerr++;
646 				if(r & Pe)
647 					cc->perr++;
648 				if(r & Fe)
649 					cc->ferr++;
650 				if (r & (Oe|Pe|Fe))
651 					work++;
652 			}
653 			cc++;
654 		}
655 //	}
656 	/* only meaningful if we don't share the irq */
657 	if (0 && !work)
658 		print("%s: interrupt with no work\n", ctlr->name);
659 	csr32w(ctlr, Pdb, 1);		/* clear doorbell interrupt */
660 	ctlr->gcb->gcw2 = 0x0001;	/* set Gintack */
661 }
662 
663 static void
664 axpdisable(Uart* uart)
665 {
666 	Cc *cc;
667 	u16int lp;
668 	Ctlr *ctlr;
669 
670 	/*
671  	 * Turn off DTR and RTS, disable interrupts.
672 	 */
673 	(*uart->phys->dtr)(uart, 0);
674 	(*uart->phys->rts)(uart, 0);
675 
676 	cc = uart->regs;
677 	lp = cc->ccb->lp;
678 	cc->ccb->lp = Emcs|lp;
679 	axpcc(cc, Dt|Dr|Fob|Fib|Ccu);
680 
681 	/*
682 	 * The Uart is qlocked.
683 	 */
684 	ctlr = cc->ctlr;
685 	ctlr->im &= ~(1<<cc->uartno);
686 	if(ctlr->im == 0)
687 		intrdisable(ctlr->pcidev->intl, axpinterrupt, ctlr,
688 			ctlr->pcidev->tbdf, ctlr->name);
689 }
690 
691 static void
692 axpenable(Uart* uart, int ie)
693 {
694 	Cc *cc;
695 	Ctlr *ctlr;
696 	u16int lp;
697 
698 	cc = uart->regs;
699 	ctlr = cc->ctlr;
700 
701 	/*
702  	 * Enable interrupts and turn on DTR and RTS.
703 	 * Be careful if this is called to set up a polled serial line
704 	 * early on not to try to enable interrupts as interrupt-
705 	 * -enabling mechanisms might not be set up yet.
706 	 */
707 	if(ie){
708 		/*
709 		 * The Uart is qlocked.
710 		 */
711 		if(ctlr->im == 0){
712 			intrenable(ctlr->pcidev->intl, axpinterrupt, ctlr,
713 				ctlr->pcidev->tbdf, ctlr->name);
714 			csr32w(ctlr, Ics, 0x00031F00);
715 			csr32w(ctlr, Pdb, 1);
716 			ctlr->gcb->gcw2 = 1;
717 		}
718 		ctlr->im |= 1<<cc->uartno;
719 	}
720 
721 	(*uart->phys->dtr)(uart, 1);
722 	(*uart->phys->rts)(uart, 1);
723 
724 	/*
725 	 * Make sure we control RTS, DTR and break.
726 	 */
727 	lp = cc->ccb->lp;
728 	cc->ccb->lp = Emcs|lp;
729 	cc->ccb->oblw = 64;
730 	axpcc(cc, Et|Er|Ccu);
731 }
732 
733 static void*
734 axpdealloc(Ctlr* ctlr)
735 {
736 	int i;
737 
738 	for(i = 0; i < 16; i++){
739 		if(ctlr->cc[i].name != nil)
740 			free(ctlr->cc[i].name);
741 	}
742 	if(ctlr->reg != nil)
743 		vunmap(ctlr->reg, ctlr->pcidev->mem[0].size);
744 	if(ctlr->mem != nil)
745 		vunmap(ctlr->mem, ctlr->pcidev->mem[2].size);
746 	if(ctlr->name != nil)
747 		free(ctlr->name);
748 	free(ctlr);
749 
750 	return nil;
751 }
752 
753 static Uart*
754 axpalloc(int ctlrno, Pcidev* pcidev)
755 {
756 	Cc *cc;
757 	uchar *p;
758 	Ctlr *ctlr;
759 	void *addr;
760 	char name[64];
761 	u32int bar, r;
762 	int i, n, timeo;
763 
764 	ctlr = malloc(sizeof(Ctlr));
765 	seprint(name, name+sizeof(name), "uartaxp%d", ctlrno);
766 	kstrdup(&ctlr->name, name);
767 	ctlr->pcidev = pcidev;
768 	ctlr->ctlrno = ctlrno;
769 
770 	/*
771 	 * Access to runtime registers.
772 	 */
773 	bar = pcidev->mem[0].bar;
774 	if((addr = vmap(bar & ~0x0F, pcidev->mem[0].size)) == 0){
775 		print("%s: can't map registers at %#ux\n", ctlr->name, bar);
776 		return axpdealloc(ctlr);
777 	}
778 	ctlr->reg = addr;
779 	print("%s: port 0x%ux irq %d ", ctlr->name, bar, pcidev->intl);
780 
781 	/*
782 	 * Local address space 0.
783 	 */
784 	bar = pcidev->mem[2].bar;
785 	if((addr = vmap(bar & ~0x0F, pcidev->mem[2].size)) == 0){
786 		print("%s: can't map memory at %#ux\n", ctlr->name, bar);
787 		return axpdealloc(ctlr);
788 	}
789 	ctlr->mem = addr;
790 	ctlr->gcb = (Gcb*)(ctlr->mem+0x10000);
791 	print("mem 0x%ux size %d: ", bar, pcidev->mem[2].size);
792 
793 	/*
794 	 * Toggle the software reset and wait for
795 	 * the adapter local init status to indicate done.
796 	 *
797 	 * The two 'delay(100)'s below are important,
798 	 * without them the board seems to become confused
799 	 * (perhaps it needs some 'quiet time' because the
800 	 * timeout loops are not sufficient in themselves).
801 	 */
802 	r = csr32r(ctlr, Mcc);
803 	csr32w(ctlr, Mcc, r|Asr);
804 	microdelay(1);
805 	csr32w(ctlr, Mcc, r&~Asr);
806 	delay(100);
807 
808 	for(timeo = 0; timeo < 100000; timeo++){
809 		if(csr32r(ctlr, Mcc) & Lis)
810 			break;
811 		microdelay(1);
812 	}
813 	if(!(csr32r(ctlr, Mcc) & Lis)){
814 		print("%s: couldn't reset\n", ctlr->name);
815 		return axpdealloc(ctlr);
816 	}
817 	print("downloading...");
818 	/*
819 	 * Copy the control programme to the card memory.
820 	 * The card's i960 control structures live at 0xD000.
821 	 */
822 	if(sizeof(uartaxpcp) > 0xD000){
823 		print("%s: control programme too big\n", ctlr->name);
824 		return axpdealloc(ctlr);
825 	}
826 	/* TODO: is this right for more than 1 card? devastar does the same */
827 	csr32w(ctlr, Remap, 0xA0000001);
828 	for(i = 0; i < sizeof(uartaxpcp); i++)
829 		ctlr->mem[i] = uartaxpcp[i];
830 	/*
831 	 * Execute downloaded code and wait for it
832 	 * to signal ready.
833 	 */
834 	csr32w(ctlr, Mb0, Edcc);
835 	delay(100);
836 	/* the manual says to wait for Cpr for 1 second */
837 	for(timeo = 0; timeo < 10000; timeo++){
838 		if(csr32r(ctlr, Mb0) & Cpr)
839 			break;
840 		microdelay(100);
841 	}
842 	if(!(csr32r(ctlr, Mb0) & Cpr)){
843 		print("control programme not ready; Mb0 %#ux\n",
844 			csr32r(ctlr, Mb0));
845 		print("%s: might not be fully seated in its PCI slot\n",
846 			ctlr->name);
847 
848 		return axpdealloc(ctlr);
849 	}
850 	print("\n");
851 
852 	n = ctlr->gcb->ccbn;
853 	if(ctlr->gcb->bt != 0x12 || n > 16){
854 		print("%s: wrong board type %#ux, %d channels\n",
855 			ctlr->name, ctlr->gcb->bt, ctlr->gcb->ccbn);
856 		return axpdealloc(ctlr);
857 	}
858 
859 	p = ((uchar*)ctlr->gcb) + ctlr->gcb->ccboff;
860 	for(i = 0; i < n; i++){
861 		cc = &ctlr->cc[i];
862 		cc->ccb = (Ccb*)p;
863 		p += ctlr->gcb->ccbsz;
864 		cc->uartno = i;
865 		cc->ctlr = ctlr;
866 
867 		cc->regs = cc;		/* actually Uart->regs */
868 		seprint(name, name+sizeof(name), "uartaxp%d%2.2d", ctlrno, i);
869 		kstrdup(&cc->name, name);
870 		cc->freq = 0;
871 		cc->bits = 8;
872 		cc->stop = 1;
873 		cc->parity = 'n';
874 		cc->baud = 9600;
875 		cc->phys = &axpphysuart;
876 		cc->console = 0;
877 		cc->special = 0;
878 
879 		cc->next = &ctlr->cc[i+1];
880 	}
881 	ctlr->cc[n-1].next = nil;
882 
883 	ctlr->next = nil;
884 	if(axpctlrhead != nil)
885 		axpctlrtail->next = ctlr;
886 	else
887 		axpctlrhead = ctlr;
888 	axpctlrtail = ctlr;
889 
890 	return ctlr->cc;
891 }
892 
893 static Uart*
894 axppnp(void)
895 {
896 	Pcidev *p;
897 	int ctlrno;
898 	Uart *head, *tail, *uart;
899 
900 	/*
901 	 * Loop through all PCI devices looking for simple serial
902 	 * controllers (ccrb == 0x07) and configure the ones which
903 	 * are familiar.
904 	 */
905 	head = tail = nil;
906 	ctlrno = 0;
907 	for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
908 		if(p->ccrb != 0x07)
909 			continue;
910 
911 		switch((p->did<<16)|p->vid){
912 		default:
913 			continue;
914 		case (0x6001<<16)|0x114F:	/* AvanstarXp */
915 			if((uart = axpalloc(ctlrno, p)) == nil)
916 				continue;
917 			break;
918 		}
919 
920 		if(head != nil)
921 			tail->next = uart;
922 		else
923 			head = uart;
924 		for(tail = uart; tail->next != nil; tail = tail->next)
925 			;
926 		ctlrno++;
927 	}
928 
929 	return head;
930 }
931 
932 PhysUart axpphysuart = {
933 	.name		= "AvanstarXp",
934 	.pnp		= axppnp,
935 	.enable		= axpenable,
936 	.disable	= axpdisable,
937 	.kick		= axpkick,
938 	.dobreak	= axpbreak,
939 	.baud		= axpbaud,
940 	.bits		= axpbits,
941 	.stop		= axpstop,
942 	.parity		= axpparity,
943 	.modemctl	= axpmodemctl,
944 	.rts		= axprts,
945 	.dtr		= axpdtr,
946 	.status		= axpstatus,
947 	.fifo		= axpfifo,
948 	.getc		= nil,
949 	.putc		= nil,
950 };
951