X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2F9%2Fpc%2Fpci.c;h=c88983f45b03db13e91d0552e54ead17f2646c8b;hb=8b40eecea8905cd70b240df77b0f30814a2adf73;hp=6ad5d36639a132ce7e71e818fea5988b415d206b;hpb=fe668572ff7b8c8968f78bd9173d7d1c6e624a23;p=plan9front.git diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c index 6ad5d3663..c88983f45 100644 --- a/sys/src/9/pc/pci.c +++ b/sys/src/9/pc/pci.c @@ -60,7 +60,7 @@ enum static Lock pcicfglock; static Lock pcicfginitlock; static int pcicfgmode = -1; -static int pcimaxbno = 7; +static int pcimaxbno = 255; static int pcimaxdno; static Pcidev* pciroot; static Pcidev* pcilist; @@ -200,6 +200,8 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) ntb *= (PciCIS-PciBAR0)/4; table = malloc(2*ntb*sizeof(Pcisiz)); + if(table == nil) + panic("pcibusmap: can't allocate memory"); itb = table; mtb = table+ntb; @@ -365,7 +367,7 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) } static int -pcilscan(int bno, Pcidev** list) +pcilscan(int bno, Pcidev** list, Pcidev *parent) { Pcidev *p, *head, *tail; int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; @@ -389,6 +391,8 @@ pcilscan(int bno, Pcidev** list) if(l == 0xFFFFFFFF || l == 0) continue; p = malloc(sizeof(*p)); + if(p == nil) + panic("pcilscan: can't allocate memory"); p->tbdf = tbdf; p->vid = l; p->did = l>>16; @@ -449,6 +453,7 @@ pcilscan(int bno, Pcidev** list) break; } + p->parent = parent; if(head != nil) tail->link = p; else @@ -490,7 +495,7 @@ pcilscan(int bno, Pcidev** list) l = (MaxUBN<<16)|(sbn<<8)|bno; pcicfgw32(p, PciPBN, l); pcicfgw16(p, PciSPSR, 0xFFFF); - maxubn = pcilscan(sbn, &p->bridge); + maxubn = pcilscan(sbn, &p->bridge, p); l = (maxubn<<16)|(sbn<<8)|bno; pcicfgw32(p, PciPBN, l); @@ -498,7 +503,7 @@ pcilscan(int bno, Pcidev** list) else { if(ubn > maxubn) maxubn = ubn; - pcilscan(sbn, &p->bridge); + pcilscan(sbn, &p->bridge, p); } } @@ -511,7 +516,7 @@ pciscan(int bno, Pcidev **list) int ubn; lock(&pcicfginitlock); - ubn = pcilscan(bno, list); + ubn = pcilscan(bno, list, nil); unlock(&pcicfginitlock); return ubn; } @@ -640,7 +645,9 @@ static Bridge southbridges[] = { { 0x8086, 0x2410, pIIxget, pIIxset }, /* Intel 82801AA */ { 0x8086, 0x2420, pIIxget, pIIxset }, /* Intel 82801AB */ { 0x8086, 0x2440, pIIxget, pIIxset }, /* Intel 82801BA */ + { 0x8086, 0x2448, pIIxget, pIIxset }, /* Intel 82801BAM/CAM/DBM */ { 0x8086, 0x244c, pIIxget, pIIxset }, /* Intel 82801BAM */ + { 0x8086, 0x244e, pIIxget, pIIxset }, /* Intel 82801 */ { 0x8086, 0x2480, pIIxget, pIIxset }, /* Intel 82801CA */ { 0x8086, 0x248c, pIIxget, pIIxset }, /* Intel 82801CAM */ { 0x8086, 0x24c0, pIIxget, pIIxset }, /* Intel 82801DBL */ @@ -649,26 +656,59 @@ static Bridge southbridges[] = { { 0x8086, 0x25a1, pIIxget, pIIxset }, /* Intel 6300ESB */ { 0x8086, 0x2640, pIIxget, pIIxset }, /* Intel 82801FB */ { 0x8086, 0x2641, pIIxget, pIIxset }, /* Intel 82801FBM */ + { 0x8086, 0x2670, pIIxget, pIIxset }, /* Intel 632xesb */ { 0x8086, 0x27b8, pIIxget, pIIxset }, /* Intel 82801GB */ { 0x8086, 0x27b9, pIIxget, pIIxset }, /* Intel 82801GBM */ + { 0x8086, 0x27bd, pIIxget, pIIxset }, /* Intel 82801GB/GR */ + { 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801JIR */ + { 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801JI */ + { 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801JI */ + { 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801JI */ { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801? */ + { 0x8086, 0x1c02, pIIxget, pIIxset }, /* Intel 6 Series/C200 */ + { 0x8086, 0x1e53, pIIxget, pIIxset }, /* Intel 7 Series/C216 */ + { 0x8086, 0x2810, pIIxget, pIIxset }, /* Intel 82801HB/HR (ich8/r) */ + { 0x8086, 0x2812, pIIxget, pIIxset }, /* Intel 82801HH (ich8dh) */ + { 0x8086, 0x2912, pIIxget, pIIxset }, /* Intel 82801ih ich9dh */ + { 0x8086, 0x2914, pIIxget, pIIxset }, /* Intel 82801io ich9do */ + { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801ibr ich9r */ + { 0x8086, 0x2917, pIIxget, pIIxset }, /* Intel 82801iem ich9m-e */ + { 0x8086, 0x2918, pIIxget, pIIxset }, /* Intel 82801ib ich9 */ + { 0x8086, 0x2919, pIIxget, pIIxset }, /* Intel 82801? ich9m */ + { 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801jir ich10r */ + { 0x8086, 0x3a18, pIIxget, pIIxset }, /* Intel 82801jib ich10 */ + { 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801ji */ + { 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801ji */ + { 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801ji */ + { 0x8086, 0x3b06, pIIxget, pIIxset }, /* Intel 82801? ibex peak */ + { 0x8086, 0x3b14, pIIxget, pIIxset }, /* Intel 82801? 3420 */ + { 0x8086, 0x1c49, pIIxget, pIIxset }, /* Intel 82hm65 cougar point pch */ + { 0x8086, 0x1c4f, pIIxget, pIIxset }, /* Intel 82qm67 cougar point pch */ + { 0x8086, 0x1c52, pIIxget, pIIxset }, /* Intel 82q65 cougar point pch */ + { 0x8086, 0x1c54, pIIxget, pIIxset }, /* Intel 82q67 cougar point pch */ { 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */ { 0x1106, 0x0596, viaget, viaset }, /* Viatech 82C596 */ { 0x1106, 0x0686, viaget, viaset }, /* Viatech 82C686 */ + { 0x1106, 0x3177, viaget, viaset }, /* Viatech VT8235 */ { 0x1106, 0x3227, viaget, viaset }, /* Viatech VT8237 */ + { 0x1106, 0x3287, viaget, viaset }, /* Viatech VT8251 */ + { 0x1106, 0x8410, viaget, viaset }, /* Viatech PV530 bridge */ { 0x1045, 0xc700, optiget, optiset }, /* Opti 82C700 */ { 0x10b9, 0x1533, aliget, aliset }, /* Al M1533 */ { 0x1039, 0x0008, pIIxget, pIIxset }, /* SI 503 */ { 0x1039, 0x0496, pIIxget, pIIxset }, /* SI 496 */ { 0x1078, 0x0100, cyrixget, cyrixset }, /* Cyrix 5530 Legacy */ - { 0x1022, 0x746B, nil, nil }, /* AMD 8111 */ - { 0x10DE, 0x00D1, nil, nil }, /* NVIDIA nForce 3 */ - { 0x10DE, 0x00E0, nil, nil }, /* NVIDIA nForce 3 250 Series */ - { 0x10DE, 0x00E1, nil, nil }, /* NVIDIA nForce 3 250 Series */ + { 0x1022, 0x746b, nil, nil }, /* AMD 8111 */ + { 0x10de, 0x00d1, nil, nil }, /* NVIDIA nForce 3 */ + { 0x10de, 0x00e0, nil, nil }, /* NVIDIA nForce 3 250 Series */ + { 0x10de, 0x00e1, nil, nil }, /* NVIDIA nForce 3 250 Series */ { 0x1166, 0x0200, nil, nil }, /* ServerWorks ServerSet III LE */ { 0x1002, 0x4377, nil, nil }, /* ATI Radeon Xpress 200M */ { 0x1002, 0x4372, nil, nil }, /* ATI SB400 */ + { 0x1002, 0x9601, nil, nil }, /* AMD SB710 */ + { 0x1002, 0x438d, nil, nil }, /* AMD SB600 */ + { 0x1002, 0x439d, nil, nil }, /* AMD SB810 */ }; typedef struct Slot Slot; @@ -706,18 +746,16 @@ pcirouting(void) Pcidev *sbpci, *pci; uchar *p, pin, irq, link, *map; - /* Search for PCI interrupt routing table in BIOS */ - for(p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16) - if(p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R') - break; - - if(p >= (uchar *)KADDR(0xfffff)) + if((p = sigsearch("$PIR")) == 0) return; - r = (Router *)p; + r = (Router*)p; + size = (r->size[1] << 8)|r->size[0]; + if(size < sizeof(Router) || checksum(r, size)) + return; - // print("PCI interrupt routing table version %d.%d at %.6uX\n", - // r->version[0], r->version[1], (ulong)r & 0xfffff); + if(0) print("PCI interrupt routing table version %d.%d at %p\n", + r->version[0], r->version[1], r); tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8); sbpci = pcimatchtbdf(tbdf); @@ -739,8 +777,6 @@ pcirouting(void) return; pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0]; - - size = (r->size[1] << 8)|r->size[0]; for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) { if (0) { print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot); @@ -961,11 +997,8 @@ pcicfginit(void) fmtinstall('T', tbdffmt); - if(p = getconf("*pcimaxbno")){ - n = strtoul(p, 0, 0); - if(n < pcimaxbno) - pcimaxbno = n; - } + if(p = getconf("*pcimaxbno")) + pcimaxbno = strtoul(p, 0, 0); if(p = getconf("*pcimaxdno")){ n = strtoul(p, 0, 0); if(n < pcimaxdno) @@ -975,7 +1008,7 @@ pcicfginit(void) list = &pciroot; for(bno = 0; bno <= pcimaxbno; bno++) { int sbno = bno; - bno = pcilscan(bno, list); + bno = pcilscan(bno, list, nil); while(*list) list = &(*list)->link; @@ -1020,11 +1053,10 @@ pcicfginit(void) pcibusmap(pciroot, &mema, &ioa, 1); DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa); - unlock(&pcicfginitlock); - return; + goto out; } - if (!nopcirouting) + if(!nopcirouting) pcirouting(); out: @@ -1381,53 +1413,46 @@ pciclrmwi(Pcidev* p) pcicfgw16(p, PciPCR, p->pcr); } +int +pcicap(Pcidev *p, int cap) +{ + int i, c, off; + + /* status register bit 4 has capabilities */ + if((pcicfgr16(p, PciPSR) & 1<<4) == 0) + return -1; + switch(pcicfgr8(p, PciHDT) & 0x7F){ + default: + return -1; + case 0: /* etc */ + case 1: /* pci to pci bridge */ + off = 0x34; + break; + case 2: /* cardbus bridge */ + off = 0x14; + break; + } + for(i = 48; i--;){ + off = pcicfgr8(p, off); + if(off < 0x40 || (off & 3)) + break; + off &= ~3; + c = pcicfgr8(p, off); + if(c == 0xff) + break; + if(c == cap) + return off; + off++; + } + return -1; +} + static int pcigetpmrb(Pcidev* p) { - int ptr; - - if(p->pmrb != 0) - return p->pmrb; - p->pmrb = -1; - - /* - * If there are no extended capabilities implemented, - * (bit 4 in the status register) assume there's no standard - * power management method. - * Find the capabilities pointer based on PCI header type. - */ - if(!(pcicfgr16(p, PciPSR) & 0x0010)) - return -1; - switch(pcicfgr8(p, PciHDT)){ - default: - return -1; - case 0: /* all other */ - case 1: /* PCI to PCI bridge */ - ptr = 0x34; - break; - case 2: /* CardBus bridge */ - ptr = 0x14; - break; - } - ptr = pcicfgr32(p, ptr); - - while(ptr != 0){ - /* - * Check for validity. - * Can't be in standard header and must be double - * word aligned. - */ - if(ptr < 0x40 || (ptr & ~0xFC)) - return -1; - if(pcicfgr8(p, ptr) == 0x01){ - p->pmrb = ptr; - return ptr; - } - - ptr = pcicfgr8(p, ptr+1); - } - - return -1; + if(p->pmrb != 0) + return p->pmrb; + return p->pmrb = pcicap(p, PciCapPMG); } int