diff options
| author | Charles.Forsyth <devnull@localhost> | 2008-06-11 14:21:44 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2008-06-11 14:21:44 +0000 |
| commit | 8a8c2d742b51525f66c2210e3c8a251de10022ff (patch) | |
| tree | 8282ce595e5fbe2e487dc20f54891d9e9e7cbf37 /os/boot/pc/pci.c | |
| parent | 31a18a6996a6b5927e39cc553696c167e6c88e3d (diff) | |
20080611-1520
Diffstat (limited to 'os/boot/pc/pci.c')
| -rw-r--r-- | os/boot/pc/pci.c | 300 |
1 files changed, 225 insertions, 75 deletions
diff --git a/os/boot/pc/pci.c b/os/boot/pc/pci.c index c7b9eda5..a83a10fa 100644 --- a/os/boot/pc/pci.c +++ b/os/boot/pc/pci.c @@ -23,6 +23,16 @@ enum { /* configuration mechanism #1 */ MaxUBN = 255, }; +enum +{ /* command register */ + IOen = (1<<0), + MEMen = (1<<1), + MASen = (1<<2), + MemWrInv = (1<<4), + PErrEn = (1<<6), + SErrEn = (1<<8), +}; + static Lock pcicfglock; static Lock pcicfginitlock; static int pcicfgmode = -1; @@ -145,7 +155,8 @@ pciscan(int bno, Pcidev** list) *list = head; for(p = head; p != nil; p = p->link){ /* - * Find PCI-PCI and PCI-Cardbus bridges and recursively descend the tree. + * Find PCI-PCI and PCI-Cardbus bridges + * and recursively descend the tree. */ if(p->ccrb != 0x06 || p->ccru != 0x04) continue; @@ -181,7 +192,16 @@ pciscan(int bno, Pcidev** list) pcicfgw32(p, PciPBN, l); } else{ - maxubn = ubn; + /* + * You can't go back. + * This shouldn't be possible, but the + * Iwill DK8-HTX seems to have subordinate + * bus numbers which get smaller on the + * way down. Need to look more closely at + * this. + */ + if(ubn > maxubn) + maxubn = ubn; pciscan(sbn, &p->bridge); } } @@ -189,7 +209,18 @@ pciscan(int bno, Pcidev** list) return maxubn; } -static uchar +static uchar +null_link(Pcidev *, uchar ) +{ + return 0; +} + +static void +null_init(Pcidev *, uchar , uchar ) +{ +} + +static uchar pIIx_link(Pcidev *router, uchar link) { uchar pirq; @@ -199,13 +230,13 @@ pIIx_link(Pcidev *router, uchar link) return (pirq < 16)? pirq: 0; } -static void +static void pIIx_init(Pcidev *router, uchar link, uchar irq) { pcicfgw8(router, link, irq); } -static uchar +static uchar via_link(Pcidev *router, uchar link) { uchar pirq; @@ -216,7 +247,7 @@ via_link(Pcidev *router, uchar link) return (link & 1)? (pirq >> 4): (pirq & 15); } -static void +static void via_init(Pcidev *router, uchar link, uchar irq) { uchar pirq; @@ -227,7 +258,7 @@ via_init(Pcidev *router, uchar link, uchar irq) pcicfgw8(router, 0x55 + (link>>1), pirq); } -static uchar +static uchar opti_link(Pcidev *router, uchar link) { uchar pirq = 0; @@ -238,7 +269,7 @@ opti_link(Pcidev *router, uchar link) return (link & 0x10)? (pirq >> 4): (pirq & 15); } -static void +static void opti_init(Pcidev *router, uchar link, uchar irq) { uchar pirq; @@ -249,7 +280,7 @@ opti_init(Pcidev *router, uchar link, uchar irq) pcicfgw8(router, 0xb8 + (link >> 5), pirq); } -static uchar +static uchar ali_link(Pcidev *router, uchar link) { /* No, you're not dreaming */ @@ -261,7 +292,7 @@ ali_link(Pcidev *router, uchar link) return (link & 1)? map[pirq&15]: map[pirq>>4]; } -static void +static void ali_init(Pcidev *router, uchar link, uchar irq) { /* Inverse of map in ali_link */ @@ -274,7 +305,7 @@ ali_init(Pcidev *router, uchar link, uchar irq) pcicfgw8(router, 0x48 + ((link-1)>>1), pirq); } -static uchar +static uchar cyrix_link(Pcidev *router, uchar link) { uchar pirq; @@ -284,7 +315,7 @@ cyrix_link(Pcidev *router, uchar link) return ((link & 1)? pirq >> 4: pirq & 15); } -static void +static void cyrix_init(Pcidev *router, uchar link, uchar irq) { uchar pirq; @@ -295,64 +326,46 @@ cyrix_init(Pcidev *router, uchar link, uchar irq) pcicfgw8(router, 0x5c + (link>>1), pirq); } -enum { - Intel = 0x8086, - Intel_82371FB_0 = 0x122e, - Intel_82371MX_0 = 0x1234, - Intel_82371SB_0 = 0x7000, - Intel_82371AB_0 = 0x7110, - Intel_82443MX_1 = 0x7198, - Intel_82801AA_0 = 0x2410, - Intel_82801AB_0 = 0x2420, - Intel_82801BA_0 = 0x2440, - Intel_82801BAM_0 = 0x244c, - Intel_82801CAM_0 = 0x248c, - Intel_82801DBM_0 = 0x24cc, - Intel_82801EB_0 = 0x24d0, - Intel_82801FB_0 = 0x2640, - Viatech = 0x1106, - Via_82C586_0 = 0x0586, - Via_82C596 = 0x0596, - Via_82C686 = 0x0686, - Opti = 0x1045, - Opti_82C700 = 0xc700, - Al = 0x10b9, - Al_M1533 = 0x1533, - SI = 0x1039, - SI_503 = 0x0008, - SI_496 = 0x0496, - Cyrix = 0x1078, - Cyrix_5530_Legacy = 0x0100, -}; - typedef struct { ushort sb_vid, sb_did; uchar (*sb_translate)(Pcidev *, uchar); - void (*sb_initialize)(Pcidev *, uchar, uchar); + void (*sb_initialize)(Pcidev *, uchar, uchar); } bridge_t; static bridge_t southbridges[] = { -{ Intel, Intel_82371FB_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82371MX_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82371SB_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82371AB_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82443MX_1, pIIx_link, pIIx_init }, -{ Intel, Intel_82801AA_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82801AB_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82801BA_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82801BAM_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82801CAM_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82801DBM_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82801EB_0, pIIx_link, pIIx_init }, -{ Intel, Intel_82801FB_0, pIIx_link, pIIx_init }, -{ Viatech, Via_82C586_0, via_link, via_init }, -{ Viatech, Via_82C596, via_link, via_init }, -{ Viatech, Via_82C686, via_link, via_init }, -{ Opti, Opti_82C700, opti_link, opti_init }, -{ Al, Al_M1533, ali_link, ali_init }, -{ SI, SI_503, pIIx_link, pIIx_init }, -{ SI, SI_496, pIIx_link, pIIx_init }, -{ Cyrix, Cyrix_5530_Legacy, cyrix_link, cyrix_init } + { 0x8086, 0x122e, pIIx_link, pIIx_init }, // Intel 82371FB + { 0x8086, 0x1234, pIIx_link, pIIx_init }, // Intel 82371MX + { 0x8086, 0x7000, pIIx_link, pIIx_init }, // Intel 82371SB + { 0x8086, 0x7110, pIIx_link, pIIx_init }, // Intel 82371AB + { 0x8086, 0x7198, pIIx_link, pIIx_init }, // Intel 82443MX (fn 1) + { 0x8086, 0x2410, pIIx_link, pIIx_init }, // Intel 82801AA + { 0x8086, 0x2420, pIIx_link, pIIx_init }, // Intel 82801AB + { 0x8086, 0x2440, pIIx_link, pIIx_init }, // Intel 82801BA + { 0x8086, 0x244c, pIIx_link, pIIx_init }, // Intel 82801BAM + { 0x8086, 0x2480, pIIx_link, pIIx_init }, // Intel 82801CA + { 0x8086, 0x248c, pIIx_link, pIIx_init }, // Intel 82801CAM + { 0x8086, 0x24c0, pIIx_link, pIIx_init }, // Intel 82801DBL + { 0x8086, 0x24cc, pIIx_link, pIIx_init }, // Intel 82801DBM + { 0x8086, 0x24d0, pIIx_link, pIIx_init }, // Intel 82801EB + { 0x8086, 0x2640, pIIx_link, pIIx_init }, // Intel 82801FB + { 0x8086, 0x27b8, pIIx_link, pIIx_init }, // Intel 82801GB + { 0x8086, 0x27b9, pIIx_link, pIIx_init }, // Intel 82801GBM + { 0x1106, 0x0586, via_link, via_init }, // Viatech 82C586 + { 0x1106, 0x0596, via_link, via_init }, // Viatech 82C596 + { 0x1106, 0x0686, via_link, via_init }, // Viatech 82C686 + { 0x1106, 0x3227, via_link, via_init }, // Viatech VT8237 + { 0x1045, 0xc700, opti_link, opti_init }, // Opti 82C700 + { 0x10b9, 0x1533, ali_link, ali_init }, // Al M1533 + { 0x1039, 0x0008, pIIx_link, pIIx_init }, // SI 503 + { 0x1039, 0x0496, pIIx_link, pIIx_init }, // SI 496 + { 0x1078, 0x0100, cyrix_link, cyrix_init }, // Cyrix 5530 Legacy + + { 0x1002, 0x4377, nil, nil }, // ATI Radeon Xpress 200M + { 0x1002, 0x4372, nil, nil }, // ATI SB400 + { 0x1022, 0x746B, nil, nil }, // AMD 8111 + { 0x10DE, 0x00D1, nil, nil }, // NVIDIA nForce 3 + { 0x10DE, 0x00E0, nil, nil }, // NVIDIA nForce 3 250 Series + { 0x1166, 0x0200, nil, nil }, // ServerWorks ServerSet III LE }; typedef struct { @@ -423,7 +436,7 @@ pcirouting(void) vid, did); return; } - + pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0]; size = (r->rt_size[1] << 8)|r->rt_size[0]; @@ -443,12 +456,12 @@ pcirouting(void) // obtaining the Pcidev structure. tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8); vdid = pcicfgrw32(tbdf, PciVID, 0, 1); - if (vdid == 0xFFFFFFFF || vdid == 0) + if (vdid == 0xFFFFFFFF || vdid == 0) continue; vid = vdid; did = vdid >> 16; - + pci = nil; while ((pci = pcimatch(pci, vid, did)) != nil) { @@ -456,13 +469,13 @@ pcirouting(void) continue; pin = pcicfgr8(pci, PciINTP); - if (pin == 0 || pin == 0xff) + if (pin == 0 || pin == 0xff) continue; - + m = &e->e_maps[(pin - 1) * 3]; irq = southbridge->sb_translate(sbpci, m[0]); if (irq) { - print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n", + print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n", vid, did, pin, irq); pcicfgw8(pci, PciINTL, irq); pci->intl = irq; @@ -521,7 +534,7 @@ pcicfginit(void) } outb(PciCSE, n); } - + if(pcicfgmode < 0) goto out; @@ -841,12 +854,149 @@ pcireset(void) } void +pcisetioe(Pcidev* p) +{ + p->pcr |= IOen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pciclrioe(Pcidev* p) +{ + p->pcr &= ~IOen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void pcisetbme(Pcidev* p) { - int pcr; + p->pcr |= MASen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pciclrbme(Pcidev* p) +{ + p->pcr &= ~MASen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pcisetmwi(Pcidev* p) +{ + p->pcr |= MemWrInv; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pciclrmwi(Pcidev* p) +{ + p->pcr &= ~MemWrInv; + pcicfgw16(p, PciPCR, p->pcr); +} + +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; +} - pcr = pcicfgr16(p, PciPCR); - pcr |= 0x0004; - pcicfgw16(p, PciPCR, pcr); +int +pcigetpms(Pcidev* p) +{ + int pmcsr, ptr; + + if((ptr = pcigetpmrb(p)) == -1) + return -1; + + /* + * Power Management Register Block: + * offset 0: Capability ID + * 1: next item pointer + * 2: capabilities + * 4: control/status + * 6: bridge support extensions + * 7: data + */ + pmcsr = pcicfgr16(p, ptr+4); + + return pmcsr & 0x0003; } +int +pcisetpms(Pcidev* p, int state) +{ + int ostate, pmc, pmcsr, ptr; + + if((ptr = pcigetpmrb(p)) == -1) + return -1; + + pmc = pcicfgr16(p, ptr+2); + pmcsr = pcicfgr16(p, ptr+4); + ostate = pmcsr & 0x0003; + pmcsr &= ~0x0003; + + switch(state){ + default: + return -1; + case 0: + break; + case 1: + if(!(pmc & 0x0200)) + return -1; + break; + case 2: + if(!(pmc & 0x0400)) + return -1; + break; + case 3: + break; + } + pmcsr |= state; + pcicfgw16(p, ptr+4, pmcsr); + + return ostate; +} |
