aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/esp/esp_sbus.c
diff options
context:
space:
mode:
authorMarius Strobl <marius@FreeBSD.org>2005-05-19 14:51:10 +0000
committerMarius Strobl <marius@FreeBSD.org>2005-05-19 14:51:10 +0000
commit65fb49a994d52fdf59fbbc13095993cad1abe329 (patch)
treeb01c4fc232ba2ecf59b19468701e66ebeeda19ad /sys/dev/esp/esp_sbus.c
parent410f3d914ed63cf118fd9470e726cca5b444ab4e (diff)
Notes
Diffstat (limited to 'sys/dev/esp/esp_sbus.c')
-rw-r--r--sys/dev/esp/esp_sbus.c458
1 files changed, 364 insertions, 94 deletions
diff --git a/sys/dev/esp/esp_sbus.c b/sys/dev/esp/esp_sbus.c
index 24a6a8f2c665..cc92f19fd6e5 100644
--- a/sys/dev/esp/esp_sbus.c
+++ b/sys/dev/esp/esp_sbus.c
@@ -109,18 +109,39 @@ struct esp_softc {
struct lsi64854_softc *sc_dma; /* pointer to my DMA */
};
-static int esp_sbus_probe(device_t);
+static devclass_t esp_devclass;
+
+static int esp_probe(device_t);
+static int esp_dma_attach(device_t);
+static int esp_dma_detach(device_t);
static int esp_sbus_attach(device_t);
static int esp_sbus_detach(device_t);
-static int esp_sbus_suspend(device_t);
-static int esp_sbus_resume(device_t);
+static int esp_suspend(device_t);
+static int esp_resume(device_t);
+
+static device_method_t esp_dma_methods[] = {
+ DEVMETHOD(device_probe, esp_probe),
+ DEVMETHOD(device_attach, esp_dma_attach),
+ DEVMETHOD(device_detach, esp_dma_detach),
+ DEVMETHOD(device_suspend, esp_suspend),
+ DEVMETHOD(device_resume, esp_resume),
+ {0, 0}
+};
+
+static driver_t esp_dma_driver = {
+ "esp",
+ esp_dma_methods,
+ sizeof(struct esp_softc)
+};
+
+DRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0);
static device_method_t esp_sbus_methods[] = {
- DEVMETHOD(device_probe, esp_sbus_probe),
+ DEVMETHOD(device_probe, esp_probe),
DEVMETHOD(device_attach, esp_sbus_attach),
DEVMETHOD(device_detach, esp_sbus_detach),
- DEVMETHOD(device_suspend, esp_sbus_suspend),
- DEVMETHOD(device_resume, esp_sbus_resume),
+ DEVMETHOD(device_suspend, esp_suspend),
+ DEVMETHOD(device_resume, esp_resume),
{0, 0}
};
@@ -130,7 +151,6 @@ static driver_t esp_sbus_driver = {
sizeof(struct esp_softc)
};
-static devclass_t esp_devclass;
DRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0);
/*
@@ -146,7 +166,7 @@ static int esp_dma_setup(struct ncr53c9x_softc *, caddr_t *, size_t *,
static void esp_dma_go(struct ncr53c9x_softc *);
static void esp_dma_stop(struct ncr53c9x_softc *);
static int esp_dma_isactive(struct ncr53c9x_softc *);
-static void espattach(struct esp_softc *, struct ncr53c9x_glue *);
+static int espattach(struct esp_softc *, struct ncr53c9x_glue *);
static struct ncr53c9x_glue esp_sbus_glue = {
esp_read_reg,
@@ -162,7 +182,7 @@ static struct ncr53c9x_glue esp_sbus_glue = {
};
static int
-esp_sbus_probe(device_t dev)
+esp_probe(device_t dev)
{
const char *name;
@@ -170,6 +190,9 @@ esp_sbus_probe(device_t dev)
if (strcmp("SUNW,fas", name) == 0) {
device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI");
return (BUS_PROBE_DEFAULT);
+ } else if (strcmp("esp", name) == 0) {
+ device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI");
+ return (BUS_PROBE_DEFAULT);
}
return (ENXIO);
@@ -181,126 +204,291 @@ esp_sbus_attach(device_t dev)
struct esp_softc *esc;
struct ncr53c9x_softc *sc;
struct lsi64854_softc *lsc;
+ device_t *children;
+ const char *name;
phandle_t node;
- int burst;
+ int burst, error, i, nchildren, slot;
esc = device_get_softc(dev);
bzero(esc, sizeof(struct esp_softc));
sc = &esc->sc_ncr53c9x;
+ lsc = NULL;
esc->sc_dev = dev;
+ name = ofw_bus_get_name(dev);
node = ofw_bus_get_node(dev);
if (OF_getprop(node, "initiator-id", &sc->sc_id,
sizeof(sc->sc_id)) == -1)
sc->sc_id = 7;
- if (OF_getprop(node, "clock-frequency", &sc->sc_freq,
- sizeof(sc->sc_freq)) == -1) {
- printf("failed to query OFW for clock-frequency\n");
- sc->sc_freq = sbus_get_clockfreq(dev);
- }
+ sc->sc_freq = sbus_get_clockfreq(dev);
#ifdef ESP_SBUS_DEBUG
device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
sc->sc_freq);
#endif
- /*
- * allocate space for DMA, in SUNW,fas there are no separate
- * DMA devices
- */
- lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (lsc == NULL) {
- device_printf(dev, "out of memory (lsi64854_softc)\n");
- return (ENOMEM);
- }
- esc->sc_dma = lsc;
+ if (strcmp(name, "SUNW,fas") == 0) {
+ /*
+ * Allocate space for DMA, in SUNW,fas there are no
+ * separate DMA devices.
+ */
+ lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (lsc == NULL) {
+ device_printf(dev, "out of memory (lsi64854_softc)\n");
+ return (ENOMEM);
+ }
+ esc->sc_dma = lsc;
- /*
- * fas has 2 register spaces: DMA (lsi64854) and SCSI core (ncr53c9x)
- */
+ /*
+ * SUNW,fas have 2 register spaces: DMA (lsi64854) and
+ * SCSI core (ncr53c9x).
+ */
- /* allocate DMA registers */
- lsc->sc_rid = 0;
- if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &lsc->sc_rid, RF_ACTIVE)) == NULL) {
- device_printf(dev, "cannot allocate DMA registers\n");
- free(lsc, M_DEVBUF);
- return (ENXIO);
- }
- lsc->sc_regt = rman_get_bustag(lsc->sc_res);
- lsc->sc_regh = rman_get_bushandle(lsc->sc_res);
+ /* Allocate DMA registers. */
+ lsc->sc_rid = 0;
+ if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &lsc->sc_rid, RF_ACTIVE)) == NULL) {
+ device_printf(dev, "cannot allocate DMA registers\n");
+ error = ENXIO;
+ goto fail_sbus_lsc;
+ }
+ lsc->sc_regt = rman_get_bustag(lsc->sc_res);
+ lsc->sc_regh = rman_get_bushandle(lsc->sc_res);
- /* Create a parent DMA tag based on this bus */
- if (bus_dma_tag_create(
- NULL, /* parent */
- PAGE_SIZE, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
- 0, /* nsegments */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* no locking */
- &lsc->sc_parent_dmat)) {
- device_printf(dev, "cannot allocate parent DMA tag\n");
- free(lsc, M_DEVBUF);
- return (ENOMEM);
- }
- burst = sbus_get_burstsz(dev);
+ /* Create a parent DMA tag based on this bus. */
+ error = bus_dma_tag_create(
+ NULL, /* parent */
+ PAGE_SIZE, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
+ 0, /* nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* no locking */
+ &lsc->sc_parent_dmat);
+ if (error != 0) {
+ device_printf(dev, "cannot allocate parent DMA tag\n");
+ goto fail_sbus_lres;
+ }
+ burst = sbus_get_burstsz(dev);
#ifdef ESP_SBUS_DEBUG
- printf("%s: burst 0x%x\n", __func__, burst);
+ printf("%s: burst 0x%x\n", __func__, burst);
#endif
- lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
- (burst & SBUS_BURST_16) ? 16 : 0;
+ lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
+ (burst & SBUS_BURST_16) ? 16 : 0;
+
+ lsc->sc_channel = L64854_CHANNEL_SCSI;
+ lsc->sc_client = sc;
+ lsc->sc_dev = dev;
+
+ error = lsi64854_attach(lsc);
+ if (error != 0) {
+ device_printf(dev, "lsi64854_attach failed\n");
+ goto fail_sbus_lpdma;
+ }
+
+ /*
+ * Allocate SCSI core registers.
+ */
+ esc->sc_rid = 1;
+ if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &esc->sc_rid, RF_ACTIVE)) == NULL) {
+ device_printf(dev,
+ "cannot allocate SCSI core registers\n");
+ error = ENXIO;
+ goto fail_sbus_lsi;
+ }
+ esc->sc_regt = rman_get_bustag(esc->sc_res);
+ esc->sc_regh = rman_get_bushandle(esc->sc_res);
+ } else {
+ /*
+ * Search accompanying DMA engine. It should have been
+ * already attached otherwise there isn't much we can do.
+ */
+ if (device_get_children(device_get_parent(dev), &children,
+ &nchildren) != 0) {
+ device_printf(dev, "cannot determine siblings\n");
+ return (ENXIO);
+ }
+ slot = sbus_get_slot(dev);
+ for (i = 0; i < nchildren; i++) {
+ if (device_is_attached(children[i]) &&
+ sbus_get_slot(children[i]) == slot &&
+ strcmp(ofw_bus_get_name(children[i]), "dma") == 0) {
+ /* XXX hackery */
+ esc->sc_dma = (struct lsi64854_softc *)
+ device_get_softc(children[i]);
+ break;
+ }
+ }
+ free(children, M_TEMP);
+ if (esc->sc_dma == NULL) {
+ device_printf(dev, "cannot find DMA engine\n");
+ return (ENXIO);
+ }
+ esc->sc_dma->sc_client = sc;
+
+ /*
+ * Allocate SCSI core registers.
+ */
+ esc->sc_rid = 0;
+ if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &esc->sc_rid, RF_ACTIVE)) == NULL) {
+ device_printf(dev,
+ "cannot allocate SCSI core registers\n");
+ return (ENXIO);
+ }
+ esc->sc_regt = rman_get_bustag(esc->sc_res);
+ esc->sc_regh = rman_get_bushandle(esc->sc_res);
+ }
+
+ error = espattach(esc, &esp_sbus_glue);
+ if (error != 0) {
+ device_printf(dev, "espattach failed\n");
+ goto fail_sbus_eres;
+ }
+
+ return (0);
+
+ fail_sbus_eres:
+ bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
+ if (strcmp(name, "SUNW,fas") != 0)
+ return (error);
+ fail_sbus_lsi:
+ lsi64854_detach(lsc);
+ fail_sbus_lpdma:
+ bus_dma_tag_destroy(lsc->sc_parent_dmat);
+ fail_sbus_lres:
+ bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
+ fail_sbus_lsc:
+ free(lsc, M_DEVBUF);
+ return (error);
+}
+
+static int
+esp_sbus_detach(device_t dev)
+{
+ struct esp_softc *esc;
+ struct ncr53c9x_softc *sc;
+ struct lsi64854_softc *lsc;
+ int error;
+
+ esc = device_get_softc(dev);
+ sc = &esc->sc_ncr53c9x;
+ lsc = esc->sc_dma;
+
+ bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
+ error = ncr53c9x_detach(sc);
+ if (error != 0)
+ return (error);
+ bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
+ esc->sc_irqres);
+ bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
+ if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0)
+ return (0);
+ error = lsi64854_detach(lsc);
+ if (error != 0)
+ return (error);
+ bus_dma_tag_destroy(lsc->sc_parent_dmat);
+ bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
+ free(lsc, M_DEVBUF);
+
+ return (0);
+}
+
+static int
+esp_dma_attach(device_t dev)
+{
+ struct esp_softc *esc;
+ struct ncr53c9x_softc *sc;
+ phandle_t node;
+ int error;
+
+ esc = device_get_softc(dev);
+ bzero(esc, sizeof(struct esp_softc));
+ sc = &esc->sc_ncr53c9x;
+
+ esc->sc_dev = dev;
+ node = ofw_bus_get_node(dev);
+ if (OF_getprop(node, "initiator-id", &sc->sc_id,
+ sizeof(sc->sc_id)) == -1)
+ sc->sc_id = 7;
+ if (OF_getprop(node, "clock-frequency", &sc->sc_freq,
+ sizeof(sc->sc_freq)) == -1) {
+ printf("failed to query OFW for clock-frequency\n");
+ return (ENXIO);
+ }
- lsc->sc_channel = L64854_CHANNEL_SCSI;
- lsc->sc_client = sc;
- lsc->sc_dev = dev;
+#ifdef ESP_SBUS_DEBUG
+ device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
+ sc->sc_freq);
+#endif
- lsi64854_attach(lsc);
+ /* XXX hackery */
+ esc->sc_dma = (struct lsi64854_softc *)
+ device_get_softc(device_get_parent(dev));
+ esc->sc_dma->sc_client = sc;
/*
- * allocate SCSI core registers
+ * Allocate SCSI core registers.
*/
- esc->sc_rid = 1;
+ esc->sc_rid = 0;
if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&esc->sc_rid, RF_ACTIVE)) == NULL) {
device_printf(dev, "cannot allocate SCSI core registers\n");
- free(lsc, M_DEVBUF);
return (ENXIO);
}
esc->sc_regt = rman_get_bustag(esc->sc_res);
esc->sc_regh = rman_get_bushandle(esc->sc_res);
- espattach(esc, &esp_sbus_glue);
+ error = espattach(esc, &esp_sbus_glue);
+ if (error != 0) {
+ device_printf(dev, "espattach failed\n");
+ goto fail_dma_eres;
+ }
return (0);
+
+ fail_dma_eres:
+ bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
+ return (error);
}
static int
-esp_sbus_detach(device_t dev)
+esp_dma_detach(device_t dev)
{
- struct ncr53c9x_softc *sc;
struct esp_softc *esc;
+ struct ncr53c9x_softc *sc;
+ int error;
esc = device_get_softc(dev);
sc = &esc->sc_ncr53c9x;
- return (ncr53c9x_detach(sc, 0));
+
+ bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
+ error = ncr53c9x_detach(sc);
+ if (error != 0)
+ return (error);
+ bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
+ esc->sc_irqres);
+ bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
+
+ return (0);
}
static int
-esp_sbus_suspend(device_t dev)
+esp_suspend(device_t dev)
{
return (ENXIO);
}
static int
-esp_sbus_resume(device_t dev)
+esp_resume(device_t dev)
{
return (ENXIO);
@@ -309,11 +497,19 @@ esp_sbus_resume(device_t dev)
/*
* Attach this instance, and then all the sub-devices
*/
-static void
+static int
espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
{
struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
unsigned int uid = 0;
+ int error;
+
+ /*
+ * The `ESC' DMA chip must be reset before we can access
+ * the ESP registers.
+ */
+ if (esc->sc_dma->sc_rev == DMAREV_ESC)
+ DMA_RESET(esc->sc_dma);
/*
* Set up glue for MI code early; we use some of it here.
@@ -330,13 +526,30 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
*/
/*
+ * Read the part-unique ID code of the SCSI chip. The contained
+ * value is only valid if all of the following conditions are met:
+ * - After power-up or chip reset.
+ * - Before any value is written to this register.
+ * - The NCRCFG2_FE bit is set.
+ * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued.
+ */
+ NCRCMD(sc, NCRCMD_RSTCHIP);
+ NCRCMD(sc, NCRCMD_NOP);
+ sc->sc_cfg2 = NCRCFG2_FE;
+ NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
+ NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
+ uid = NCR_READ_REG(sc, NCR_UID);
+
+ /*
* It is necessary to try to load the 2nd config register here,
* to find out what rev the esp chip is, else the ncr53c9x_reset
* will not set up the defaults correctly.
*/
sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
+ NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
+ sc->sc_cfg2 = 0;
+ NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
- sc->sc_cfg3 = NCRCFG3_CDB;
NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
@@ -357,15 +570,33 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
sc->sc_cfg2 |= NCRCFG2_FE;
sc->sc_cfg3 = 0;
NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
- sc->sc_rev = NCR_VARIANT_ESP200;
-
- /*
- * XXX spec says it's valid after power up or chip
- * reset.
- */
- uid = NCR_READ_REG(sc, NCR_UID);
- if (((uid & 0xf8) >> 3) == 0x0a) /* XXX */
- sc->sc_rev = NCR_VARIANT_FAS366;
+ if (sc->sc_freq <= 25)
+ sc->sc_rev = NCR_VARIANT_ESP200;
+ else {
+ switch ((uid & 0xf8) >> 3) {
+ case 0x00:
+ sc->sc_rev = NCR_VARIANT_FAS100A;
+ break;
+ case 0x02:
+ if ((uid & 0x07) == 0x02)
+ sc->sc_rev = NCR_VARIANT_FAS216;
+ else
+ sc->sc_rev = NCR_VARIANT_FAS236;
+ break;
+ case 0x0a:
+ sc->sc_rev = NCR_VARIANT_FAS366;
+ break;
+ default:
+ /*
+ * We could just treat unknown chips
+ * as ESP200 but then we would most
+ * likely drive them out of specs.
+ */
+ device_printf(esc->sc_dev,
+ "Unknown chip\n");
+ return (ENXIO);
+ }
+ }
}
}
@@ -390,10 +621,7 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
*/
sc->sc_minsync = 1000 / sc->sc_freq;
- /* limit minsync due to unsolved performance issues */
- sc->sc_maxsync = sc->sc_minsync;
sc->sc_maxoffset = 15;
-
sc->sc_extended_geom = 1;
/*
@@ -409,31 +637,60 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
break;
case NCR_VARIANT_ESP100A:
- sc->sc_maxwidth = 1;
+ sc->sc_maxwidth = 0;
sc->sc_maxxfer = 64 * 1024;
/* Min clocks/byte is 5 */
sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
break;
case NCR_VARIANT_ESP200:
+ sc->sc_maxwidth = 0;
+ sc->sc_maxxfer = 16 * 1024 * 1024;
+ /* Min clocks/byte is 5 */
+ sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
+ break;
+
+ case NCR_VARIANT_FAS100A:
+ case NCR_VARIANT_FAS216:
+ case NCR_VARIANT_FAS236:
+ /*
+ * The onboard SCSI chips in Sun Ultra 1 are actually
+ * documented to be NCR53C9X which use NCRCFG3_FCLK and
+ * NCRCFG3_FSCSI. BSD/OS however probes these chips as
+ * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI
+ * instead which seems to be correct as otherwise sync
+ * negotiation just doesn't work. Using NCRF9XCFG3_FCLK
+ * and NCRF9XCFG3_FSCSI with these chips in fact also
+ * yields Fast-SCSI speed.
+ */
+ sc->sc_features = NCR_F_FASTSCSI;
+ sc->sc_cfg3 = NCRF9XCFG3_FCLK;
+ sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI;
+ sc->sc_maxwidth = 0;
+ sc->sc_maxxfer = 16 * 1024 * 1024;
+ break;
+
case NCR_VARIANT_FAS366:
sc->sc_maxwidth = 1;
sc->sc_maxxfer = 16 * 1024 * 1024;
- /* XXX - do actually set FAST* bits */
break;
}
+ /* Limit minsync due to unsolved performance issues. */
+ sc->sc_maxsync = sc->sc_minsync;
+
/* Establish interrupt channel */
esc->sc_irqrid = 0;
if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ,
&esc->sc_irqrid, RF_SHAREABLE|RF_ACTIVE)) == NULL) {
- device_printf(esc->sc_dev, "Cannot allocate interrupt\n");
- return;
+ device_printf(esc->sc_dev, "cannot allocate interrupt\n");
+ return (ENXIO);
}
if (bus_setup_intr(esc->sc_dev, esc->sc_irqres,
INTR_TYPE_BIO|INTR_MPSAFE, ncr53c9x_intr, sc, &esc->sc_irq)) {
- device_printf(esc->sc_dev, "Cannot set up interrupt\n");
- return;
+ device_printf(esc->sc_dev, "cannot set up interrupt\n");
+ error = ENXIO;
+ goto fail_ires;
}
/* Turn on target selection using the `DMA' method */
@@ -442,7 +699,20 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
/* Do the common parts of attachment. */
sc->sc_dev = esc->sc_dev;
- ncr53c9x_attach(sc);
+ error = ncr53c9x_attach(sc);
+ if (error != 0) {
+ device_printf(esc->sc_dev, "ncr53c9x_attach failed\n");
+ goto fail_intr;
+ }
+
+ return (0);
+
+ fail_intr:
+ bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
+ fail_ires:
+ bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
+ esc->sc_irqres);
+ return (error);
}
/*