Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/9/mtx/pci.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * PCI support code.
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
#define DBG	if(0) pcilog
13
 
14
struct
15
{
16
	char	output[16384];
17
	int	ptr;
18
}PCICONS;
19
 
20
int
21
pcilog(char *fmt, ...)
22
{
23
	int n;
24
	va_list arg;
25
	char buf[PRINTSIZE];
26
 
27
	va_start(arg, fmt);
28
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
29
	va_end(arg);
30
 
31
	memmove(PCICONS.output+PCICONS.ptr, buf, n);
32
	PCICONS.ptr += n;
33
	return n;
34
}
35
 
36
enum
37
{					/* configuration mechanism #1 */
38
	PciADDR		= 0xCF8,	/* CONFIG_ADDRESS */
39
	PciDATA		= 0xCFC,	/* CONFIG_DATA */
40
 
41
					/* configuration mechanism #2 */
42
	PciCSE		= 0xCF8,	/* configuration space enable */
43
	PciFORWARD	= 0xCFA,	/* which bus */
44
 
45
	MaxFNO		= 7,
46
	MaxUBN		= 255,
47
};
48
 
49
enum
50
{					/* command register */
51
	IOen		= (1<<0),
52
	MEMen		= (1<<1),
53
	MASen		= (1<<2),
54
	MemWrInv	= (1<<4),
55
	PErrEn		= (1<<6),
56
	SErrEn		= (1<<8),
57
};
58
 
59
static Lock pcicfglock;
60
static QLock pcicfginitlock;
61
static int pcicfgmode = -1;
62
static int pcimaxbno = 7;
63
static int pcimaxdno;
64
static Pcidev* pciroot;
65
static Pcidev* pcilist;
66
static Pcidev* pcitail;
67
 
68
static int pcicfgrw32(int, int, int, int);
69
static int pcicfgrw8(int, int, int, int);
70
 
71
static char* bustypes[] = {
72
	"CBUSI",
73
	"CBUSII",
74
	"EISA",
75
	"FUTURE",
76
	"INTERN",
77
	"ISA",
78
	"MBI",
79
	"MBII",
80
	"MCA",
81
	"MPI",
82
	"MPSA",
83
	"NUBUS",
84
	"PCI",
85
	"PCMCIA",
86
	"TC",
87
	"VL",
88
	"VME",
89
	"XPRESS",
90
};
91
 
92
#pragma	varargck	type	"T"	int
93
 
94
static int
95
tbdffmt(Fmt* fmt)
96
{
97
	char *p;
98
	int l, r, type, tbdf;
99
 
100
	if((p = malloc(READSTR)) == nil)
101
		return fmtstrcpy(fmt, "(tbdfconv)");
102
 
103
	switch(fmt->r){
104
	case 'T':
105
		tbdf = va_arg(fmt->args, int);
106
		type = BUSTYPE(tbdf);
107
		if(type < nelem(bustypes))
108
			l = snprint(p, READSTR, bustypes[type]);
109
		else
110
			l = snprint(p, READSTR, "%d", type);
111
		snprint(p+l, READSTR-l, ".%d.%d.%d",
112
			BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
113
		break;
114
 
115
	default:
116
		snprint(p, READSTR, "(tbdfconv)");
117
		break;
118
	}
119
	r = fmtstrcpy(fmt, p);
120
	free(p);
121
 
122
	return r;
123
}
124
 
125
ulong
126
pcibarsize(Pcidev *p, int rno)
127
{
128
	ulong v, size;
129
 
130
	v = pcicfgrw32(p->tbdf, rno, 0, 1);
131
	pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
132
	size = pcicfgrw32(p->tbdf, rno, 0, 1);
133
	if(v & 1)
134
		size |= 0xFFFF0000;
135
	pcicfgrw32(p->tbdf, rno, v, 0);
136
 
137
	return -(size & ~0x0F);
138
}
139
 
140
static int
141
pcisizcmp(void *a, void *b)
142
{
143
	Pcisiz *aa, *bb;
144
 
145
	aa = a;
146
	bb = b;
147
	return aa->siz - bb->siz;
148
}
149
 
150
static ulong
151
pcimask(ulong v)
152
{
153
	ulong m;
154
 
155
	m = BI2BY*sizeof(v);
156
	for(m = 1<<(m-1); m != 0; m >>= 1) {
157
		if(m & v)
158
			break;
159
	}
160
 
161
	m--;
162
	if((v & m) == 0)
163
		return v;
164
 
165
	v |= m;
166
	return v+1;
167
}
168
 
169
static void
170
pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
171
{
172
	Pcidev *p;
173
	int ntb, i, size, rno, hole;
174
	ulong v, mema, ioa, sioa, smema, base, limit;
175
	Pcisiz *table, *tptr, *mtb, *itb;
176
	extern void qsort(void*, long, long, int (*)(void*, void*));
177
 
178
	ioa = *pioa;
179
	mema = *pmema;
180
 
181
	DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n", 
182
		wrreg, root->tbdf, mema, ioa);
183
 
184
	ntb = 0;
185
	for(p = root; p != nil; p = p->link)
186
		ntb++;
187
 
188
	ntb *= (PciCIS-PciBAR0)/4;
189
	table = malloc(2*ntb*sizeof(Pcisiz));
190
	itb = table;
191
	mtb = table+ntb;
192
 
193
	/*
194
	 * Build a table of sizes
195
	 */
196
	for(p = root; p != nil; p = p->link) {
197
		if(p->ccrb == 0x06) {
198
			if(p->ccru == 0x04 && p->bridge != nil) {
199
				sioa = ioa;
200
				smema = mema;
201
				pcibusmap(p->bridge, &smema, &sioa, 0);
202
 
203
				hole = pcimask(smema-mema);
204
				if(hole < (1<<20))
205
					hole = 1<<20;
206
				p->mema.size = hole;
207
 
208
				hole = pcimask(sioa-ioa);
209
				if(hole < (1<<12))
210
					hole = 1<<12;
211
 
212
				p->ioa.size = hole;
213
 
214
				itb->dev = p;
215
				itb->bar = -1;
216
				itb->siz = p->ioa.size;
217
				itb++;
218
 
219
				mtb->dev = p;
220
				mtb->bar = -1;
221
				mtb->siz = p->mema.size;
222
				mtb++;
223
			}
224
			if((pcicfgr8(p, PciHDT)&0x7f) != 0)
225
				continue;
226
		}
227
 
228
		for(i = 0; i <= 5; i++) {
229
			rno = PciBAR0 + i*4;
230
			v = pcicfgrw32(p->tbdf, rno, 0, 1);
231
			size = pcibarsize(p, rno);
232
			if(size == 0)
233
				continue;
234
 
235
			if(v & 1) {
236
				itb->dev = p;
237
				itb->bar = i;
238
				itb->siz = size;
239
				itb++;
240
			}
241
			else {
242
				mtb->dev = p;
243
				mtb->bar = i;
244
				mtb->siz = size;
245
				mtb++;
246
			}
247
 
248
			p->mem[i].size = size;
249
		}
250
	}
251
 
252
	/*
253
	 * Sort both tables IO smallest first, Memory largest
254
	 */
255
	qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
256
	tptr = table+ntb;
257
	qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
258
 
259
	/*
260
	 * Allocate IO address space on this bus
261
	 */
262
	for(tptr = table; tptr < itb; tptr++) {
263
		hole = tptr->siz;
264
		if(tptr->bar == -1)
265
			hole = 1<<12;
266
		ioa = (ioa+hole-1) & ~(hole-1);
267
 
268
		p = tptr->dev;
269
		if(tptr->bar == -1)
270
			p->ioa.bar = ioa;
271
		else {
272
			p->pcr |= IOen;
273
			p->mem[tptr->bar].bar = ioa|1;
274
			if(wrreg)
275
				pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
276
		}
277
 
278
		ioa += tptr->siz;
279
	}
280
 
281
	/*
282
	 * Allocate Memory address space on this bus
283
	 */
284
	for(tptr = table+ntb; tptr < mtb; tptr++) {
285
		hole = tptr->siz;
286
		if(tptr->bar == -1)
287
			hole = 1<<20;
288
		mema = (mema+hole-1) & ~(hole-1);
289
 
290
		p = tptr->dev;
291
		if(tptr->bar == -1)
292
			p->mema.bar = mema;
293
		else {
294
			p->pcr |= MEMen;
295
			p->mem[tptr->bar].bar = mema;
296
			if(wrreg)
297
				pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
298
		}
299
		mema += tptr->siz;
300
	}
301
 
302
	*pmema = mema;
303
	*pioa = ioa;
304
	free(table);
305
 
306
	if(wrreg == 0)
307
		return;
308
 
309
	/*
310
	 * Finally set all the bridge addresses & registers
311
	 */
312
	for(p = root; p != nil; p = p->link) {
313
		if(p->bridge == nil) {
314
			pcicfgrw8(p->tbdf, PciLTR, 64, 0);
315
 
316
			p->pcr |= MASen;
317
			pcicfgrw32(p->tbdf, PciPCR, p->pcr, 0);
318
			continue;
319
		}
320
 
321
		base = p->ioa.bar;
322
		limit = base+p->ioa.size-1;
323
		v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
324
		v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
325
		pcicfgrw32(p->tbdf, PciIBR, v, 0);
326
		v = (limit & 0xFFFF0000)|(base>>16);
327
		pcicfgrw32(p->tbdf, PciIUBR, v, 0);
328
 
329
		base = p->mema.bar;
330
		limit = base+p->mema.size-1;
331
		v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
332
		pcicfgrw32(p->tbdf, PciMBR, v, 0);
333
 
334
		/*
335
		 * Disable memory prefetch
336
		 */
337
		pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
338
		pcicfgrw8(p->tbdf, PciLTR, 64, 0);
339
 
340
		/*
341
		 * Enable the bridge
342
		 */
343
		v = 0xFFFF0000 | IOen | MEMen | MASen;
344
		pcicfgrw32(p->tbdf, PciPCR, v, 0);
345
 
346
		sioa = p->ioa.bar;
347
		smema = p->mema.bar;
348
		pcibusmap(p->bridge, &smema, &sioa, 1);
349
	}
350
}
351
 
352
static int
353
pcilscan(int bno, Pcidev** list)
354
{
355
	Pcidev *p, *head, *tail;
356
	int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
357
 
358
	maxubn = bno;
359
	head = nil;
360
	tail = nil;
361
	for(dno = 0; dno <= pcimaxdno; dno++){
362
		maxfno = 0;
363
		for(fno = 0; fno <= maxfno; fno++){
364
			/*
365
			 * For this possible device, form the
366
			 * bus+device+function triplet needed to address it
367
			 * and try to read the vendor and device ID.
368
			 * If successful, allocate a device struct and
369
			 * start to fill it in with some useful information
370
			 * from the device's configuration space.
371
			 */
372
			tbdf = MKBUS(BusPCI, bno, dno, fno);
373
			l = pcicfgrw32(tbdf, PciVID, 0, 1);
374
			if(l == 0xFFFFFFFF || l == 0)
375
				continue;
376
			p = malloc(sizeof(*p));
377
			p->tbdf = tbdf;
378
			p->vid = l;
379
			p->did = l>>16;
380
 
381
			if(pcilist != nil)
382
				pcitail->list = p;
383
			else
384
				pcilist = p;
385
			pcitail = p;
386
 
387
			p->rid = pcicfgr8(p, PciRID);
388
			p->ccrp = pcicfgr8(p, PciCCRp);
389
			p->ccru = pcicfgr8(p, PciCCRu);
390
			p->ccrb = pcicfgr8(p, PciCCRb);
391
			p->pcr = pcicfgr32(p, PciPCR);
392
 
393
			p->intl = pcicfgr8(p, PciINTL);
394
 
395
			/*
396
			 * If the device is a multi-function device adjust the
397
			 * loop count so all possible functions are checked.
398
			 */
399
			hdt = pcicfgr8(p, PciHDT);
400
			if(hdt & 0x80)
401
				maxfno = MaxFNO;
402
 
403
			/*
404
			 * If appropriate, read the base address registers
405
			 * and work out the sizes.
406
			 */
407
			switch(p->ccrb) {
408
			case 0x01:		/* mass storage controller */
409
			case 0x02:		/* network controller */
410
			case 0x03:		/* display controller */
411
			case 0x04:		/* multimedia device */
412
			case 0x06:		/* bridge device */
413
			case 0x07:		/* simple comm. controllers */
414
			case 0x08:		/* base system peripherals */
415
			case 0x09:		/* input devices */
416
			case 0x0A:		/* docking stations */
417
			case 0x0B:		/* processors */
418
			case 0x0C:		/* serial bus controllers */
419
				if((hdt & 0x7F) != 0)
420
					break;
421
				rno = PciBAR0 - 4;
422
				for(i = 0; i < nelem(p->mem); i++) {
423
					rno += 4;
424
					p->mem[i].bar = pcicfgr32(p, rno);
425
					p->mem[i].size = pcibarsize(p, rno);
426
				}
427
				break;
428
 
429
			case 0x00:
430
			case 0x05:		/* memory controller */
431
			default:
432
				break;
433
			}
434
 
435
			if(head != nil)
436
				tail->link = p;
437
			else
438
				head = p;
439
			tail = p;
440
		}
441
	}
442
 
443
	*list = head;
444
	for(p = head; p != nil; p = p->link){
445
		/*
446
		 * Find PCI-PCI bridges and recursively descend the tree.
447
		 */
448
		if(p->ccrb != 0x06 || p->ccru != 0x04)
449
			continue;
450
 
451
		/*
452
		 * If the secondary or subordinate bus number is not
453
		 * initialised try to do what the PCI BIOS should have
454
		 * done and fill in the numbers as the tree is descended.
455
		 * On the way down the subordinate bus number is set to
456
		 * the maximum as it's not known how many buses are behind
457
		 * this one; the final value is set on the way back up.
458
		 */
459
		sbn = pcicfgr8(p, PciSBN);
460
		ubn = pcicfgr8(p, PciUBN);
461
 
462
		if(sbn == 0 || ubn == 0) {
463
			sbn = maxubn+1;
464
			/*
465
			 * Make sure memory, I/O and master enables are
466
			 * off, set the primary, secondary and subordinate
467
			 * bus numbers and clear the secondary status before
468
			 * attempting to scan the secondary bus.
469
			 *
470
			 * Initialisation of the bridge should be done here.
471
			 */
472
			pcicfgw32(p, PciPCR, 0xFFFF0000);
473
			l = (MaxUBN<<16)|(sbn<<8)|bno;
474
			pcicfgw32(p, PciPBN, l);
475
			pcicfgw16(p, PciSPSR, 0xFFFF);
476
			maxubn = pcilscan(sbn, &p->bridge);
477
			l = (maxubn<<16)|(sbn<<8)|bno;
478
 
479
			pcicfgw32(p, PciPBN, l);
480
		}
481
		else {
482
			maxubn = ubn;
483
			pcilscan(sbn, &p->bridge);
484
		}
485
	}
486
 
487
	return maxubn;
488
}
489
 
490
int
491
pciscan(int bno, Pcidev **list)
492
{
493
	int ubn;
494
 
495
	qlock(&pcicfginitlock);
496
	ubn = pcilscan(bno, list);
497
	qunlock(&pcicfginitlock);
498
	return ubn;
499
}
500
 
501
static void
502
pcicfginit(void)
503
{
504
	char *p;
505
	int bno;
506
	Pcidev **list;
507
	ulong mema, ioa;
508
 
509
	qlock(&pcicfginitlock);
510
	if(pcicfgmode != -1)
511
		goto out;
512
 
513
	/*
514
	 * Try to determine which PCI configuration mode is implemented.
515
	 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
516
	 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
517
	 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
518
	 * a device behind these addresses so if Mode2 accesses fail try
519
	 * for Mode1 (which is preferred, Mode2 is deprecated).
520
	 */
521
	outb(PciCSE, 0);
522
	if(inb(PciCSE) == 0){
523
		pcicfgmode = 2;
524
		pcimaxdno = 15;
525
	}
526
	else {
527
		outl(PciADDR, 0);
528
		if(inl(PciADDR) == 0){
529
			pcicfgmode = 1;
530
			pcimaxdno = 31;
531
		}
532
	}
533
 
534
	if(pcicfgmode < 0)
535
		goto out;
536
 
537
	fmtinstall('T', tbdffmt);
538
 
539
	if(p = getconf("*pcimaxbno"))
540
		pcimaxbno = strtoul(p, 0, 0);
541
	if(p = getconf("*pcimaxdno"))
542
		pcimaxdno = strtoul(p, 0, 0);
543
 
544
	list = &pciroot;
545
	for(bno = 0; bno <= pcimaxbno; bno++) {
546
		int sbno = bno;
547
		bno = pcilscan(bno, list);
548
 
549
		while(*list)
550
			list = &(*list)->link;
551
 
552
		if (sbno == 0) {
553
			Pcidev *pci;
554
 
555
			/*
556
			  * If we have found a PCI-to-Cardbus bridge, make sure
557
			  * it has no valid mappings anymore.  
558
			  */
559
			pci = pciroot;
560
			while (pci) {
561
				if (pci->ccrb == 6 && pci->ccru == 7) {
562
					ushort bcr;
563
 
564
					/* reset the cardbus */
565
					bcr = pcicfgr16(pci, PciBCR);
566
					pcicfgw16(pci, PciBCR, 0x40 | bcr);
567
					delay(50);
568
				}
569
				pci = pci->link;
570
			}
571
		}
572
	}
573
 
574
	if(pciroot == nil)
575
		goto out;
576
 
577
	/*
578
	 * Work out how big the top bus is
579
	 */
580
	mema = 0;
581
	ioa = 0;
582
	pcibusmap(pciroot, &mema, &ioa, 0);
583
 
584
	DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n",
585
		mema, pcimask(mema), ioa);
586
 
587
	/*
588
	 * Align the windows and map it
589
	 */
590
	ioa = 0x1000;
591
	mema = 0;
592
 
593
	pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
594
 
595
	pcibusmap(pciroot, &mema, &ioa, 1);
596
	DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
597
 
598
out:
599
	qunlock(&pcicfginitlock);
600
}
601
 
602
static int
603
pcicfgrw8(int tbdf, int rno, int data, int read)
604
{
605
	int o, type, x;
606
 
607
	if(pcicfgmode == -1)
608
		pcicfginit();
609
 
610
	if(BUSBNO(tbdf))
611
		type = 0x01;
612
	else
613
		type = 0x00;
614
	x = -1;
615
	if(BUSDNO(tbdf) > pcimaxdno)
616
		return x;
617
 
618
	lock(&pcicfglock);
619
	switch(pcicfgmode){
620
 
621
	case 1:
622
		o = rno & 0x03;
623
		rno &= ~0x03;
624
		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
625
		if(read)
626
			x = inb(PciDATA+o);
627
		else
628
			outb(PciDATA+o, data);
629
		outl(PciADDR, 0);
630
		break;
631
 
632
	case 2:
633
		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
634
		outb(PciFORWARD, BUSBNO(tbdf));
635
		if(read)
636
			x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
637
		else
638
			outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
639
		outb(PciCSE, 0);
640
		break;
641
	}
642
	unlock(&pcicfglock);
643
 
644
	return x;
645
}
646
 
647
int
648
pcicfgr8(Pcidev* pcidev, int rno)
649
{
650
	return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
651
}
652
 
653
void
654
pcicfgw8(Pcidev* pcidev, int rno, int data)
655
{
656
	pcicfgrw8(pcidev->tbdf, rno, data, 0);
657
}
658
 
659
static int
660
pcicfgrw16(int tbdf, int rno, int data, int read)
661
{
662
	int o, type, x;
663
 
664
	if(pcicfgmode == -1)
665
		pcicfginit();
666
 
667
	if(BUSBNO(tbdf))
668
		type = 0x01;
669
	else
670
		type = 0x00;
671
	x = -1;
672
	if(BUSDNO(tbdf) > pcimaxdno)
673
		return x;
674
 
675
	lock(&pcicfglock);
676
	switch(pcicfgmode){
677
 
678
	case 1:
679
		o = rno & 0x02;
680
		rno &= ~0x03;
681
		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
682
		if(read)
683
			x = ins(PciDATA+o);
684
		else
685
			outs(PciDATA+o, data);
686
		outl(PciADDR, 0);
687
		break;
688
 
689
	case 2:
690
		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
691
		outb(PciFORWARD, BUSBNO(tbdf));
692
		if(read)
693
			x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
694
		else
695
			outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
696
		outb(PciCSE, 0);
697
		break;
698
	}
699
	unlock(&pcicfglock);
700
 
701
	return x;
702
}
703
 
704
int
705
pcicfgr16(Pcidev* pcidev, int rno)
706
{
707
	return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
708
}
709
 
710
void
711
pcicfgw16(Pcidev* pcidev, int rno, int data)
712
{
713
	pcicfgrw16(pcidev->tbdf, rno, data, 0);
714
}
715
 
716
static int
717
pcicfgrw32(int tbdf, int rno, int data, int read)
718
{
719
	int type, x;
720
 
721
	if(pcicfgmode == -1)
722
		pcicfginit();
723
 
724
	if(BUSBNO(tbdf))
725
		type = 0x01;
726
	else
727
		type = 0x00;
728
	x = -1;
729
	if(BUSDNO(tbdf) > pcimaxdno)
730
		return x;
731
 
732
	lock(&pcicfglock);
733
	switch(pcicfgmode){
734
 
735
	case 1:
736
		rno &= ~0x03;
737
		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
738
		if(read)
739
			x = inl(PciDATA);
740
		else
741
			outl(PciDATA, data);
742
		outl(PciADDR, 0);
743
		break;
744
 
745
	case 2:
746
		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
747
		outb(PciFORWARD, BUSBNO(tbdf));
748
		if(read)
749
			x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
750
		else
751
			outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
752
		outb(PciCSE, 0);
753
		break;
754
	}
755
	unlock(&pcicfglock);
756
 
757
	return x;
758
}
759
 
760
int
761
pcicfgr32(Pcidev* pcidev, int rno)
762
{
763
	return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
764
}
765
 
766
void
767
pcicfgw32(Pcidev* pcidev, int rno, int data)
768
{
769
	pcicfgrw32(pcidev->tbdf, rno, data, 0);
770
}
771
 
772
Pcidev*
773
pcimatch(Pcidev* prev, int vid, int did)
774
{
775
	if(pcicfgmode == -1)
776
		pcicfginit();
777
 
778
	if(prev == nil)
779
		prev = pcilist;
780
	else
781
		prev = prev->list;
782
 
783
	while(prev != nil){
784
		if((vid == 0 || prev->vid == vid)
785
		&& (did == 0 || prev->did == did))
786
			break;
787
		prev = prev->list;
788
	}
789
	return prev;
790
}
791
 
792
Pcidev*
793
pcimatchtbdf(int tbdf)
794
{
795
	Pcidev *pcidev;
796
 
797
	if(pcicfgmode == -1)
798
		pcicfginit();
799
 
800
	for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
801
		if(pcidev->tbdf == tbdf)
802
			break;
803
	}
804
	return pcidev;
805
}
806
 
807
uchar
808
pciipin(Pcidev *pci, uchar pin)
809
{
810
	if (pci == nil)
811
		pci = pcilist;
812
 
813
	while (pci) {
814
		uchar intl;
815
 
816
		if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
817
			return pci->intl;
818
 
819
		if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
820
			return intl;
821
 
822
		pci = pci->list;
823
	}
824
	return 0;
825
}
826
 
827
static void
828
pcilhinv(Pcidev* p)
829
{
830
	int i;
831
	Pcidev *t;
832
 
833
	if(p == nil) {
834
		putstrn(PCICONS.output, PCICONS.ptr);
835
		p = pciroot;
836
		print("bus dev type vid  did intl memory\n");
837
	}
838
	for(t = p; t != nil; t = t->link) {
839
		print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d  ",
840
			BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
841
			t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
842
 
843
		for(i = 0; i < nelem(p->mem); i++) {
844
			if(t->mem[i].size == 0)
845
				continue;
846
			print("%d:%.8lux %d ", i,
847
				t->mem[i].bar, t->mem[i].size);
848
		}
849
		if(t->ioa.bar || t->ioa.size)
850
			print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
851
		if(t->mema.bar || t->mema.size)
852
			print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
853
		if(t->bridge)
854
			print("->%d", BUSBNO(t->bridge->tbdf));
855
		print("\n");
856
	}
857
	while(p != nil) {
858
		if(p->bridge != nil)
859
			pcilhinv(p->bridge);
860
		p = p->link;
861
	}	
862
}
863
 
864
void
865
pcihinv(Pcidev* p)
866
{
867
	if(pcicfgmode == -1)
868
		pcicfginit();
869
	qlock(&pcicfginitlock);
870
	pcilhinv(p);
871
	qunlock(&pcicfginitlock);
872
}
873
 
874
void
875
pcireset(void)
876
{
877
	Pcidev *p;
878
	int pcr;
879
 
880
	if(pcicfgmode == -1)
881
		pcicfginit();
882
 
883
	for(p = pcilist; p != nil; p = p->list){
884
		pcr = pcicfgr16(p, PciPCR);
885
		pcr &= ~0x0004;
886
		pcicfgw16(p, PciPCR, pcr);
887
	}
888
}
889
 
890
void
891
pcisetbme(Pcidev* p)
892
{
893
	int pcr;
894
 
895
	pcr = pcicfgr16(p, PciPCR);
896
	pcr |= MASen;
897
	pcicfgw16(p, PciPCR, pcr);
898
}
899
 
900
void
901
pciclrbme(Pcidev* p)
902
{
903
	int pcr;
904
 
905
	pcr = pcicfgr16(p, PciPCR);
906
	pcr &= ~MASen;
907
	pcicfgw16(p, PciPCR, pcr);
908
}