xref: /plan9/sys/src/9/mtx/pci.c (revision d0f3faac644260b801b3ce61d6da0b1e8e492dac)
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
pcilog(char * fmt,...)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
tbdffmt(Fmt * fmt)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
pcibarsize(Pcidev * p,int rno)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
pcisizcmp(void * a,void * b)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
pcimask(ulong v)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
pcibusmap(Pcidev * root,ulong * pmema,ulong * pioa,int wrreg)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
pcilscan(int bno,Pcidev ** list)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
pciscan(int bno,Pcidev ** list)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
pcicfginit(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
pcicfgrw8(int tbdf,int rno,int data,int read)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
pcicfgr8(Pcidev * pcidev,int rno)648 pcicfgr8(Pcidev* pcidev, int rno)
649 {
650 	return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
651 }
652 
653 void
pcicfgw8(Pcidev * pcidev,int rno,int data)654 pcicfgw8(Pcidev* pcidev, int rno, int data)
655 {
656 	pcicfgrw8(pcidev->tbdf, rno, data, 0);
657 }
658 
659 static int
pcicfgrw16(int tbdf,int rno,int data,int read)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
pcicfgr16(Pcidev * pcidev,int rno)705 pcicfgr16(Pcidev* pcidev, int rno)
706 {
707 	return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
708 }
709 
710 void
pcicfgw16(Pcidev * pcidev,int rno,int data)711 pcicfgw16(Pcidev* pcidev, int rno, int data)
712 {
713 	pcicfgrw16(pcidev->tbdf, rno, data, 0);
714 }
715 
716 static int
pcicfgrw32(int tbdf,int rno,int data,int read)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
pcicfgr32(Pcidev * pcidev,int rno)761 pcicfgr32(Pcidev* pcidev, int rno)
762 {
763 	return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
764 }
765 
766 void
pcicfgw32(Pcidev * pcidev,int rno,int data)767 pcicfgw32(Pcidev* pcidev, int rno, int data)
768 {
769 	pcicfgrw32(pcidev->tbdf, rno, data, 0);
770 }
771 
772 Pcidev*
pcimatch(Pcidev * prev,int vid,int did)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*
pcimatchtbdf(int tbdf)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
pciipin(Pcidev * pci,uchar pin)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
pcilhinv(Pcidev * p)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
pcihinv(Pcidev * p)865 pcihinv(Pcidev* p)
866 {
867 	if(pcicfgmode == -1)
868 		pcicfginit();
869 	qlock(&pcicfginitlock);
870 	pcilhinv(p);
871 	qunlock(&pcicfginitlock);
872 }
873 
874 void
pcireset(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
pcisetbme(Pcidev * p)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
pciclrbme(Pcidev * p)901 pciclrbme(Pcidev* p)
902 {
903 	int pcr;
904 
905 	pcr = pcicfgr16(p, PciPCR);
906 	pcr &= ~MASen;
907 	pcicfgw16(p, PciPCR, pcr);
908 }
909