}
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;
break;
}
+ p->parent = parent;
if(head != nil)
tail->link = p;
else
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);
else {
if(ubn > maxubn)
maxubn = ubn;
- pcilscan(sbn, &p->bridge);
+ pcilscan(sbn, &p->bridge, p);
}
}
int ubn;
lock(&pcicfginitlock);
- ubn = pcilscan(bno, list);
+ ubn = pcilscan(bno, list, nil);
unlock(&pcicfginitlock);
return ubn;
}
{ 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, 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, 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, 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, 0x438d, nil, nil }, /* AMD SB600 */
+ { 0x1002, 0x439d, nil, nil }, /* AMD SB810 */
};
typedef struct Slot Slot;
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);
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);
fmtinstall('T', tbdffmt);
if(p = getconf("*pcimaxbno"))
- pcimaxbno = strtoul(p, 0, 0) & 0xff;
+ pcimaxbno = strtoul(p, 0, 0);
if(p = getconf("*pcimaxdno")){
n = strtoul(p, 0, 0);
if(n < pcimaxdno)
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;
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:
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