17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier #include "pci.h"
6*9a747e4fSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier /*
97dd7cddfSDavid du Colombier * PCI support code.
107dd7cddfSDavid du Colombier * There really should be a driver for this, it's not terribly safe
117dd7cddfSDavid du Colombier * without locks or restrictions on what can be poked (e.g. Axil NX801).
127dd7cddfSDavid du Colombier */
137dd7cddfSDavid du Colombier enum { /* configuration mechanism #1 */
147dd7cddfSDavid du Colombier PciADDR = 0xCF8, /* CONFIG_ADDRESS */
157dd7cddfSDavid du Colombier PciDATA = 0xCFC, /* CONFIG_DATA */
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier /* configuration mechanism #2 */
187dd7cddfSDavid du Colombier PciCSE = 0xCF8, /* configuration space enable */
197dd7cddfSDavid du Colombier PciFORWARD = 0xCFA, /* which bus */
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier MaxFNO = 7,
227dd7cddfSDavid du Colombier MaxUBN = 255,
237dd7cddfSDavid du Colombier };
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier static int pcicfgmode = -1;
267dd7cddfSDavid du Colombier static int pcimaxdno;
277dd7cddfSDavid du Colombier static Pcidev* pciroot;
287dd7cddfSDavid du Colombier static Pcidev* pcilist;
297dd7cddfSDavid du Colombier static Pcidev* pcitail;
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier static int pcicfgrw32(int, int, int, int);
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier static int
pciscan(int bno,Pcidev ** list)347dd7cddfSDavid du Colombier pciscan(int bno, Pcidev** list)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier ulong v;
377dd7cddfSDavid du Colombier Pcidev *p, *head, *tail;
387dd7cddfSDavid du Colombier int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
397dd7cddfSDavid du Colombier
407dd7cddfSDavid du Colombier maxubn = bno;
417dd7cddfSDavid du Colombier head = nil;
427dd7cddfSDavid du Colombier tail = nil;
437dd7cddfSDavid du Colombier for(dno = 0; dno <= pcimaxdno; dno++){
447dd7cddfSDavid du Colombier maxfno = 0;
457dd7cddfSDavid du Colombier for(fno = 0; fno <= maxfno; fno++){
467dd7cddfSDavid du Colombier /*
477dd7cddfSDavid du Colombier * For this possible device, form the bus+device+function
487dd7cddfSDavid du Colombier * triplet needed to address it and try to read the vendor
497dd7cddfSDavid du Colombier * and device ID. If successful, allocate a device struct
507dd7cddfSDavid du Colombier * and start to fill it in with some useful information from
517dd7cddfSDavid du Colombier * the device's configuration space.
527dd7cddfSDavid du Colombier */
537dd7cddfSDavid du Colombier tbdf = MKBUS(BusPCI, bno, dno, fno);
547dd7cddfSDavid du Colombier l = pcicfgrw32(tbdf, PciVID, 0, 1);
557dd7cddfSDavid du Colombier if(l == 0xFFFFFFFF || l == 0)
567dd7cddfSDavid du Colombier continue;
577dd7cddfSDavid du Colombier p = mallocz(sizeof(*p), 1);
587dd7cddfSDavid du Colombier p->tbdf = tbdf;
597dd7cddfSDavid du Colombier p->vid = l;
607dd7cddfSDavid du Colombier p->did = l>>16;
61*9a747e4fSDavid du Colombier p->rid = pcicfgr8(p, PciRID);
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier if(pcilist != nil)
647dd7cddfSDavid du Colombier pcitail->list = p;
657dd7cddfSDavid du Colombier else
667dd7cddfSDavid du Colombier pcilist = p;
677dd7cddfSDavid du Colombier pcitail = p;
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier p->intl = pcicfgr8(p, PciINTL);
707dd7cddfSDavid du Colombier p->ccru = pcicfgr16(p, PciCCRu);
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier /*
737dd7cddfSDavid du Colombier * If the device is a multi-function device adjust the
747dd7cddfSDavid du Colombier * loop count so all possible functions are checked.
757dd7cddfSDavid du Colombier */
767dd7cddfSDavid du Colombier hdt = pcicfgr8(p, PciHDT);
777dd7cddfSDavid du Colombier if(hdt & 0x80)
787dd7cddfSDavid du Colombier maxfno = MaxFNO;
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier /*
817dd7cddfSDavid du Colombier * If appropriate, read the base address registers
827dd7cddfSDavid du Colombier * and work out the sizes.
837dd7cddfSDavid du Colombier */
847dd7cddfSDavid du Colombier switch(p->ccru>>8){
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier case 0x01: /* mass storage controller */
877dd7cddfSDavid du Colombier case 0x02: /* network controller */
887dd7cddfSDavid du Colombier case 0x03: /* display controller */
897dd7cddfSDavid du Colombier case 0x04: /* multimedia device */
907dd7cddfSDavid du Colombier case 0x07: /* simple communication controllers */
917dd7cddfSDavid du Colombier case 0x08: /* base system peripherals */
927dd7cddfSDavid du Colombier case 0x09: /* input devices */
937dd7cddfSDavid du Colombier case 0x0A: /* docking stations */
947dd7cddfSDavid du Colombier case 0x0B: /* processors */
957dd7cddfSDavid du Colombier case 0x0C: /* serial bus controllers */
967dd7cddfSDavid du Colombier if((hdt & 0x7F) != 0)
977dd7cddfSDavid du Colombier break;
987dd7cddfSDavid du Colombier rno = PciBAR0 - 4;
997dd7cddfSDavid du Colombier for(i = 0; i < nelem(p->mem); i++){
1007dd7cddfSDavid du Colombier rno += 4;
1017dd7cddfSDavid du Colombier p->mem[i].bar = pcicfgr32(p, rno);
1027dd7cddfSDavid du Colombier pcicfgw32(p, rno, -1);
1037dd7cddfSDavid du Colombier v = pcicfgr32(p, rno);
1047dd7cddfSDavid du Colombier pcicfgw32(p, rno, p->mem[i].bar);
1057dd7cddfSDavid du Colombier p->mem[i].size = -(v & ~0xF);
1067dd7cddfSDavid du Colombier }
1077dd7cddfSDavid du Colombier break;
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier case 0x00:
1107dd7cddfSDavid du Colombier case 0x05: /* memory controller */
1117dd7cddfSDavid du Colombier case 0x06: /* bridge device */
1127dd7cddfSDavid du Colombier default:
1137dd7cddfSDavid du Colombier break;
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier
1167dd7cddfSDavid du Colombier if(head != nil)
1177dd7cddfSDavid du Colombier tail->link = p;
1187dd7cddfSDavid du Colombier else
1197dd7cddfSDavid du Colombier head = p;
1207dd7cddfSDavid du Colombier tail = p;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier *list = head;
1257dd7cddfSDavid du Colombier for(p = head; p != nil; p = p->link){
1267dd7cddfSDavid du Colombier /*
1277dd7cddfSDavid du Colombier * Find PCI-PCI bridges and recursively descend the tree.
1287dd7cddfSDavid du Colombier */
1297dd7cddfSDavid du Colombier if(p->ccru != ((0x06<<8)|0x04))
1307dd7cddfSDavid du Colombier continue;
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier /*
1337dd7cddfSDavid du Colombier * If the secondary or subordinate bus number is not initialised
1347dd7cddfSDavid du Colombier * try to do what the PCI BIOS should have done and fill in the
1357dd7cddfSDavid du Colombier * numbers as the tree is descended. On the way down the subordinate
1367dd7cddfSDavid du Colombier * bus number is set to the maximum as it's not known how many
1377dd7cddfSDavid du Colombier * buses are behind this one; the final value is set on the way
1387dd7cddfSDavid du Colombier * back up.
1397dd7cddfSDavid du Colombier */
1407dd7cddfSDavid du Colombier sbn = pcicfgr8(p, PciSBN);
1417dd7cddfSDavid du Colombier ubn = pcicfgr8(p, PciUBN);
1427dd7cddfSDavid du Colombier if(sbn == 0 || ubn == 0){
1437dd7cddfSDavid du Colombier sbn = maxubn+1;
1447dd7cddfSDavid du Colombier /*
1457dd7cddfSDavid du Colombier * Make sure memory, I/O and master enables are off,
1467dd7cddfSDavid du Colombier * set the primary, secondary and subordinate bus numbers
1477dd7cddfSDavid du Colombier * and clear the secondary status before attempting to
1487dd7cddfSDavid du Colombier * scan the secondary bus.
1497dd7cddfSDavid du Colombier *
1507dd7cddfSDavid du Colombier * Initialisation of the bridge should be done here.
1517dd7cddfSDavid du Colombier */
1527dd7cddfSDavid du Colombier pcicfgw32(p, PciPCR, 0xFFFF0000);
1537dd7cddfSDavid du Colombier l = (MaxUBN<<16)|(sbn<<8)|bno;
1547dd7cddfSDavid du Colombier pcicfgw32(p, PciPBN, l);
1557dd7cddfSDavid du Colombier pcicfgw16(p, PciSPSR, 0xFFFF);
1567dd7cddfSDavid du Colombier maxubn = pciscan(sbn, &p->bridge);
1577dd7cddfSDavid du Colombier l = (maxubn<<16)|(sbn<<8)|bno;
1587dd7cddfSDavid du Colombier pcicfgw32(p, PciPBN, l);
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier else{
1617dd7cddfSDavid du Colombier maxubn = ubn;
1627dd7cddfSDavid du Colombier pciscan(sbn, &p->bridge);
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier return maxubn;
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier
1697dd7cddfSDavid du Colombier static void
pcicfginit(void)1707dd7cddfSDavid du Colombier pcicfginit(void)
1717dd7cddfSDavid du Colombier {
1727dd7cddfSDavid du Colombier #ifdef kernel
1737dd7cddfSDavid du Colombier char *p;
1747dd7cddfSDavid du Colombier #endif /* kernel */
1757dd7cddfSDavid du Colombier int bno;
1767dd7cddfSDavid du Colombier Pcidev **list;
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier if(pcicfgmode == -1){
1797dd7cddfSDavid du Colombier /*
1807dd7cddfSDavid du Colombier * Try to determine which PCI configuration mode is implemented.
1817dd7cddfSDavid du Colombier * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
1827dd7cddfSDavid du Colombier * a DWORD at 0xCF8 and another at 0xCFC and will pass through
1837dd7cddfSDavid du Colombier * any non-DWORD accesses as normal I/O cycles. There shouldn't be
1847dd7cddfSDavid du Colombier * a device behind these addresses so if Mode2 accesses fail try
1857dd7cddfSDavid du Colombier * for Mode1 (which is preferred, Mode2 is deprecated).
1867dd7cddfSDavid du Colombier */
1877dd7cddfSDavid du Colombier outportb(PciCSE, 0);
1887dd7cddfSDavid du Colombier if(inportb(PciCSE) == 0){
1897dd7cddfSDavid du Colombier pcicfgmode = 2;
1907dd7cddfSDavid du Colombier pcimaxdno = 15;
1917dd7cddfSDavid du Colombier }
1927dd7cddfSDavid du Colombier else{
1937dd7cddfSDavid du Colombier outportl(PciADDR, 0);
1947dd7cddfSDavid du Colombier if(inportl(PciADDR) == 0){
1957dd7cddfSDavid du Colombier pcicfgmode = 1;
1967dd7cddfSDavid du Colombier pcimaxdno = 31;
1977dd7cddfSDavid du Colombier }
1987dd7cddfSDavid du Colombier }
1997dd7cddfSDavid du Colombier
2007dd7cddfSDavid du Colombier if(pcicfgmode > 0){
2017dd7cddfSDavid du Colombier list = &pciroot;
2027dd7cddfSDavid du Colombier for(bno = 0; bno < 256; bno++){
2037dd7cddfSDavid du Colombier bno = pciscan(bno, list);
2047dd7cddfSDavid du Colombier while(*list)
2057dd7cddfSDavid du Colombier list = &(*list)->link;
2067dd7cddfSDavid du Colombier }
2077dd7cddfSDavid du Colombier
2087dd7cddfSDavid du Colombier }
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier static int
pcicfgrw8(int tbdf,int rno,int data,int read)2137dd7cddfSDavid du Colombier pcicfgrw8(int tbdf, int rno, int data, int read)
2147dd7cddfSDavid du Colombier {
2157dd7cddfSDavid du Colombier int o, type, x;
2167dd7cddfSDavid du Colombier
2177dd7cddfSDavid du Colombier if(pcicfgmode == -1)
2187dd7cddfSDavid du Colombier pcicfginit();
2197dd7cddfSDavid du Colombier
2207dd7cddfSDavid du Colombier if(BUSBNO(tbdf))
2217dd7cddfSDavid du Colombier type = 0x01;
2227dd7cddfSDavid du Colombier else
2237dd7cddfSDavid du Colombier type = 0x00;
2247dd7cddfSDavid du Colombier x = -1;
2257dd7cddfSDavid du Colombier if(BUSDNO(tbdf) > pcimaxdno)
2267dd7cddfSDavid du Colombier return x;
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier switch(pcicfgmode){
2297dd7cddfSDavid du Colombier
2307dd7cddfSDavid du Colombier case 1:
2317dd7cddfSDavid du Colombier o = rno & 0x03;
2327dd7cddfSDavid du Colombier rno &= ~0x03;
2337dd7cddfSDavid du Colombier outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
2347dd7cddfSDavid du Colombier if(read)
2357dd7cddfSDavid du Colombier x = inportb(PciDATA+o);
2367dd7cddfSDavid du Colombier else
2377dd7cddfSDavid du Colombier outportb(PciDATA+o, data);
2387dd7cddfSDavid du Colombier outportl(PciADDR, 0);
2397dd7cddfSDavid du Colombier break;
2407dd7cddfSDavid du Colombier
2417dd7cddfSDavid du Colombier case 2:
2427dd7cddfSDavid du Colombier outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
2437dd7cddfSDavid du Colombier outportb(PciFORWARD, BUSBNO(tbdf));
2447dd7cddfSDavid du Colombier if(read)
2457dd7cddfSDavid du Colombier x = inportb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
2467dd7cddfSDavid du Colombier else
2477dd7cddfSDavid du Colombier outportb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
2487dd7cddfSDavid du Colombier outportb(PciCSE, 0);
2497dd7cddfSDavid du Colombier break;
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier
2527dd7cddfSDavid du Colombier return x;
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier int
pcicfgr8(Pcidev * pcidev,int rno)2567dd7cddfSDavid du Colombier pcicfgr8(Pcidev* pcidev, int rno)
2577dd7cddfSDavid du Colombier {
2587dd7cddfSDavid du Colombier return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
2597dd7cddfSDavid du Colombier }
2607dd7cddfSDavid du Colombier
2617dd7cddfSDavid du Colombier void
pcicfgw8(Pcidev * pcidev,int rno,int data)2627dd7cddfSDavid du Colombier pcicfgw8(Pcidev* pcidev, int rno, int data)
2637dd7cddfSDavid du Colombier {
2647dd7cddfSDavid du Colombier pcicfgrw8(pcidev->tbdf, rno, data, 0);
2657dd7cddfSDavid du Colombier }
2667dd7cddfSDavid du Colombier
2677dd7cddfSDavid du Colombier static int
pcicfgrw16(int tbdf,int rno,int data,int read)2687dd7cddfSDavid du Colombier pcicfgrw16(int tbdf, int rno, int data, int read)
2697dd7cddfSDavid du Colombier {
2707dd7cddfSDavid du Colombier int o, type, x;
2717dd7cddfSDavid du Colombier
2727dd7cddfSDavid du Colombier if(pcicfgmode == -1)
2737dd7cddfSDavid du Colombier pcicfginit();
2747dd7cddfSDavid du Colombier
2757dd7cddfSDavid du Colombier if(BUSBNO(tbdf))
2767dd7cddfSDavid du Colombier type = 0x01;
2777dd7cddfSDavid du Colombier else
2787dd7cddfSDavid du Colombier type = 0x00;
2797dd7cddfSDavid du Colombier x = -1;
2807dd7cddfSDavid du Colombier if(BUSDNO(tbdf) > pcimaxdno)
2817dd7cddfSDavid du Colombier return x;
2827dd7cddfSDavid du Colombier
2837dd7cddfSDavid du Colombier switch(pcicfgmode){
2847dd7cddfSDavid du Colombier
2857dd7cddfSDavid du Colombier case 1:
2867dd7cddfSDavid du Colombier o = rno & 0x02;
2877dd7cddfSDavid du Colombier rno &= ~0x03;
2887dd7cddfSDavid du Colombier outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
2897dd7cddfSDavid du Colombier if(read)
2907dd7cddfSDavid du Colombier x = inportw(PciDATA+o);
2917dd7cddfSDavid du Colombier else
2927dd7cddfSDavid du Colombier outportw(PciDATA+o, data);
2937dd7cddfSDavid du Colombier outportl(PciADDR, 0);
2947dd7cddfSDavid du Colombier break;
2957dd7cddfSDavid du Colombier
2967dd7cddfSDavid du Colombier case 2:
2977dd7cddfSDavid du Colombier outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
2987dd7cddfSDavid du Colombier outportb(PciFORWARD, BUSBNO(tbdf));
2997dd7cddfSDavid du Colombier if(read)
3007dd7cddfSDavid du Colombier x = inportw((0xC000|(BUSDNO(tbdf)<<8)) + rno);
3017dd7cddfSDavid du Colombier else
3027dd7cddfSDavid du Colombier outportw((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
3037dd7cddfSDavid du Colombier outportb(PciCSE, 0);
3047dd7cddfSDavid du Colombier break;
3057dd7cddfSDavid du Colombier }
3067dd7cddfSDavid du Colombier
3077dd7cddfSDavid du Colombier return x;
3087dd7cddfSDavid du Colombier }
3097dd7cddfSDavid du Colombier
3107dd7cddfSDavid du Colombier int
pcicfgr16(Pcidev * pcidev,int rno)3117dd7cddfSDavid du Colombier pcicfgr16(Pcidev* pcidev, int rno)
3127dd7cddfSDavid du Colombier {
3137dd7cddfSDavid du Colombier return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier
3167dd7cddfSDavid du Colombier void
pcicfgw16(Pcidev * pcidev,int rno,int data)3177dd7cddfSDavid du Colombier pcicfgw16(Pcidev* pcidev, int rno, int data)
3187dd7cddfSDavid du Colombier {
3197dd7cddfSDavid du Colombier pcicfgrw16(pcidev->tbdf, rno, data, 0);
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier
3227dd7cddfSDavid du Colombier static int
pcicfgrw32(int tbdf,int rno,int data,int read)3237dd7cddfSDavid du Colombier pcicfgrw32(int tbdf, int rno, int data, int read)
3247dd7cddfSDavid du Colombier {
3257dd7cddfSDavid du Colombier int type, x;
3267dd7cddfSDavid du Colombier
3277dd7cddfSDavid du Colombier if(pcicfgmode == -1)
3287dd7cddfSDavid du Colombier pcicfginit();
3297dd7cddfSDavid du Colombier
3307dd7cddfSDavid du Colombier if(BUSBNO(tbdf))
3317dd7cddfSDavid du Colombier type = 0x01;
3327dd7cddfSDavid du Colombier else
3337dd7cddfSDavid du Colombier type = 0x00;
3347dd7cddfSDavid du Colombier x = -1;
3357dd7cddfSDavid du Colombier if(BUSDNO(tbdf) > pcimaxdno)
3367dd7cddfSDavid du Colombier return x;
3377dd7cddfSDavid du Colombier
3387dd7cddfSDavid du Colombier switch(pcicfgmode){
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier case 1:
3417dd7cddfSDavid du Colombier rno &= ~0x03;
3427dd7cddfSDavid du Colombier outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
3437dd7cddfSDavid du Colombier if(read)
3447dd7cddfSDavid du Colombier x = inportl(PciDATA);
3457dd7cddfSDavid du Colombier else
3467dd7cddfSDavid du Colombier outportl(PciDATA, data);
3477dd7cddfSDavid du Colombier outportl(PciADDR, 0);
3487dd7cddfSDavid du Colombier break;
3497dd7cddfSDavid du Colombier
3507dd7cddfSDavid du Colombier case 2:
3517dd7cddfSDavid du Colombier outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
3527dd7cddfSDavid du Colombier outportb(PciFORWARD, BUSBNO(tbdf));
3537dd7cddfSDavid du Colombier if(read)
3547dd7cddfSDavid du Colombier x = inportl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
3557dd7cddfSDavid du Colombier else
3567dd7cddfSDavid du Colombier outportl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
3577dd7cddfSDavid du Colombier outportb(PciCSE, 0);
3587dd7cddfSDavid du Colombier break;
3597dd7cddfSDavid du Colombier }
3607dd7cddfSDavid du Colombier
3617dd7cddfSDavid du Colombier return x;
3627dd7cddfSDavid du Colombier }
3637dd7cddfSDavid du Colombier
3647dd7cddfSDavid du Colombier int
pcicfgr32(Pcidev * pcidev,int rno)3657dd7cddfSDavid du Colombier pcicfgr32(Pcidev* pcidev, int rno)
3667dd7cddfSDavid du Colombier {
3677dd7cddfSDavid du Colombier return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
3687dd7cddfSDavid du Colombier }
3697dd7cddfSDavid du Colombier
3707dd7cddfSDavid du Colombier void
pcicfgw32(Pcidev * pcidev,int rno,int data)3717dd7cddfSDavid du Colombier pcicfgw32(Pcidev* pcidev, int rno, int data)
3727dd7cddfSDavid du Colombier {
3737dd7cddfSDavid du Colombier pcicfgrw32(pcidev->tbdf, rno, data, 0);
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier Pcidev*
pcimatch(Pcidev * prev,int vid,int did)3777dd7cddfSDavid du Colombier pcimatch(Pcidev* prev, int vid, int did)
3787dd7cddfSDavid du Colombier {
3797dd7cddfSDavid du Colombier if(pcicfgmode == -1)
3807dd7cddfSDavid du Colombier pcicfginit();
3817dd7cddfSDavid du Colombier
3827dd7cddfSDavid du Colombier if(prev == nil)
3837dd7cddfSDavid du Colombier prev = pcilist;
3847dd7cddfSDavid du Colombier else
3857dd7cddfSDavid du Colombier prev = prev->list;
3867dd7cddfSDavid du Colombier
3877dd7cddfSDavid du Colombier while(prev != nil) {
3887dd7cddfSDavid du Colombier if(prev->vid == vid && (did == 0 || prev->did == did))
3897dd7cddfSDavid du Colombier break;
3907dd7cddfSDavid du Colombier prev = prev->list;
3917dd7cddfSDavid du Colombier }
3927dd7cddfSDavid du Colombier return prev;
3937dd7cddfSDavid du Colombier }
3947dd7cddfSDavid du Colombier
3957dd7cddfSDavid du Colombier void
pcihinv(Pcidev * p)3967dd7cddfSDavid du Colombier pcihinv(Pcidev* p)
3977dd7cddfSDavid du Colombier {
3987dd7cddfSDavid du Colombier int i;
3997dd7cddfSDavid du Colombier Pcidev *t;
4007dd7cddfSDavid du Colombier
4017dd7cddfSDavid du Colombier if(pcicfgmode == -1)
4027dd7cddfSDavid du Colombier pcicfginit();
4037dd7cddfSDavid du Colombier
4047dd7cddfSDavid du Colombier
4057dd7cddfSDavid du Colombier if(p == nil) {
4067dd7cddfSDavid du Colombier p = pciroot;
4077dd7cddfSDavid du Colombier Bprint(&stdout, "bus dev type vid did intl memory\n");
4087dd7cddfSDavid du Colombier }
4097dd7cddfSDavid du Colombier for(t = p; t != nil; t = t->link) {
4107dd7cddfSDavid du Colombier Bprint(&stdout, "%d %2d/%d %.4ux %.4ux %.4ux %2d ",
4117dd7cddfSDavid du Colombier BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
4127dd7cddfSDavid du Colombier t->ccru, t->vid, t->did, t->intl);
4137dd7cddfSDavid du Colombier
4147dd7cddfSDavid du Colombier for(i = 0; i < nelem(p->mem); i++) {
4157dd7cddfSDavid du Colombier if(t->mem[i].size == 0)
4167dd7cddfSDavid du Colombier continue;
4177dd7cddfSDavid du Colombier Bprint(&stdout, "%d:%.8lux %d ", i,
4187dd7cddfSDavid du Colombier t->mem[i].bar, t->mem[i].size);
4197dd7cddfSDavid du Colombier }
4207dd7cddfSDavid du Colombier Bprint(&stdout, "\n");
4217dd7cddfSDavid du Colombier }
4227dd7cddfSDavid du Colombier while(p != nil) {
4237dd7cddfSDavid du Colombier if(p->bridge != nil)
4247dd7cddfSDavid du Colombier pcihinv(p->bridge);
4257dd7cddfSDavid du Colombier p = p->link;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier }
428