]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/pci.c
kernel: cleanup /sys/src/9/pc/mkfile PORT= and OBJ= lists
[plan9front.git] / sys / src / 9 / pc / pci.c
index 6ad5d36639a132ce7e71e818fea5988b415d206b..c88983f45b03db13e91d0552e54ead17f2646c8b 100644 (file)
@@ -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