summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2001-07-31 06:44:37 +0000
committerimp <imp@FreeBSD.org>2001-07-31 06:44:37 +0000
commit7ffebadcef03ef7d4c21bb2bacc7138cf1cce87a (patch)
treebf5b7745d1930fe2e8d980854cd090f6d9336f91 /sys
parentac051210c345e786944512f477e364d55b394ea1 (diff)
downloadFreeBSD-src-7ffebadcef03ef7d4c21bb2bacc7138cf1cce87a.zip
FreeBSD-src-7ffebadcef03ef7d4c21bb2bacc7138cf1cce87a.tar.gz
A bunch of interrupt related cleanup.
o Move PIOCSRESOURCE from pccard to pcic so the kernel can give pccardd better hints as to what resources to use. o Implement an undocumented hw.pcic.interrupt_route to allow people that need to do so to route their interrupts in a non-standard way. o Only preallocate a resource in probe if we're routing via pci. o If we aren't routing via pci, then set the irq to use explicitly to defeat the automatic IRQ routing of the pci layer. This, with the pccardd code should be close to what can be committed to -stable.
Diffstat (limited to 'sys')
-rw-r--r--sys/pccard/pccard.c33
-rw-r--r--sys/pccard/pcic.c45
-rw-r--r--sys/pccard/pcic_pci.c87
3 files changed, 98 insertions, 67 deletions
diff --git a/sys/pccard/pccard.c b/sys/pccard/pccard.c
index 816fa3f..0a02e02 100644
--- a/sys/pccard/pccard.c
+++ b/sys/pccard/pccard.c
@@ -442,36 +442,6 @@ crdwrite(dev_t dev, struct uio *uio, int ioflag)
return (error);
}
-static int
-crdioctl_sresource(dev_t dev, caddr_t data)
-{
- struct pccard_resource *pr;
- struct resource *r;
- int flags;
- int rid = 0;
- device_t bridgedev;
-
- pr = (struct pccard_resource *)data;
- pr->resource_addr = ~0ul;
- bridgedev = PCCARD_DEV2SOFTC(dev)->dev;
- switch(pr->type) {
- default:
- return (EINVAL);
- case SYS_RES_MEMORY:
- case SYS_RES_IRQ:
- case SYS_RES_IOPORT:
- break;
- }
- flags = rman_make_alignment_flags(pr->size);
- r = bus_alloc_resource(bridgedev, pr->type, &rid, pr->min, pr->max,
- pr->size, flags);
- if (r != NULL) {
- pr->resource_addr = (u_long)rman_get_start(r);
- bus_release_resource(bridgedev, pr->type, rid, r);
- }
- return (0);
-}
-
/*
* ioctl calls - allows setting/getting of memory and I/O
* descriptors, and assignment of drivers.
@@ -638,9 +608,6 @@ crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
return (EINVAL);
}
break;
- case PIOCSRESOURCE:
- return (crdioctl_sresource(dev, data));
- break;
}
return (0);
}
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c
index 14b444a..2b2b4da 100644
--- a/sys/pccard/pcic.c
+++ b/sys/pccard/pcic.c
@@ -368,6 +368,41 @@ pcic_attach(device_t dev)
return (bus_generic_attach(dev));
}
+
+static int
+pcic_sresource(struct slot *slt, caddr_t data)
+{
+ struct pccard_resource *pr;
+ struct resource *r;
+ int flags;
+ int rid = 0;
+ device_t bridgedev = slt->dev;
+ struct pcic_slot *sp = slt->cdata;
+
+ pr = (struct pccard_resource *)data;
+ pr->resource_addr = ~0ul;
+ if (pr->type == SYS_RES_IRQ && sp->sc->func_route == pci_parallel) {
+ pr->resource_addr = sp->sc->irq;
+ return (0);
+ }
+ switch(pr->type) {
+ default:
+ return (EINVAL);
+ case SYS_RES_MEMORY:
+ case SYS_RES_IRQ:
+ case SYS_RES_IOPORT:
+ break;
+ }
+ flags = rman_make_alignment_flags(pr->size);
+ r = bus_alloc_resource(bridgedev, pr->type, &rid, pr->min, pr->max,
+ pr->size, flags);
+ if (r != NULL) {
+ pr->resource_addr = (u_long)rman_get_start(r);
+ bus_release_resource(bridgedev, pr->type, rid, r);
+ }
+ return (0);
+}
+
/*
* ioctl calls - Controller specific ioctls
*/
@@ -379,17 +414,17 @@ pcic_ioctl(struct slot *slt, int cmd, caddr_t data)
switch(cmd) {
default:
return (ENOTTY);
- /*
- * Get/set PCIC registers
- */
- case PIOCGREG:
+ case PIOCGREG: /* Get pcic register */
((struct pcic_reg *)data)->value =
sp->getb(sp, ((struct pcic_reg *)data)->reg);
- break;
+ break; /* Set pcic register */
case PIOCSREG:
sp->putb(sp, ((struct pcic_reg *)data)->reg,
((struct pcic_reg *)data)->value);
break;
+ case PIOCSRESOURCE: /* Can I use this resource? */
+ pcic_sresource(slt, data);
+ break;
}
return (0);
}
diff --git a/sys/pccard/pcic_pci.c b/sys/pccard/pcic_pci.c
index e4f390d..6cb7c5a 100644
--- a/sys/pccard/pcic_pci.c
+++ b/sys/pccard/pcic_pci.c
@@ -59,13 +59,26 @@
static int pcic_pci_get_memory(device_t dev);
+SYSCTL_DECL(_hw_pcic);
+
static int pcic_ignore_function_1 = 0;
TUNABLE_INT("hw.pcic.ignore_function_1", &pcic_ignore_function_1);
-SYSCTL_DECL(_hw_pcic);
SYSCTL_INT(_hw_pcic, OID_AUTO, ignore_function_1, CTLFLAG_RD,
&pcic_ignore_function_1, 0,
"When set, driver ignores pci function 1 of the bridge");
+/*
+ * The following should be a hint, so we can do it on a per device
+ * instance, but this is convenient. Do not set this unless pci
+ * routing doesn't work. It is purposely vague and undocumented
+ * at the moment.
+ */
+static int pcic_interrupt_route = (int) pci_parallel;
+TUNABLE_INT("hw.pcic.interrupt_route", &pcic_interrupt_route);
+SYSCTL_INT(_hw_pcic, OID_AUTO, interrupt_route, CTLFLAG_RD,
+ &pcic_interrupt_route, (int) pci_parallel,
+ "Interrupt routing type for pci cardbus bridges.");
+
struct pcic_pci_table
{
u_int32_t devid;
@@ -208,16 +221,21 @@ pcic_pci_lookup(u_int32_t devid, struct pcic_pci_table *tbl)
static void
pcic_pci_pd6832_init(device_t dev)
{
+ struct pcic_softc *sc = device_get_softc(dev);
u_long bcr; /* to set interrupts */
- /*
- * CLPD683X management interrupt enable bit is bit 11 in bridge
- * control register(offset 0x3d).
- * When this bit is turned on, card status change interrupt sets
- * on ISA IRQ interrupt.
+ /*
+ * CLPD683X management interrupt enable bit is bit 11 in bridge
+ * control register(offset 0x3d).
+ * When this bit is turned on, card status change interrupt sets
+ * on ISA IRQ interrupt.
*/
bcr = pci_read_config(dev, CB_PCI_BRIDGE_CTRL, 2);
bcr |= CLPD6832_BCR_MGMT_IRQ_ENA;
+ if (sc->csc_route == pci_parallel)
+ bcr &= ~CLPD6832_BCR_ISA_IRQ;
+ else
+ bcr |= CLPD6832_BCR_ISA_IRQ;
pci_write_config(dev, CB_PCI_BRIDGE_CTRL, bcr, 2);
}
@@ -350,7 +368,7 @@ pcic_pci_cardbus_init(device_t dev)
static void
pcic_pci_ricoh_init(device_t dev, int old)
{
- u_int16_t brgcntl;
+ u_int16_t brgcntl;
/*
* Ricoh chips have a legacy bridge enable different than most
@@ -477,11 +495,16 @@ pcic_pci_probe(device_t dev)
* Allocated/deallocate interrupt. This forces the PCI BIOS or
* other MD method to route the interrupts to this card.
* This so we get the interrupt number in the probe message.
+ * We only need to route interrupts when we're doing pci
+ * parallel interrupt routing.
*/
- rid = 0;
- res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE);
- if (res)
- bus_release_resource(dev, SYS_RES_IRQ, rid, res);
+ if (pcic_interrupt_route == pci_parallel) {
+ rid = 0;
+ res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_ACTIVE);
+ if (res)
+ bus_release_resource(dev, SYS_RES_IRQ, rid, res);
+ }
return (0);
}
@@ -503,16 +526,17 @@ pcic_pci_attach(device_t dev)
int rid;
struct resource *r;
int error;
- static int num6729;
+ u_long start;
+ u_long end;
/*
* In sys/pci/pcireg.h, PCIR_COMMAND must be separated
* PCI_COMMAND_REG(0x04) and PCI_STATUS_REG(0x06).
* Takeshi Shibagaki(shiba@jp.freebsd.org).
*/
- command = pci_read_config(dev, PCIR_COMMAND, 4);
- command |= PCIM_CMD_PORTEN | PCIM_CMD_MEMEN;
- pci_write_config(dev, PCIR_COMMAND, command, 4);
+ command = pci_read_config(dev, PCIR_COMMAND, 4);
+ command |= PCIM_CMD_PORTEN | PCIM_CMD_MEMEN;
+ pci_write_config(dev, PCIR_COMMAND, command, 4);
sc = (struct pcic_softc *) device_get_softc(dev);
sp = &sc->slots[0];
@@ -529,13 +553,11 @@ pcic_pci_attach(device_t dev)
sp->putb = pcic_putb_io;
sc->bst = sp->bst = rman_get_bustag(sc->iores);
sc->bsh = sp->bsh = rman_get_bushandle(sc->iores);
- sp->offset = (num6729 % 2) * PCIC_SLOT_SIZE;
+ sp->offset = pci_get_function(dev) * PCIC_SLOT_SIZE;
sp->controller = PCIC_PD672X;
sp->revision = 0;
sc->flags = PCIC_PD_POWER;
- num6729++;
} else {
- device_printf(dev, "Memory mapped device, will work.\n");
sc->memrid = CB_PCI_SOCKET_BASE;
sc->memres = bus_alloc_resource(dev, SYS_RES_MEMORY,
&sc->memrid, 0, ~0, 1, RF_ACTIVE);
@@ -557,24 +579,24 @@ pcic_pci_attach(device_t dev)
sp->revision = 0;
sc->flags = PCIC_DF_POWER;
}
- sp->slt = (struct slot *) 1;
}
+ sp->slt = (struct slot *) 1;
sc->dev = dev;
- sc->csc_route = pci_parallel;
- sc->func_route = pci_parallel;
+ sc->csc_route = pcic_interrupt_route;
+ sc->func_route = pcic_interrupt_route;
switch (device_id) {
case PCI_DEVICE_ID_RICOH_RL5C465:
case PCI_DEVICE_ID_RICOH_RL5C466:
pcic_pci_ricoh_init(dev, 1);
- pcic_pci_cardbus_init(dev);
+ pcic_pci_cardbus_init(dev);
break;
case PCI_DEVICE_ID_RICOH_RL5C475:
case PCI_DEVICE_ID_RICOH_RL5C476:
case PCI_DEVICE_ID_RICOH_RL5C477:
case PCI_DEVICE_ID_RICOH_RL5C478:
pcic_pci_ricoh_init(dev, 0);
- pcic_pci_cardbus_init(dev);
+ pcic_pci_cardbus_init(dev);
break;
case PCI_DEVICE_ID_PCIC_TI1031:
case PCI_DEVICE_ID_PCIC_TI1130:
@@ -591,20 +613,27 @@ pcic_pci_attach(device_t dev)
case PCI_DEVICE_ID_PCIC_TI1450:
case PCI_DEVICE_ID_PCIC_TI1451:
case PCI_DEVICE_ID_PCIC_TI4451:
- pcic_pci_ti_init(dev);
- pcic_pci_cardbus_init(dev);
+ pcic_pci_ti_init(dev);
+ pcic_pci_cardbus_init(dev);
break;
case PCI_DEVICE_ID_PCIC_CLPD6832:
pcic_pci_pd6832_init(dev);
break;
default:
- pcic_pci_cardbus_init(dev);
- break;
+ pcic_pci_cardbus_init(dev);
+ break;
}
+ if (sc->csc_route == pci_parallel) {
+ start = 0;
+ end = ~0;
+ } else {
+ start = pcic_override_irq;
+ end = pcic_override_irq;
+ }
rid = 0;
r = NULL;
- r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, start, end, 1,
RF_ACTIVE | RF_SHAREABLE);
if (r == NULL) {
device_printf(dev, "Failed to allocate managment irq\n");
@@ -650,7 +679,7 @@ pcic_pci_get_memory(device_t dev)
sockbase = pci_read_config(dev, sc->memrid, 4);
sockbase = (sockbase & 0xfffffff0) & -(sockbase & 0xfffffff0);
#define CARDBUS_SYS_RES_MEMORY_START 0x44000000
-#define CARDBUS_SYS_RES_MEMORY_END 0xFFFFFFFF
+#define CARDBUS_SYS_RES_MEMORY_END 0xFFFFFFFF
sc->memres = bus_generic_alloc_resource(device_get_parent(dev),
dev, SYS_RES_MEMORY, &sc->memrid,
CARDBUS_SYS_RES_MEMORY_START, CARDBUS_SYS_RES_MEMORY_END,
OpenPOWER on IntegriCloud