summaryrefslogtreecommitdiffstats
path: root/sys/alpha/mcbus/mcpcia.c
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2001-02-13 22:48:12 +0000
committermjacob <mjacob@FreeBSD.org>2001-02-13 22:48:12 +0000
commit7e987d1dffccf9f5e300add01ae8314cf34165a1 (patch)
tree76610fdb100ec28be1fd95dbf31e548e24fba5a3 /sys/alpha/mcbus/mcpcia.c
parent3651ee34575a30029c99602b61eab92a015ea5ba (diff)
downloadFreeBSD-src-7e987d1dffccf9f5e300add01ae8314cf34165a1.zip
FreeBSD-src-7e987d1dffccf9f5e300add01ae8314cf34165a1.tar.gz
Doug found that doing a W1C on MCPCIA_INT_REQ just around the time you
clear MCPCIA_INT_MASK0 helps things substantially. So, why not indeed? Rearrange irq and cookie calculation to use shifts/masks instead of division. Fix things to correctly remember the intpin for that one in a million non-INTA PCI device.
Diffstat (limited to 'sys/alpha/mcbus/mcpcia.c')
-rw-r--r--sys/alpha/mcbus/mcpcia.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/sys/alpha/mcbus/mcpcia.c b/sys/alpha/mcbus/mcpcia.c
index 03bb36e..c66a9bc 100644
--- a/sys/alpha/mcbus/mcpcia.c
+++ b/sys/alpha/mcbus/mcpcia.c
@@ -246,7 +246,6 @@ mcpcia_attach(device_t dev)
static void
mcpcia_enable_intr(struct mcpcia_softc *sc, int irq)
{
- alpha_mb();
REGVAL(MCPCIA_INT_MASK0(sc)) |= (1 << irq);
alpha_mb();
}
@@ -254,9 +253,15 @@ mcpcia_enable_intr(struct mcpcia_softc *sc, int irq)
static void
mcpcia_disable_intr(struct mcpcia_softc *sc, int irq)
{
- alpha_mb();
- REGVAL(MCPCIA_INT_MASK0(sc)) &= ~(1 << irq);
- alpha_mb();
+ /*
+ * We need to write to INT_REQ as well as INT_MASK0 in case we
+ * are trying to mask an interrupt which is already
+ * asserted. Writing a 1 bit to INT_REQ clears the
+ * corresponding bit in the register.
+ */
+ REGVAL(MCPCIA_INT_MASK0(sc)) &= ~(1 << irq);
+ REGVAL(MCPCIA_INT_REQ(sc)) = (1 << irq);
+ alpha_mb();
}
static void
@@ -284,8 +289,7 @@ mcpcia_disable_intr_vec(int vector)
return;
}
tmp -= (2 * MCPCIA_VECWIDTH_PER_SLOT);
- irq = (tmp / MCPCIA_VECWIDTH_PER_INTPIN);
- irq = ((vector - 0x900) >> 4) - 8;
+ irq = (tmp >> MCPCIA_VECWIDTH_PER_INTPIN) & 0xf;
}
/* printf("D<%03x>=%d,%d\n", vector, mid, irq); */
while (sc) {
@@ -325,7 +329,7 @@ mcpcia_enable_intr_vec(int vector)
return;
}
tmp -= (2 * MCPCIA_VECWIDTH_PER_SLOT);
- irq = (tmp / MCPCIA_VECWIDTH_PER_INTPIN);
+ irq = (tmp >> MCPCIA_VECWIDTH_PER_INTPIN) & 0xf;
}
/* printf("E<%03x>=%d,%d\n", vector, mid, irq); */
while (sc) {
@@ -372,7 +376,7 @@ mcpcia_setup_intr(device_t dev, device_t child, struct resource *ir, int flags,
if (mid == 5 && slot == 1) {
irq = 16; /* MID 5, slot 1, is the internal NCR 53c810 */
} else if (slot >= 2 && slot <= 5) {
- irq = (slot - 2) * 4;
+ irq = ((slot - 2) * 4) + (intpin - 1);
} else {
device_printf(child, "weird slot number (%d); can't make irq\n",
slot);
@@ -389,12 +393,13 @@ mcpcia_setup_intr(device_t dev, device_t child, struct resource *ir, int flags,
if (irq == 16) {
h = MCPCIA_VEC_NCR;
} else {
- h = MCPCIA_VEC_PCI + ((mid - 4) * MCPCIA_VECWIDTH_PER_MCPCIA) +
+ h = MCPCIA_VEC_PCI +
+ ((mid - MCPCIA_PCI_MIDMIN) * MCPCIA_VECWIDTH_PER_MCPCIA) +
(slot * MCPCIA_VECWIDTH_PER_SLOT) +
((intpin - 1) * MCPCIA_VECWIDTH_PER_INTPIN);
}
birq = irq + INTRCNT_KN300_IRQ;
- error = alpha_setup_intr(device_get_nameunit(child ? child : dev), h,
+ error = alpha_setup_intr(device_get_nameunit(child), h,
intr, arg, flags, cp, &intrcnt[birq],
mcpcia_disable_intr_vec, mcpcia_enable_intr_vec);
if (error)
@@ -409,7 +414,17 @@ static int
mcpcia_teardown_intr(device_t dev, device_t child, struct resource *i, void *c)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
- int slot, mid, irq;
+ int slot, mid, intpin, irq;
+
+ intpin = pci_get_intpin(child);
+ if (intpin == 0) {
+ /* No IRQ used */
+ return (0);
+ }
+ if (intpin < 1 || intpin > 4) {
+ /* Bad IRQ */
+ return (ENXIO);
+ }
slot = pci_get_slot(child);
mid = mcbus_get_mid(dev);
@@ -417,7 +432,7 @@ mcpcia_teardown_intr(device_t dev, device_t child, struct resource *i, void *c)
if (mid == 5 && slot == 1) {
irq = 16;
} else if (slot >= 2 && slot <= 5) {
- irq = (slot - 2) * 4;
+ irq = ((slot - 2) << 4) + (intpin - 1);
} else {
return (ENXIO);
}
OpenPOWER on IntegriCloud