From 6e8d0bf5006657c22463000d06254cb3b0ce110d Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 14 May 2012 18:09:19 +0200 Subject: [PATCH] mp: cleanup allocvector, allow sharing of edge triggered interrupts, more southbridges --- sys/src/9/pc/mp.c | 74 +++++++++++++++++++--------------------------- sys/src/9/pc/pci.c | 22 +++++++++----- 2 files changed, 45 insertions(+), 51 deletions(-) diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c index 5e981ee15..bba892b71 100644 --- a/sys/src/9/pc/mp.c +++ b/sys/src/9/pc/mp.c @@ -259,7 +259,6 @@ mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/) el = intr->flags & PcmpELMASK; switch(intr->intr){ - default: /* PcmpINT */ v |= ApicFIXED; /* no-op */ break; @@ -598,7 +597,6 @@ mpinit(void) if(getconf("*mp") != nil) mpoverride(&p, &e); while(p < e) switch(*p){ - default: print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", *p, e-p); @@ -738,20 +736,32 @@ mpintrcpu(void) return mpapic[i].apicno; } -/* hardcoded VectorAPIC and stuff. bad. */ +/* + * With the APIC a unique vector can be assigned to each + * request to enable an interrupt. There are two reasons this + * is a good idea: + * 1) to prevent lost interrupts, no more than 2 interrupts + * should be assigned per block of 16 vectors (there is an + * in-service entry and a holding entry for each priority + * level and there is one priority level per block of 16 + * interrupts). + * 2) each input pin on the IOAPIC will receive a different + * vector regardless of whether the devices on that pin use + * the same IRQ as devices on another pin. + */ static int allocvector(void) { - static int round = 0, num = 1; + static int round = 0, num = 0; static Lock l; int vno; lock(&l); - if(num >= 24) { - if(++round >= 8) round = 0; - num = 1; - } - vno = 64 + num++ * 8 + round; + vno = VectorAPIC + num; + if(vno < MaxVectorAPIC-7) + num += 8; + else + num = ++round % 8; unlock(&l); return vno; } @@ -780,7 +790,7 @@ mpintrenablex(Vctl* v, int tbdf) break; } if(bus == nil){ - print("ioapicirq: can't find bus type %d, number %d\n", type, bno); + print("mpintrenable: can't find bus type %d, number %d\n", type, bno); return -1; } @@ -796,7 +806,6 @@ mpintrenablex(Vctl* v, int tbdf) irq = (dno<<2)|(n-1); else irq = -1; - //print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq); } else irq = v->irq; @@ -808,9 +817,8 @@ mpintrenablex(Vctl* v, int tbdf) for(aintr = bus->aintr; aintr; aintr = aintr->next){ if(aintr->intr->irq != irq) continue; - if (0) { + if(0){ PCMPintr* p = aintr->intr; - print("mpintrenablex: bus %d intin %d irq %d\n", p->busno, p->intin, p->irq); } @@ -828,55 +836,34 @@ mpintrenablex(Vctl* v, int tbdf) ioapicrdtr(apic, aintr->intr->intin, 0, &lo); if(!(lo & ApicIMASK)){ vno = lo & 0xFF; -//print("%s vector %d (!imask)\n", v->name, vno); + if(0) print("%s vector %d (!imask)\n", v->name, vno); n = mpintrinit(bus, aintr->intr, vno, v->irq); n |= ApicPHYSICAL; /* no-op */ lo &= ~(ApicRemoteIRR|ApicDELIVS); - if(n != lo || !(n & ApicLEVEL)){ + if(n != lo){ print("mpintrenable: multiple botch irq %d, tbdf %uX, lo %8.8uX, n %8.8uX\n", v->irq, tbdf, lo, n); return -1; } - v->isr = lapicisr; v->eoi = lapiceoi; - return vno; } - /* - * With the APIC a unique vector can be assigned to each - * request to enable an interrupt. There are two reasons this - * is a good idea: - * 1) to prevent lost interrupts, no more than 2 interrupts - * should be assigned per block of 16 vectors (there is an - * in-service entry and a holding entry for each priority - * level and there is one priority level per block of 16 - * interrupts). - * 2) each input pin on the IOAPIC will receive a different - * vector regardless of whether the devices on that pin use - * the same IRQ as devices on another pin. - */ vno = allocvector(); hi = mpintrcpu()<<24; lo = mpintrinit(bus, aintr->intr, vno, v->irq); - //print("lo 0x%uX: busno %d intr %d vno %d irq %d elcr 0x%uX\n", - // lo, bus->busno, aintr->intr->irq, vno, - // v->irq, i8259elcr); - if(lo & ApicIMASK) - return -1; - lo |= ApicPHYSICAL; /* no-op */ - + if(lo & ApicIMASK){ + print("mpintrenable: disabled irq %d, tbdf %uX, lo %8.8uX, hi %8.8uX\n", + v->irq, tbdf, lo, hi); + return -1; + } if((apic->flags & PcmpEN) && apic->type == PcmpIOAPIC) ioapicrdtw(apic, aintr->intr->intin, hi, lo); - //else - // print("lo not enabled 0x%uX %d\n", - // apic->flags, apic->type); v->isr = lapicisr; v->eoi = lapiceoi; - return vno; } @@ -903,7 +890,7 @@ msiintrenable(Vctl *v) return -1; pci = pcimatchtbdf(tbdf); if(pci == nil) { - print("msiintrenable: could not find Pcidev for tbdf %.8x\n", tbdf); + print("msiintrenable: could not find Pcidev for tbdf %uX\n", tbdf); return -1; } cap = pcicap(pci, PciCapMSI); @@ -916,7 +903,6 @@ msiintrenable(Vctl *v) if(ok64) pcicfgw32(pci, cap + MSIAddr + 4, 0); pcicfgw16(pci, cap + (ok64 ? MSIData64 : MSIData32), vno | (1<<14)); pcicfgw16(pci, cap + MSICtrl, 1); - print("msiintrenable: success with tbdf %.8x, vector %d, cpu %d\n", tbdf, vno, cpu); v->isr = lapicisr; v->eoi = lapiceoi; return vno; @@ -973,7 +959,7 @@ mpintrenable(Vctl* v) if(vno != -1) return vno; } - print("mpintrenable: out of choices eisa %d isa %d tbdf %#ux irq %d\n", + print("mpintrenable: out of choices eisa %d isa %d tbdf %uX irq %d\n", mpeisabus, mpisabus, v->tbdf, v->irq); return -1; } diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c index f36f01baf..41904f322 100644 --- a/sys/src/9/pc/pci.c +++ b/sys/src/9/pc/pci.c @@ -655,9 +655,15 @@ 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, 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, 0x2810, pIIxget, pIIxset }, /* Intel 82801HB/HR (ich8/r) */ { 0x8086, 0x2812, pIIxget, pIIxset }, /* Intel 82801HH (ich8dh) */ { 0x8086, 0x2912, pIIxget, pIIxset }, /* Intel 82801ih ich9dh */ @@ -672,6 +678,7 @@ static Bridge southbridges[] = { { 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801ji */ { 0x8086, 0x3b06, pIIxget, pIIxset }, /* Intel 82801? ibex peak */ { 0x8086, 0x3b14, pIIxget, pIIxset }, /* Intel 82801? 3420 */ + { 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 */ @@ -684,15 +691,16 @@ static Bridge southbridges[] = { { 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; @@ -986,7 +994,7 @@ pcicfginit(void) 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)