summaryrefslogtreecommitdiffstats
path: root/sys/sparc64/pci/psycho.c
diff options
context:
space:
mode:
authorpiso <piso@FreeBSD.org>2007-02-23 12:19:07 +0000
committerpiso <piso@FreeBSD.org>2007-02-23 12:19:07 +0000
commit6a2ffa86e5b748ba71e36d37462a936eb9101be7 (patch)
tree10833d4edb6c0d0a5efcf7762d842a4c378404b0 /sys/sparc64/pci/psycho.c
parent7b48c9d78377cdb9fc6e8bcc5406e28819aef6e3 (diff)
downloadFreeBSD-src-6a2ffa86e5b748ba71e36d37462a936eb9101be7.zip
FreeBSD-src-6a2ffa86e5b748ba71e36d37462a936eb9101be7.tar.gz
o break newbus api: add a new argument of type driver_filter_t to
bus_setup_intr() o add an int return code to all fast handlers o retire INTR_FAST/IH_FAST For more info: http://docs.freebsd.org/cgi/getmsg.cgi?fetch=465712+0+current/freebsd-current Reviewed by: many Approved by: re@
Diffstat (limited to 'sys/sparc64/pci/psycho.c')
-rw-r--r--sys/sparc64/pci/psycho.c87
1 files changed, 58 insertions, 29 deletions
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index 8e21d3b..8d5ae04 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -81,20 +81,20 @@ static const struct psycho_desc *psycho_find_desc(const struct psycho_desc *,
const char *);
static const struct psycho_desc *psycho_get_desc(phandle_t, const char *);
static void psycho_set_intr(struct psycho_softc *, int, bus_addr_t, int,
- driver_intr_t);
+ driver_filter_t);
static int psycho_find_intrmap(struct psycho_softc *, int, bus_addr_t *,
bus_addr_t *, u_long *);
-static void psycho_intr_stub(void *);
+static int psycho_intr_stub(void *);
static bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int);
/* Interrupt handlers */
-static void psycho_ue(void *);
-static void psycho_ce(void *);
-static void psycho_pci_bus(void *);
-static void psycho_powerfail(void *);
-static void psycho_overtemp(void *);
+static int psycho_ue(void *);
+static int psycho_ce(void *);
+static int psycho_pci_bus(void *);
+static int psycho_powerfail(void *);
+static int psycho_overtemp(void *);
#ifdef PSYCHO_MAP_WAKEUP
-static void psycho_wakeup(void *);
+static int psycho_wakeup(void *);
#endif
/* IOMMU support */
@@ -170,7 +170,7 @@ SLIST_HEAD(, psycho_softc) psycho_softcs =
struct psycho_clr {
struct psycho_softc *pci_sc;
bus_addr_t pci_clr; /* clear register */
- driver_intr_t *pci_handler; /* handler to call */
+ driver_filter_t *pci_handler; /* handler to call */
void *pci_arg; /* argument for the handler */
void *pci_cookie; /* parent bus int. cookie */
device_t pci_ppb; /* farest PCI-PCI bridge */
@@ -216,8 +216,11 @@ struct psycho_clr {
* On UltraII machines, there can be any number of "Psycho+" ICs, each
* providing two PCI buses.
*/
+
+#define FAST 0x66600000
+
#ifdef DEBUGGER_ON_POWERFAIL
-#define PSYCHO_PWRFAIL_INT_FLAGS INTR_FAST
+#define PSYCHO_PWRFAIL_INT_FLAGS FAST
#else
#define PSYCHO_PWRFAIL_INT_FLAGS 0
#endif
@@ -507,7 +510,7 @@ psycho_attach(device_t dev)
* interrupt but they are also only used for PCI bus A.
*/
psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP :
- PSR_PCIBERR_INT_MAP, INTR_FAST, psycho_pci_bus);
+ PSR_PCIBERR_INT_MAP, FAST, psycho_pci_bus);
/*
* If we're a Hummingbird/Sabre or the first of a pair of Psycho's to
@@ -523,7 +526,7 @@ psycho_attach(device_t dev)
* XXX Not all controllers have these, but installing them
* is better than trying to sort through this mess.
*/
- psycho_set_intr(sc, 1, PSR_UE_INT_MAP, INTR_FAST, psycho_ue);
+ psycho_set_intr(sc, 1, PSR_UE_INT_MAP, FAST, psycho_ue);
psycho_set_intr(sc, 2, PSR_CE_INT_MAP, 0, psycho_ce);
psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
PSYCHO_PWRFAIL_INT_FLAGS, psycho_powerfail);
@@ -538,7 +541,7 @@ psycho_attach(device_t dev)
* The spare hardware interrupt is used for the
* over-temperature interrupt.
*/
- psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, INTR_FAST,
+ psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, FAST,
psycho_overtemp);
#ifdef PSYCHO_MAP_WAKEUP
/*
@@ -678,19 +681,30 @@ psycho_attach(device_t dev)
static void
psycho_set_intr(struct psycho_softc *sc, int index, bus_addr_t map, int iflags,
- driver_intr_t handler)
+ driver_filter_t handler)
{
- int rid, vec;
+ int rid, vec, res;
uint64_t mr;
+ res = EINVAL;
rid = index;
mr = PSYCHO_READ8(sc, map);
vec = INTVEC(mr);
sc->sc_irq_res[index] = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ,
&rid, vec, vec, 1, RF_ACTIVE);
- if (sc->sc_irq_res[index] == NULL ||
- bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC |
- iflags, handler, sc, &sc->sc_ihand[index]) != 0)
+ if (sc->sc_irq_res[index] != NULL) {
+ if (iflags & FAST) {
+ iflags &= ~FAST;
+ res = bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
+ INTR_TYPE_MISC | iflags, handler, NULL, sc,
+ &sc->sc_ihand[index]);
+ } else
+ res = bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
+ INTR_TYPE_MISC | iflags, NULL,
+ (driver_intr_t *)handler, sc,
+ &sc->sc_ihand[index]);
+ }
+ if (res)
panic("%s: failed to set up interrupt", __func__);
PSYCHO_WRITE8(sc, map, INTMAP_ENABLE(mr, PCPU_GET(mid)));
}
@@ -749,7 +763,7 @@ psycho_find_intrmap(struct psycho_softc *sc, int ino, bus_addr_t *intrmapptr,
/*
* Interrupt handlers
*/
-static void
+static int
psycho_ue(void *arg)
{
struct psycho_softc *sc = arg;
@@ -767,9 +781,10 @@ psycho_ue(void *arg)
iommu_decode_fault(sc->sc_is, afar);
panic("%s: uncorrectable DMA error AFAR %#lx AFSR %#lx",
device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
+ return (FILTER_HANDLED);
}
-static void
+static int
psycho_ce(void *arg)
{
struct psycho_softc *sc = arg;
@@ -782,9 +797,10 @@ psycho_ce(void *arg)
/* Clear the error bits that we caught. */
PSYCHO_WRITE8(sc, PSR_CE_AFS, afsr & CEAFSR_ERRMASK);
PSYCHO_WRITE8(sc, PSR_CE_INT_CLR, 0);
+ return (FILTER_HANDLED);
}
-static void
+static int
psycho_pci_bus(void *arg)
{
struct psycho_softc *sc = arg;
@@ -795,9 +811,10 @@ psycho_pci_bus(void *arg)
panic("%s: PCI bus %c error AFAR %#lx AFSR %#lx",
device_get_name(sc->sc_dev), 'A' + sc->sc_half, (u_long)afar,
(u_long)afsr);
+ return (FILTER_HANDLED);
}
-static void
+static int
psycho_powerfail(void *arg)
{
@@ -810,18 +827,20 @@ psycho_powerfail(void *arg)
printf("Power Failure Detected: Shutting down NOW.\n");
shutdown_nice(0);
#endif
+ return (FILTER_HANDLED);
}
-static void
+static int
psycho_overtemp(void *arg)
{
printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n");
shutdown_nice(RB_POWEROFF);
+ return (FILTER_HANDLED);
}
#ifdef PSYCHO_MAP_WAKEUP
-static void
+static int
psycho_wakeup(void *arg)
{
struct psycho_softc *sc = arg;
@@ -829,6 +848,7 @@ psycho_wakeup(void *arg)
PSYCHO_WRITE8(sc, PSR_PWRMGT_INT_CLR, 0);
/* Gee, we don't really have a framework to deal with this properly. */
device_printf(sc->sc_dev, "power management wakeup\n");
+ return (FILTER_HANDLED);
}
#endif /* PSYCHO_MAP_WAKEUP */
@@ -988,7 +1008,7 @@ psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
}
/* Write to the correct clr register, and call the actual handler. */
-static void
+static int
psycho_intr_stub(void *arg)
{
struct psycho_clr *pc = arg;
@@ -1000,11 +1020,13 @@ psycho_intr_stub(void *arg)
}
pc->pci_handler(pc->pci_arg);
PSYCHO_WRITE8(pc->pci_sc, pc->pci_clr, 0);
+ return (FILTER_HANDLED);
}
static int
psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
- int flags, driver_intr_t *intr, void *arg, void **cookiep)
+ int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
+ void **cookiep)
{
struct {
int apb:1;
@@ -1019,6 +1041,9 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
uint64_t mr;
int error, ino;
+ if (filt != NULL && intr != NULL)
+ return (EINVAL);
+
sc = device_get_softc(dev);
pc = malloc(sizeof(*pc), M_DEVBUF, M_NOWAIT | M_ZERO);
if (pc == NULL)
@@ -1048,7 +1073,7 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
pc->pci_sc = sc;
pc->pci_arg = arg;
- pc->pci_handler = intr;
+ pc->pci_handler = (filt != NULL) ? filt : (driver_filter_t *)intr;
pc->pci_clr = intrclrptr;
/*
@@ -1104,8 +1129,12 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
/* Disable the interrupt while we fiddle with it. */
mr = PSYCHO_READ8(sc, intrmapptr);
PSYCHO_WRITE8(sc, intrmapptr, mr & ~INTMAP_V);
- error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
- psycho_intr_stub, pc, cookiep);
+ if (filt != NULL)
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ psycho_intr_stub, NULL, pc, cookiep);
+ else
+ error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ NULL, (driver_intr_t *)psycho_intr_stub, pc, cookiep);
if (error != 0) {
free(pc, M_DEVBUF);
return (error);
OpenPOWER on IntegriCloud