Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
	p = malloc(READSTR);
264
	if(p == nil)
265
		error(Enomem);
266
	ccb = ((Cc*)(uart->regs))->ccb;
267
	bs = ccb->bs;
268
	fstat = ccb->df;
269
	ms = ccb->ms;
270
 
271
	snprint(p, READSTR,
272
		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
273
		"dev(%d) type(%d) framing(%d) overruns(%d) "
274
		"berr(%d) serr(%d)%s%s%s%s\n",
275
 
276
		uart->baud,
277
		uart->hup_dcd,
278
		ms & Sdsr,
279
		uart->hup_dsr,
280
		(fstat & DbMASK) + 5,
281
		0,
282
		(fstat & PMASK) ? ((fstat & Ep) == Ep? 'e': 'o'): 'n',
283
		(bs & Rbrts) ? 1 : 0,
284
		(fstat & Sb2) ? 2 : 1,
285
		0,
286
 
287
		uart->dev,
288
		uart->type,
289
		uart->ferr,
290
		uart->oerr,
291
		uart->berr,
292
		uart->serr,
293
		(ms & Scts) ? " cts"  : "",
294
		(ms & Sdsr) ? " dsr"  : "",
295
		(ms & Sdcd) ? " dcd"  : "",
296
		(ms & Sri) ? " ring" : ""
297
	);
298
	n = readstr(offset, buf, n, p);
299
	free(p);
300
 
301
	return n;
302
}
303
 
304
static void
305
axpfifo(Uart*, int)
306
{
307
}
308
 
309
static void
310
axpdtr(Uart* uart, int on)
311
{
312
	Ccb *ccb;
313
	u16int mc;
314
 
315
	ccb = ((Cc*)(uart->regs))->ccb;
316
 
317
	mc = ccb->mc;
318
	if(on)
319
		mc |= Adtr;
320
	else
321
		mc &= ~Adtr;
322
	ccb->mc = mc;
323
}
324
 
325
/*
326
 * can be called from uartstageinput() during an input interrupt,
327
 * with uart->rlock ilocked or the uart qlocked, sometimes both.
328
 */
329
static void
330
axprts(Uart* uart, int on)
331
{
332
	Ccb *ccb;
333
	u16int mc;
334
 
335
	ccb = ((Cc*)(uart->regs))->ccb;
336
 
337
	mc = ccb->mc;
338
	if(on)
339
		mc |= Arts;
340
	else
341
		mc &= ~Arts;
342
	ccb->mc = mc;
343
}
344
 
345
static void
346
axpmodemctl(Uart* uart, int on)
347
{
348
	Ccb *ccb;
349
	u16int lp;
350
 
351
	ccb = ((Cc*)(uart->regs))->ccb;
352
 
353
	ilock(&uart->tlock);
354
	lp = ccb->lp;
355
	if(on){
356
		lp |= Cts|Rts;
357
		lp &= ~Emcs;
358
		uart->cts = ccb->ms & Scts;
359
	}
360
	else{
361
		lp &= ~(Cts|Rts);
362
		lp |= Emcs;
363
		uart->cts = 1;
364
	}
365
	uart->modem = on;
366
	iunlock(&uart->tlock);
367
 
368
	ccb->lp = lp;
369
	axpcc(uart->regs, Ccu);
370
}
371
 
372
static int
373
axpparity(Uart* uart, int parity)
374
{
375
	Ccb *ccb;
376
	u16int df;
377
 
378
	switch(parity){
379
	default:
380
		return -1;
381
	case 'e':
382
		parity = Ep;
383
		break;
384
	case 'o':
385
		parity = Op;
386
		break;
387
	case 'n':
388
		parity = Np;
389
		break;
390
	}
391
 
392
	ccb = ((Cc*)(uart->regs))->ccb;
393
 
394
	df = ccb->df & ~PMASK;
395
	ccb->df = df|parity;
396
	axpcc(uart->regs, Ccu);
397
 
398
	return 0;
399
}
400
 
401
static int
402
axpstop(Uart* uart, int stop)
403
{
404
	Ccb *ccb;
405
	u16int df;
406
 
407
	switch(stop){
408
	default:
409
		return -1;
410
	case 1:
411
		stop = Sb1;
412
		break;
413
	case 2:
414
		stop = Sb2;
415
		break;
416
	}
417
 
418
	ccb = ((Cc*)(uart->regs))->ccb;
419
 
420
	df = ccb->df & ~SbMASK;
421
	ccb->df = df|stop;
422
	axpcc(uart->regs, Ccu);
423
 
424
	return 0;
425
}
426
 
427
static int
428
axpbits(Uart* uart, int bits)
429
{
430
	Ccb *ccb;
431
	u16int df;
432
 
433
	bits -= 5;
434
	if(bits < 0 || bits > 3)
435
		return -1;
436
 
437
	ccb = ((Cc*)(uart->regs))->ccb;
438
 
439
	df = ccb->df & ~DbMASK;
440
	ccb->df = df|bits;
441
	axpcc(uart->regs, Ccu);
442
 
443
	return 0;
444
}
445
 
446
static int
447
axpbaud(Uart* uart, int baud)
448
{
449
	Ccb *ccb;
450
	int i, ibtr;
451
 
452
	/*
453
	 * Set baud rate (high rates are special - only 16 bits).
454
	 */
455
	if(baud <= 0)
456
		return -1;
457
	uart->baud = baud;
458
 
459
	ccb = ((Cc*)(uart->regs))->ccb;
460
 
461
	switch(baud){
462
	default:
463
		ccb->br = baud;
464
		break;
465
	case 76800:
466
		ccb->br = Br76800;
467
		break;
468
	case 115200:
469
		ccb->br = Br115200;
470
		break;
471
	}
472
 
473
	/*
474
	 * Set trigger level to about 50 per second.
475
	 */
476
	ibtr = baud/500;
477
	i = (ccb->ibea - ccb->ibsa)/2;
478
	if(ibtr > i)
479
		ibtr = i;
480
	ccb->ibtr = ibtr;
481
	axpcc(uart->regs, Ccu);
482
 
483
	return 0;
484
}
485
 
486
static void
487
axpbreak(Uart* uart, int ms)
488
{
489
	Ccb *ccb;
490
	u16int mc;
491
 
492
	/*
493
	 * Send a break.
494
	 */
495
	if(ms <= 0)
496
		ms = 200;
497
 
498
	ccb = ((Cc*)(uart->regs))->ccb;
499
 
500
	mc = ccb->mc;
501
	ccb->mc = Ab|mc;
502
	tsleep(&up->sleep, return0, 0, ms);
503
	ccb->mc = mc & ~Ab;
504
}
505
 
506
/* only called from interrupt service */
507
static void
508
axpmc(Cc* cc)
509
{
510
	int old;
511
	Ccb *ccb;
512
	u16int ms;
513
 
514
	ccb = cc->ccb;
515
 
516
	ms = ccb->ms;
517
 
518
	if(ms & Scts){
519
		ilock(&cc->tlock);
520
		old = cc->cts;
521
		cc->cts = ms & Scts;
522
		if(old == 0 && cc->cts)
523
			cc->ctsbackoff = 2;
524
		iunlock(&cc->tlock);
525
	}
526
	if(ms & Sdsr){
527
		old = ms & Sdsr;
528
		if(cc->hup_dsr && cc->dsr && !old)
529
			cc->dohup = 1;
530
		cc->dsr = old;
531
	}
532
	if(ms & Sdcd){
533
		old = ms & Sdcd;
534
		if(cc->hup_dcd && cc->dcd && !old)
535
			cc->dohup = 1;
536
		cc->dcd = old;
537
	}
538
}
539
 
540
/* called from uartkick() with uart->tlock ilocked */
541
static void
542
axpkick(Uart* uart)
543
{
544
	Cc *cc;
545
	Ccb *ccb;
546
	uchar *ep, *mem, *rp, *wp, *bp;
547
 
548
	if(uart->cts == 0 || uart->blocked)
549
		return;
550
 
551
	cc = uart->regs;
552
	ccb = cc->ccb;
553
 
554
	mem = (uchar*)cc->ctlr->gcb;
555
	bp = mem + ccb->obsa;
556
	rp = mem + ccb->obrp;
557
	wp = mem + ccb->obwp;
558
	ep = mem + ccb->obea;
559
	while(wp != rp-1 && (rp != bp || wp != ep)){
560
		/*
561
		 * if we've exhausted the uart's output buffer,
562
		 * ask for more from the output queue, and quit if there
563
		 * isn't any.
564
		 */
565
		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
566
			break;
567
		*wp++ = *(uart->op++);
568
		if(wp > ep)
569
			wp = bp;
570
		ccb->obwp = wp - mem;
571
	}
572
}
573
 
574
/* only called from interrupt service */
575
static void
576
axprecv(Cc* cc)
577
{
578
	Ccb *ccb;
579
	uchar *ep, *mem, *rp, *wp;
580
 
581
	ccb = cc->ccb;
582
 
583
	mem = (uchar*)cc->ctlr->gcb;
584
	rp = mem + ccb->ibrp;
585
	wp = mem + ccb->ibwp;
586
	ep = mem + ccb->ibea;
587
 
588
	while(rp != wp){
589
		uartrecv(cc, *rp++);		/* ilocks cc->tlock */
590
		if(rp > ep)
591
			rp = mem + ccb->ibsa;
592
		ccb->ibrp = rp - mem;
593
	}
594
}
595
 
596
static void
597
axpinterrupt(Ureg*, void* arg)
598
{
599
	int work;
600
	Cc *cc;
601
	Ctlr *ctlr;
602
	u32int ics;
603
	u16int r, sr;
604
 
605
	work = 0;
606
	ctlr = arg;
607
	ics = csr32r(ctlr, Ics);
608
	if(ics & 0x0810C000)
609
		print("%s: unexpected interrupt %#ux\n", ctlr->name, ics);
610
	if(!(ics & 0x00002000)) {
611
		/* we get a steady stream of these on consoles */
612
		// print("%s: non-doorbell interrupt\n", ctlr->name);
613
		ctlr->gcb->gcw2 = 0x0001;	/* set Gintack */
614
		return;
615
	}
616
 
617
//	while(work to do){
618
		cc = ctlr->cc;
619
		for(sr = xchgw(&ctlr->gcb->isr, 0); sr != 0; sr >>= 1){
620
			if(sr & 0x0001)
621
				work++, axprecv(cc);
622
			cc++;
623
		}
624
		cc = ctlr->cc;
625
		for(sr = xchgw(&ctlr->gcb->osr, 0); sr != 0; sr >>= 1){
626
			if(sr & 0x0001)
627
				work++, uartkick(&cc->Uart);
628
			cc++;
629
		}
630
		cc = ctlr->cc;
631
		for(sr = xchgw(&ctlr->gcb->csr, 0); sr != 0; sr >>= 1){
632
			if(sr & 0x0001)
633
				work++, wakeup(cc);
634
			cc++;
635
		}
636
		cc = ctlr->cc;
637
		for(sr = xchgw(&ctlr->gcb->msr, 0); sr != 0; sr >>= 1){
638
			if(sr & 0x0001)
639
				work++, axpmc(cc);
640
			cc++;
641
		}
642
		cc = ctlr->cc;
643
		for(sr = xchgw(&ctlr->gcb->esr, 0); sr != 0; sr >>= 1){
644
			if(sr & 0x0001){
645
				r = cc->ccb->ms;
646
				if(r & Oe)
647
					cc->oerr++;
648
				if(r & Pe)
649
					cc->perr++;
650
				if(r & Fe)
651
					cc->ferr++;
652
				if (r & (Oe|Pe|Fe))
653
					work++;
654
			}
655
			cc++;
656
		}
657
//	}
658
	/* only meaningful if we don't share the irq */
659
	if (0 && !work)
660
		print("%s: interrupt with no work\n", ctlr->name);
661
	csr32w(ctlr, Pdb, 1);		/* clear doorbell interrupt */
662
	ctlr->gcb->gcw2 = 0x0001;	/* set Gintack */
663
}
664
 
665
static void
666
axpdisable(Uart* uart)
667
{
668
	Cc *cc;
669
	u16int lp;
670
	Ctlr *ctlr;
671
 
672
	/*
673
 	 * Turn off DTR and RTS, disable interrupts.
674
	 */
675
	(*uart->phys->dtr)(uart, 0);
676
	(*uart->phys->rts)(uart, 0);
677
 
678
	cc = uart->regs;
679
	lp = cc->ccb->lp;
680
	cc->ccb->lp = Emcs|lp;
681
	axpcc(cc, Dt|Dr|Fob|Fib|Ccu);
682
 
683
	/*
684
	 * The Uart is qlocked.
685
	 */
686
	ctlr = cc->ctlr;
687
	ctlr->im &= ~(1<<cc->uartno);
688
	if(ctlr->im == 0)
689
		intrdisable(ctlr->pcidev->intl, axpinterrupt, ctlr,
690
			ctlr->pcidev->tbdf, ctlr->name);
691
}
692
 
693
static void
694
axpenable(Uart* uart, int ie)
695
{
696
	Cc *cc;
697
	Ctlr *ctlr;
698
	u16int lp;
699
 
700
	cc = uart->regs;
701
	ctlr = cc->ctlr;
702
 
703
	/*
704
 	 * Enable interrupts and turn on DTR and RTS.
705
	 * Be careful if this is called to set up a polled serial line
706
	 * early on not to try to enable interrupts as interrupt-
707
	 * -enabling mechanisms might not be set up yet.
708
	 */
709
	if(ie){
710
		/*
711
		 * The Uart is qlocked.
712
		 */
713
		if(ctlr->im == 0){
714
			intrenable(ctlr->pcidev->intl, axpinterrupt, ctlr,
715
				ctlr->pcidev->tbdf, ctlr->name);
716
			csr32w(ctlr, Ics, 0x00031F00);
717
			csr32w(ctlr, Pdb, 1);
718
			ctlr->gcb->gcw2 = 1;
719
		}
720
		ctlr->im |= 1<<cc->uartno;
721
	}
722
 
723
	(*uart->phys->dtr)(uart, 1);
724
	(*uart->phys->rts)(uart, 1);
725
 
726
	/*
727
	 * Make sure we control RTS, DTR and break.
728
	 */
729
	lp = cc->ccb->lp;
730
	cc->ccb->lp = Emcs|lp;
731
	cc->ccb->oblw = 64;
732
	axpcc(cc, Et|Er|Ccu);
733
}
734
 
735
static void*
736
axpdealloc(Ctlr* ctlr)
737
{
738
	int i;
739
 
740
	for(i = 0; i < 16; i++){
741
		if(ctlr->cc[i].name != nil)
742
			free(ctlr->cc[i].name);
743
	}
744
	if(ctlr->reg != nil)
745
		vunmap(ctlr->reg, ctlr->pcidev->mem[0].size);
746
	if(ctlr->mem != nil)
747
		vunmap(ctlr->mem, ctlr->pcidev->mem[2].size);
748
	if(ctlr->name != nil)
749
		free(ctlr->name);
750
	free(ctlr);
751
 
752
	return nil;
753
}
754
 
755
static Uart*
756
axpalloc(int ctlrno, Pcidev* pcidev)
757
{
758
	Cc *cc;
759
	uchar *p;
760
	Ctlr *ctlr;
761
	void *addr;
762
	char name[64];
763
	u32int bar, r;
764
	int i, n, timeo;
765
 
766
	ctlr = malloc(sizeof(Ctlr));
767
	if(ctlr == nil)
768
		error(Enomem);
769
	seprint(name, name+sizeof(name), "uartaxp%d", ctlrno);
770
	kstrdup(&ctlr->name, name);
771
	ctlr->pcidev = pcidev;
772
	ctlr->ctlrno = ctlrno;
773
 
774
	/*
775
	 * Access to runtime registers.
776
	 */
777
	bar = pcidev->mem[0].bar;
778
	if((addr = vmap(bar & ~0x0F, pcidev->mem[0].size)) == 0){
779
		print("%s: can't map registers at %#ux\n", ctlr->name, bar);
780
		return axpdealloc(ctlr);
781
	}
782
	ctlr->reg = addr;
783
	print("%s: port 0x%ux irq %d ", ctlr->name, bar, pcidev->intl);
784
 
785
	/*
786
	 * Local address space 0.
787
	 */
788
	bar = pcidev->mem[2].bar;
789
	if((addr = vmap(bar & ~0x0F, pcidev->mem[2].size)) == 0){
790
		print("%s: can't map memory at %#ux\n", ctlr->name, bar);
791
		return axpdealloc(ctlr);
792
	}
793
	ctlr->mem = addr;
794
	ctlr->gcb = (Gcb*)(ctlr->mem+0x10000);
795
	print("mem 0x%ux size %d: ", bar, pcidev->mem[2].size);
796
 
797
	/*
798
	 * Toggle the software reset and wait for
799
	 * the adapter local init status to indicate done.
800
	 *
801
	 * The two 'delay(100)'s below are important,
802
	 * without them the board seems to become confused
803
	 * (perhaps it needs some 'quiet time' because the
804
	 * timeout loops are not sufficient in themselves).
805
	 */
806
	r = csr32r(ctlr, Mcc);
807
	csr32w(ctlr, Mcc, r|Asr);
808
	microdelay(1);
809
	csr32w(ctlr, Mcc, r&~Asr);
810
	delay(100);
811
 
812
	for(timeo = 0; timeo < 100000; timeo++){
813
		if(csr32r(ctlr, Mcc) & Lis)
814
			break;
815
		microdelay(1);
816
	}
817
	if(!(csr32r(ctlr, Mcc) & Lis)){
818
		print("%s: couldn't reset\n", ctlr->name);
819
		return axpdealloc(ctlr);
820
	}
821
	print("downloading...");
822
	/*
823
	 * Copy the control programme to the card memory.
824
	 * The card's i960 control structures live at 0xD000.
825
	 */
826
	if(sizeof(uartaxpcp) > 0xD000){
827
		print("%s: control programme too big\n", ctlr->name);
828
		return axpdealloc(ctlr);
829
	}
830
	/* TODO: is this right for more than 1 card? devastar does the same */
831
	csr32w(ctlr, Remap, 0xA0000001);
832
	for(i = 0; i < sizeof(uartaxpcp); i++)
833
		ctlr->mem[i] = uartaxpcp[i];
834
	/*
835
	 * Execute downloaded code and wait for it
836
	 * to signal ready.
837
	 */
838
	csr32w(ctlr, Mb0, Edcc);
839
	delay(100);
840
	/* the manual says to wait for Cpr for 1 second */
841
	for(timeo = 0; timeo < 10000; timeo++){
842
		if(csr32r(ctlr, Mb0) & Cpr)
843
			break;
844
		microdelay(100);
845
	}
846
	if(!(csr32r(ctlr, Mb0) & Cpr)){
847
		print("control programme not ready; Mb0 %#ux\n",
848
			csr32r(ctlr, Mb0));
849
		print("%s: distribution panel not connected or card not fully seated?\n",
850
			ctlr->name);
851
 
852
		return axpdealloc(ctlr);
853
	}
854
	print("\n");
855
 
856
	n = ctlr->gcb->ccbn;
857
	if(ctlr->gcb->bt != 0x12 || n > 16){
858
		print("%s: wrong board type %#ux, %d channels\n",
859
			ctlr->name, ctlr->gcb->bt, ctlr->gcb->ccbn);
860
		return axpdealloc(ctlr);
861
	}
862
 
863
	p = ((uchar*)ctlr->gcb) + ctlr->gcb->ccboff;
864
	for(i = 0; i < n; i++){
865
		cc = &ctlr->cc[i];
866
		cc->ccb = (Ccb*)p;
867
		p += ctlr->gcb->ccbsz;
868
		cc->uartno = i;
869
		cc->ctlr = ctlr;
870
 
871
		cc->regs = cc;		/* actually Uart->regs */
872
		seprint(name, name+sizeof(name), "uartaxp%d%2.2d", ctlrno, i);
873
		kstrdup(&cc->name, name);
874
		cc->freq = 0;
875
		cc->bits = 8;
876
		cc->stop = 1;
877
		cc->parity = 'n';
878
		cc->baud = 9600;
879
		cc->phys = &axpphysuart;
880
		cc->console = 0;
881
		cc->special = 0;
882
 
883
		cc->next = &ctlr->cc[i+1];
884
	}
885
	ctlr->cc[n-1].next = nil;
886
 
887
	ctlr->next = nil;
888
	if(axpctlrhead != nil)
889
		axpctlrtail->next = ctlr;
890
	else
891
		axpctlrhead = ctlr;
892
	axpctlrtail = ctlr;
893
 
894
	return ctlr->cc;
895
}
896
 
897
static Uart*
898
axppnp(void)
899
{
900
	Pcidev *p;
901
	int ctlrno;
902
	Uart *head, *tail, *uart;
903
 
904
	/*
905
	 * Loop through all PCI devices looking for simple serial
906
	 * controllers (ccrb == 0x07) and configure the ones which
907
	 * are familiar.
908
	 */
909
	head = tail = nil;
910
	ctlrno = 0;
911
	for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
912
		if(p->ccrb != 0x07)
913
			continue;
914
 
915
		switch((p->did<<16)|p->vid){
916
		default:
917
			continue;
918
		case (0x6001<<16)|0x114F:	/* AvanstarXp */
919
			if((uart = axpalloc(ctlrno, p)) == nil)
920
				continue;
921
			break;
922
		}
923
 
924
		if(head != nil)
925
			tail->next = uart;
926
		else
927
			head = uart;
928
		for(tail = uart; tail->next != nil; tail = tail->next)
929
			;
930
		ctlrno++;
931
	}
932
 
933
	return head;
934
}
935
 
936
PhysUart axpphysuart = {
937
	.name		= "AvanstarXp",
938
	.pnp		= axppnp,
939
	.enable		= axpenable,
940
	.disable	= axpdisable,
941
	.kick		= axpkick,
942
	.dobreak	= axpbreak,
943
	.baud		= axpbaud,
944
	.bits		= axpbits,
945
	.stop		= axpstop,
946
	.parity		= axpparity,
947
	.modemctl	= axpmodemctl,
948
	.rts		= axprts,
949
	.dtr		= axpdtr,
950
	.status		= axpstatus,
951
	.fifo		= axpfifo,
952
	.getc		= nil,
953
	.putc		= nil,
954
};