ref: d410c60593ddfa9d600b285ef90536186f9fd991
parent: 946a00708d95199113e9c9aa0849d2520bc413f4
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Mon May 14 14:09:19 EDT 2012
mp: cleanup allocvector, allow sharing of edge triggered interrupts, more southbridges
--- a/sys/src/9/pc/mp.c
+++ b/sys/src/9/pc/mp.c
@@ -259,7 +259,6 @@
el = intr->flags & PcmpELMASK;
switch(intr->intr){-
default: /* PcmpINT */
v |= ApicFIXED; /* no-op */
break;
@@ -598,7 +597,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
}
--- a/sys/src/9/pc/pci.c
+++ b/sys/src/9/pc/pci.c
@@ -655,9 +655,15 @@
{ 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 @@
{ 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 @@
{ 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 @@
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)
--
⑨