FreeBSD/Linux Kernel Cross Reference
sys/mtx/pci.c
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 }
Cache object: 2c24e81683f457ad8cb81dac99340b75
|