summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/esp/esp_sbus.c233
-rw-r--r--sys/dev/esp/ncr53c9x.c833
-rw-r--r--sys/dev/esp/ncr53c9xreg.h4
-rw-r--r--sys/dev/esp/ncr53c9xvar.h64
-rw-r--r--sys/dev/le/if_le_ledma.c62
-rw-r--r--sys/sparc64/sbus/dma_sbus.c32
-rw-r--r--sys/sparc64/sbus/lsi64854.c135
-rw-r--r--sys/sparc64/sbus/lsi64854var.h15
8 files changed, 765 insertions, 613 deletions
diff --git a/sys/dev/esp/esp_sbus.c b/sys/dev/esp/esp_sbus.c
index 962dab1..2033cc6 100644
--- a/sys/dev/esp/esp_sbus.c
+++ b/sys/dev/esp/esp_sbus.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2004 Scott Long
+ * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -71,8 +72,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/module.h>
-#include <sys/resource.h>
+#include <sys/mutex.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/openfirm.h>
@@ -83,6 +85,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
#include <sparc64/sbus/lsi64854reg.h>
#include <sparc64/sbus/lsi64854var.h>
@@ -97,12 +100,8 @@ struct esp_softc {
struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
struct device *sc_dev;
- int sc_rid;
struct resource *sc_res;
- bus_space_handle_t sc_regh;
- bus_space_tag_t sc_regt;
- int sc_irqrid;
struct resource *sc_irqres;
void *sc_irq;
@@ -155,8 +154,6 @@ static driver_t esp_sbus_driver = {
DRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0);
MODULE_DEPEND(esp, sbus, 1, 1, 1);
-MODULE_DEPEND(esp, cam, 1, 1, 1);
-
/*
* Functions and the switch for the MI code
*/
@@ -170,9 +167,11 @@ static int esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr,
static void esp_dma_go(struct ncr53c9x_softc *sc);
static void esp_dma_stop(struct ncr53c9x_softc *sc);
static int esp_dma_isactive(struct ncr53c9x_softc *sc);
-static int espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep);
+static int espattach(struct esp_softc *esc,
+ const struct ncr53c9x_glue *gluep);
+static int espdetach(struct esp_softc *esc);
-static struct ncr53c9x_glue esp_sbus_glue = {
+static const struct ncr53c9x_glue esp_sbus_glue = {
esp_read_reg,
esp_write_reg,
esp_dma_isintr,
@@ -209,29 +208,16 @@ esp_sbus_attach(device_t dev)
struct ncr53c9x_softc *sc;
struct lsi64854_softc *lsc;
device_t *children;
- const char *name;
- phandle_t node;
- int burst, error, i, nchildren, slot;
+ int error, i, nchildren;
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;
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
-
- if (strcmp(name, "SUNW,fas") == 0) {
+ if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") == 0) {
/*
* Allocate space for DMA, in SUNW,fas there are no
* separate DMA devices.
@@ -250,20 +236,18 @@ esp_sbus_attach(device_t dev)
*/
/* Allocate DMA registers. */
- lsc->sc_rid = 0;
+ i = 0;
if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &lsc->sc_rid, RF_ACTIVE)) == NULL) {
+ &i, 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. */
error = bus_dma_tag_create(
bus_get_dma_tag(dev), /* parent */
- PAGE_SIZE, 0, /* alignment, boundary */
+ 1, 0, /* alignment, boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
@@ -277,38 +261,31 @@ esp_sbus_attach(device_t dev)
device_printf(dev, "cannot allocate parent DMA tag\n");
goto fail_sbus_lres;
}
- burst = sbus_get_burstsz(dev);
+
+ i = sbus_get_burstsz(dev);
#ifdef ESP_SBUS_DEBUG
- printf("%s: burst 0x%x\n", __func__, burst);
+ printf("%s: burst 0x%x\n", __func__, i);
#endif
- lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
- (burst & SBUS_BURST_16) ? 16 : 0;
+ lsc->sc_burst = (i & SBUS_BURST_32) ? 32 :
+ (i & 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;
+ i = 1;
if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &esc->sc_rid, RF_ACTIVE)) == NULL) {
+ &i, RF_ACTIVE)) == NULL) {
device_printf(dev,
"cannot allocate SCSI core registers\n");
error = ENXIO;
- goto fail_sbus_lsi;
+ goto fail_sbus_lpdma;
}
- 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
@@ -319,10 +296,9 @@ esp_sbus_attach(device_t dev)
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 &&
+ sbus_get_slot(children[i]) == sbus_get_slot(dev) &&
strcmp(ofw_bus_get_name(children[i]), "dma") == 0) {
/* XXX hackery */
esc->sc_dma = (struct lsi64854_softc *)
@@ -340,15 +316,13 @@ esp_sbus_attach(device_t dev)
/*
* Allocate SCSI core registers.
*/
- esc->sc_rid = 0;
+ i = 0;
if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &esc->sc_rid, RF_ACTIVE)) == NULL) {
+ &i, 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);
@@ -360,15 +334,15 @@ esp_sbus_attach(device_t dev)
return (0);
fail_sbus_eres:
- bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
- if (strcmp(name, "SUNW,fas") != 0)
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
+ esc->sc_res);
+ if (strcmp(ofw_bus_get_name(dev), "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);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
+ lsc->sc_res);
fail_sbus_lsc:
free(lsc, M_DEVBUF);
return (error);
@@ -378,28 +352,22 @@ 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);
+ error = espdetach(esc);
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);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
+ 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);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
+ lsc->sc_res);
free(lsc, M_DEVBUF);
return (0);
@@ -410,29 +378,18 @@ esp_dma_attach(device_t dev)
{
struct esp_softc *esc;
struct ncr53c9x_softc *sc;
- phandle_t node;
- int error;
+ int error, i;
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) {
+ if (OF_getprop(ofw_bus_get_node(dev), "clock-frequency",
+ &sc->sc_freq, sizeof(sc->sc_freq)) == -1) {
printf("failed to query OFW for clock-frequency\n");
return (ENXIO);
}
-#ifdef ESP_SBUS_DEBUG
- device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
- sc->sc_freq);
-#endif
-
/* XXX hackery */
esc->sc_dma = (struct lsi64854_softc *)
device_get_softc(device_get_parent(dev));
@@ -441,14 +398,12 @@ esp_dma_attach(device_t dev)
/*
* Allocate SCSI core registers.
*/
- esc->sc_rid = 0;
+ i = 0;
if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &esc->sc_rid, RF_ACTIVE)) == NULL) {
+ &i, 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) {
@@ -459,7 +414,8 @@ esp_dma_attach(device_t dev)
return (0);
fail_dma_eres:
- bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
+ esc->sc_res);
return (error);
}
@@ -467,19 +423,15 @@ static int
esp_dma_detach(device_t dev)
{
struct esp_softc *esc;
- struct ncr53c9x_softc *sc;
int error;
esc = device_get_softc(dev);
- sc = &esc->sc_ncr53c9x;
- bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
- error = ncr53c9x_detach(sc);
+ error = espdetach(esc);
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);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
+ esc->sc_res);
return (0);
}
@@ -499,11 +451,29 @@ esp_resume(device_t dev)
}
static int
-espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
+espattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep)
{
struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
unsigned int uid = 0;
- int error;
+ int error, i;
+
+ NCR_LOCK_INIT(sc);
+
+ /* Attach the DMA engine. */
+ error = lsi64854_attach(esc->sc_dma);
+ if (error != 0) {
+ device_printf(esc->sc_dev, "lsi64854_attach failed\n");
+ goto fail_lock;
+ }
+
+ if (OF_getprop(ofw_bus_get_node(esc->sc_dev), "scsi-initiator-id",
+ &sc->sc_id, sizeof(sc->sc_id)) == -1)
+ sc->sc_id = 7;
+
+#ifdef ESP_SBUS_DEBUG
+ device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n",
+ __func__, sc->sc_id, sc->sc_freq);
+#endif
/*
* The `ESC' DMA chip must be reset before we can access
@@ -598,7 +568,7 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
*/
device_printf(esc->sc_dev,
"Unknown chip\n");
- return (ENXIO);
+ goto fail_lsi;
}
}
}
@@ -635,20 +605,20 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
*/
switch (sc->sc_rev) {
case NCR_VARIANT_ESP100:
- sc->sc_maxwidth = 0;
+ sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT;
sc->sc_maxxfer = 64 * 1024;
sc->sc_minsync = 0; /* No synch on old chip? */
break;
case NCR_VARIANT_ESP100A:
- sc->sc_maxwidth = 0;
+ sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT;
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_maxwidth = MSG_EXT_WDTR_BUS_8_BIT;
sc->sc_maxxfer = 16 * 1024 * 1024;
/* Min clocks/byte is 5 */
sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
@@ -670,28 +640,26 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
sc->sc_features = NCR_F_FASTSCSI;
sc->sc_cfg3 = NCRF9XCFG3_FCLK;
sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI;
- sc->sc_maxwidth = 0;
+ sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT;
sc->sc_maxxfer = 16 * 1024 * 1024;
break;
case NCR_VARIANT_FAS366:
- sc->sc_maxwidth = 1;
+ sc->sc_maxwidth = MSG_EXT_WDTR_BUS_16_BIT;
sc->sc_maxxfer = 16 * 1024 * 1024;
break;
}
- /* Limit minsync due to unsolved performance issues. */
- sc->sc_maxsync = sc->sc_minsync;
-
/* Establish interrupt channel. */
- esc->sc_irqrid = 0;
+ i = 0;
if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ,
- &esc->sc_irqrid, RF_SHAREABLE|RF_ACTIVE)) == NULL) {
+ &i, RF_SHAREABLE|RF_ACTIVE)) == NULL) {
device_printf(esc->sc_dev, "cannot allocate interrupt\n");
- return (ENXIO);
+ goto fail_lsi;
}
if (bus_setup_intr(esc->sc_dev, esc->sc_irqres,
- INTR_TYPE_BIO, NULL, ncr53c9x_intr, sc, &esc->sc_irq)) {
+ INTR_MPSAFE | INTR_TYPE_CAM, NULL, ncr53c9x_intr, sc,
+ &esc->sc_irq)) {
device_printf(esc->sc_dev, "cannot set up interrupt\n");
error = ENXIO;
goto fail_ires;
@@ -714,19 +682,43 @@ espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
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);
+ bus_release_resource(esc->sc_dev, SYS_RES_IRQ,
+ rman_get_rid(esc->sc_irqres), esc->sc_irqres);
+ fail_lsi:
+ lsi64854_detach(esc->sc_dma);
+ fail_lock:
+ NCR_LOCK_DESTROY(sc);
return (error);
}
+static int
+espdetach(struct esp_softc *esc)
+{
+ struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
+ int error;
+
+ bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
+ error = ncr53c9x_detach(sc);
+ if (error != 0)
+ return (error);
+ error = lsi64854_detach(esc->sc_dma);
+ if (error != 0)
+ return (error);
+ NCR_LOCK_DESTROY(sc);
+ bus_release_resource(esc->sc_dev, SYS_RES_IRQ,
+ rman_get_rid(esc->sc_irqres), esc->sc_irqres);
+
+ return (0);
+}
+
/*
* Glue functions
*/
#ifdef ESP_SBUS_DEBUG
-int esp_sbus_debug = 0;
+static int esp_sbus_debug = 0;
-static struct {
+static const struct {
char *r_name;
int r_flag;
} esp__read_regnames [] = {
@@ -748,7 +740,7 @@ static struct {
{ "TCX", 1}, /* f/3c */
};
-static struct {
+static const struct {
char *r_name;
int r_flag;
} esp__write_regnames[] = {
@@ -777,13 +769,15 @@ esp_read_reg(struct ncr53c9x_softc *sc, int reg)
struct esp_softc *esc = (struct esp_softc *)sc;
u_char v;
- v = bus_space_read_1(esc->sc_regt, esc->sc_regh, reg * 4);
+ v = bus_read_1(esc->sc_res, reg * 4);
+
#ifdef ESP_SBUS_DEBUG
if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
- printf("RD:%x <%s> %x\n", reg * 4,
- ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
+ printf("RD:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ?
+ esp__read_regnames[reg].r_name : "<***>", v);
#endif
- return v;
+
+ return (v);
}
static void
@@ -793,10 +787,11 @@ esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v)
#ifdef ESP_SBUS_DEBUG
if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
- printf("WR:%x <%s> %x\n", reg * 4,
- ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
+ printf("WR:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ?
+ esp__write_regnames[reg].r_name : "<***>", v);
#endif
- bus_space_write_1(esc->sc_regt, esc->sc_regh, reg * 4, v);
+
+ bus_write_1(esc->sc_res, reg * 4, v);
}
static int
diff --git a/sys/dev/esp/ncr53c9x.c b/sys/dev/esp/ncr53c9x.c
index ab94a8c..542f6c6 100644
--- a/sys/dev/esp/ncr53c9x.c
+++ b/sys/dev/esp/ncr53c9x.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2004 Scott Long
+ * Copyright (c) 2005, 2008 Marius Strobl <marius@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +26,7 @@
*
*/
-/* $NetBSD: ncr53c9x.c,v 1.114 2005/02/27 00:27:02 perry Exp $ */
+/* $NetBSD: ncr53c9x.c,v 1.125 2007/01/09 12:53:12 itohy Exp $ */
/*-
* Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
@@ -111,8 +112,8 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
-#include <sys/resource.h>
#include <sys/lock.h>
+#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <sys/time.h>
@@ -129,14 +130,22 @@ __FBSDID("$FreeBSD$");
#include <dev/esp/ncr53c9xreg.h>
#include <dev/esp/ncr53c9xvar.h>
-int ncr53c9x_debug =
+MODULE_DEPEND(esp, cam, 1, 1, 1);
+
+#ifdef NCR53C9X_DEBUG
+static int ncr53c9x_debug =
NCR_SHOWMISC /* | NCR_SHOWPHASE | NCR_SHOWTRAC | NCR_SHOWCMDS */;
-#ifdef DEBUG
-int ncr53c9x_notag = 0;
#endif
static void ncr53c9x_abort(struct ncr53c9x_softc *sc,
struct ncr53c9x_ecb *ecb);
+static void ncr53c9x_action(struct cam_sim *sim, union ccb *ccb);
+static void ncr53c9x_async(void *cbarg, uint32_t code,
+ struct cam_path *path, void *arg);
+static void ncr53c9x_callout(void *arg);
+static void ncr53c9x_clear(struct ncr53c9x_softc *sc, cam_status result);
+static void ncr53c9x_clear_target(struct ncr53c9x_softc *sc, int target,
+ cam_status result);
static void ncr53c9x_dequeue(struct ncr53c9x_softc *sc,
struct ncr53c9x_ecb *ecb);
static void ncr53c9x_done(struct ncr53c9x_softc *sc,
@@ -145,17 +154,18 @@ static void ncr53c9x_free_ecb(struct ncr53c9x_softc *sc,
struct ncr53c9x_ecb *ecb);
static void ncr53c9x_msgin(struct ncr53c9x_softc *sc);
static void ncr53c9x_msgout(struct ncr53c9x_softc *sc);
+static void ncr53c9x_init(struct ncr53c9x_softc *sc, int doreset);
+static void ncr53c9x_intr1(struct ncr53c9x_softc *sc);
static void ncr53c9x_poll(struct cam_sim *sim);
static int ncr53c9x_rdfifo(struct ncr53c9x_softc *sc, int how);
static int ncr53c9x_reselect(struct ncr53c9x_softc *sc, int message,
int tagtype, int tagid);
+static void ncr53c9x_reset(struct ncr53c9x_softc *sc);
static void ncr53c9x_sense(struct ncr53c9x_softc *sc,
struct ncr53c9x_ecb *ecb);
-static void ncr53c9x_scsi_reset(struct ncr53c9x_softc *sc);
static void ncr53c9x_sched(struct ncr53c9x_softc *sc);
static void ncr53c9x_select(struct ncr53c9x_softc *sc,
struct ncr53c9x_ecb *ecb);
-static void ncr53c9x_timeout(void *arg);
static void ncr53c9x_watch(void *arg);
static void ncr53c9x_wrfifo(struct ncr53c9x_softc *sc, u_char *p,
int len);
@@ -238,7 +248,12 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc)
struct ncr53c9x_ecb *ecb;
int error, i;
- mtx_init(&sc->sc_lock, "ncr", "ncr53c9x lock", MTX_DEF);
+ if (NCR_LOCK_INITIALIZED(sc) == 0) {
+ device_printf(sc->sc_dev, "mutex not initialized\n");
+ return (ENXIO);
+ }
+
+ callout_init_mtx(&sc->sc_watchdog, &sc->sc_lock, 0);
/*
* Note, the front-end has set us up to print the chip variation.
@@ -292,8 +307,6 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc)
goto fail_imess;
}
- callout_init(&sc->sc_watchdog, 0);
-
/*
* Treat NCR53C90 with the 86C01 DMA chip exactly as ESP100
* from now on.
@@ -334,16 +347,19 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc)
}
sim = cam_sim_alloc(ncr53c9x_action, ncr53c9x_poll, "esp", sc,
- device_get_unit(sc->sc_dev), &Giant, 1, NCR_TAG_DEPTH, devq);
+ device_get_unit(sc->sc_dev), &sc->sc_lock, 1, NCR_TAG_DEPTH, devq);
if (sim == NULL) {
device_printf(sc->sc_dev, "cannot allocate SIM entry\n");
error = ENOMEM;
goto fail_devq;
}
+
+ NCR_LOCK(sc);
+
if (xpt_bus_register(sim, sc->sc_dev, 0) != CAM_SUCCESS) {
device_printf(sc->sc_dev, "cannot register bus\n");
error = EIO;
- goto fail_sim;
+ goto fail_lock;
}
if (xpt_create_path(&path, NULL, cam_sim_path(sim),
@@ -353,6 +369,13 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc)
goto fail_bus;
}
+ if (xpt_register_async(AC_LOST_DEVICE, ncr53c9x_async, sim, path) !=
+ CAM_REQ_CMP) {
+ device_printf(sc->sc_dev, "cannot register async handler\n");
+ error = EIO;
+ goto fail_path;
+ }
+
sc->sc_sim = sim;
sc->sc_path = path;
@@ -371,7 +394,7 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc)
M_NOWAIT | M_ZERO)) == NULL) {
device_printf(sc->sc_dev, "cannot allocate ECB array\n");
error = ENOMEM;
- goto fail_path;
+ goto fail_async;
}
for (i = 0; i < NCR_TAG_DEPTH; i++) {
ecb = &sc->ecb_array[i];
@@ -380,15 +403,20 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc)
TAILQ_INSERT_HEAD(&sc->free_list, ecb, free_links);
}
- callout_reset(&sc->sc_watchdog, 60*hz, ncr53c9x_watch, sc);
+ callout_reset(&sc->sc_watchdog, 60 * hz, ncr53c9x_watch, sc);
+
+ NCR_UNLOCK(sc);
return (0);
+fail_async:
+ xpt_register_async(0, ncr53c9x_async, sim, path);
fail_path:
xpt_free_path(path);
fail_bus:
xpt_bus_deregister(cam_sim_path(sim));
-fail_sim:
+fail_lock:
+ NCR_UNLOCK(sc);
cam_sim_free(sim, TRUE);
fail_devq:
cam_simq_free(devq);
@@ -406,13 +434,33 @@ fail_omess:
int
ncr53c9x_detach(struct ncr53c9x_softc *sc)
{
+ struct ncr53c9x_linfo *li, *nextli;
+ int t;
callout_drain(&sc->sc_watchdog);
- mtx_lock(&sc->sc_lock);
- ncr53c9x_init(sc, 1);
- mtx_unlock(&sc->sc_lock);
+
+ NCR_LOCK(sc);
+
+ if (sc->sc_tinfo) {
+ /* Cancel all commands. */
+ ncr53c9x_clear(sc, CAM_REQ_ABORTED);
+
+ /* Free logical units. */
+ for (t = 0; t < sc->sc_ntarg; t++) {
+ for (li = LIST_FIRST(&sc->sc_tinfo[t].luns); li;
+ li = nextli) {
+ nextli = LIST_NEXT(li, link);
+ free(li, M_DEVBUF);
+ }
+ }
+ }
+
+ xpt_register_async(0, ncr53c9x_async, sc->sc_sim, sc->sc_path);
xpt_free_path(sc->sc_path);
xpt_bus_deregister(cam_sim_path(sc->sc_sim));
+
+ NCR_UNLOCK(sc);
+
cam_sim_free(sc->sc_sim, TRUE);
free(sc->ecb_array, M_DEVBUF);
free(sc->sc_tinfo, M_DEVBUF);
@@ -420,7 +468,6 @@ ncr53c9x_detach(struct ncr53c9x_softc *sc)
free(sc->sc_imess, M_DEVBUF);
if (sc->sc_omess_self)
free(sc->sc_omess, M_DEVBUF);
- mtx_destroy(&sc->sc_lock);
return (0);
}
@@ -433,10 +480,12 @@ ncr53c9x_detach(struct ncr53c9x_softc *sc)
* After reset, registers are loaded with the defaults from the attach
* routine above.
*/
-void
+static void
ncr53c9x_reset(struct ncr53c9x_softc *sc)
{
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
/* Reset DMA first. */
NCRDMA_RESET(sc);
@@ -477,9 +526,11 @@ ncr53c9x_reset(struct ncr53c9x_softc *sc)
sc->sc_features |=
NCR_F_HASCFG3 | NCR_F_FASTSCSI | NCR_F_SELATN3;
sc->sc_cfg3 = NCRFASCFG3_FASTCLK | NCRFASCFG3_OBAUTO;
+ if (sc->sc_id > 7)
+ sc->sc_cfg3 |= NCRFASCFG3_IDBIT3;
sc->sc_cfg3_fscsi = NCRFASCFG3_FASTSCSI;
NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
- sc->sc_cfg2 = 0; /* NCRCFG2_HMEFE | NCRCFG2_HME32 */
+ sc->sc_cfg2 = NCRCFG2_HMEFE | NCRCFG2_HME32;
NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf);
@@ -509,29 +560,73 @@ ncr53c9x_reset(struct ncr53c9x_softc *sc)
}
/*
- * Reset the SCSI bus, but not the chip.
+ * Clear all commands.
+ */
+static void
+ncr53c9x_clear(struct ncr53c9x_softc *sc, cam_status result)
+{
+ struct ncr53c9x_ecb *ecb;
+ int r;
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
+ /* Cancel any active commands. */
+ sc->sc_state = NCR_CLEANING;
+ sc->sc_msgify = 0;
+ if ((ecb = sc->sc_nexus) != NULL) {
+ ecb->ccb->ccb_h.status = result;
+ ncr53c9x_done(sc, ecb);
+ }
+ /* Cancel outstanding disconnected commands. */
+ for (r = 0; r < sc->sc_ntarg; r++)
+ ncr53c9x_clear_target(sc, r, result);
+}
+
+/*
+ * Clear all commands for a specific target.
*/
static void
-ncr53c9x_scsi_reset(struct ncr53c9x_softc *sc)
+ncr53c9x_clear_target(struct ncr53c9x_softc *sc, int target,
+ cam_status result)
{
+ struct ncr53c9x_ecb *ecb;
+ struct ncr53c9x_linfo *li;
+ int i;
- (*sc->sc_glue->gl_dma_stop)(sc);
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
- NCR_MISC(("%s: resetting SCSI bus\n", device_get_nameunit(sc->sc_dev)));
- NCRCMD(sc, NCRCMD_RSTSCSI);
- DELAY(250000); /* Give the bus a fighting chance to settle */
+ /* Cancel outstanding disconnected commands on each LUN. */
+ LIST_FOREACH(li, &sc->sc_tinfo[target].luns, link) {
+ if ((ecb = li->untagged) != NULL) {
+ li->untagged = NULL;
+ /*
+ * XXX should we terminate a command
+ * that never reached the disk?
+ */
+ li->busy = 0;
+ ecb->ccb->ccb_h.status = result;
+ ncr53c9x_done(sc, ecb);
+ }
+ for (i = 0; i < NCR_TAG_DEPTH; i++)
+ if ((ecb = li->queued[i])) {
+ li->queued[i] = NULL;
+ ecb->ccb->ccb_h.status = result;
+ ncr53c9x_done(sc, ecb);
+ }
+ li->used = 0;
+ }
}
/*
* Initialize ncr53c9x state machine.
*/
-void
+static void
ncr53c9x_init(struct ncr53c9x_softc *sc, int doreset)
{
- struct ncr53c9x_ecb *ecb;
- struct ncr53c9x_linfo *li;
struct ncr53c9x_tinfo *ti;
- int i, r;
+ int r;
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
NCR_MISC(("[NCR_INIT(%d) %d] ", doreset, sc->sc_state));
@@ -544,41 +639,8 @@ ncr53c9x_init(struct ncr53c9x_softc *sc, int doreset)
for (r = 0; r < sc->sc_ntarg; r++) {
LIST_INIT(&sc->sc_tinfo[r].luns);
}
- } else {
- /* Cancel any active commands. */
- sc->sc_state = NCR_CLEANING;
- sc->sc_msgify = 0;
- if ((ecb = sc->sc_nexus) != NULL) {
- ecb->ccb->ccb_h.status = CAM_CMD_TIMEOUT;
- ncr53c9x_done(sc, ecb);
- }
- /* Cancel outstanding disconnected commands on each LUN. */
- for (r = 0; r < sc->sc_ntarg; r++) {
- LIST_FOREACH(li, &sc->sc_tinfo[r].luns, link) {
- if ((ecb = li->untagged) != NULL) {
- li->untagged = NULL;
- /*
- * XXX
- *
- * Should we terminate a command
- * that never reached the disk?
- */
- li->busy = 0;
- ecb->ccb->ccb_h.status =
- CAM_CMD_TIMEOUT;
- ncr53c9x_done(sc, ecb);
- }
- for (i = 0; i < 256; i++)
- if ((ecb = li->queued[i])) {
- li->queued[i] = NULL;
- ecb->ccb->ccb_h.status =
- CAM_CMD_TIMEOUT;
- ncr53c9x_done(sc, ecb);
- }
- li->used = 0;
- }
- }
- }
+ } else
+ ncr53c9x_clear(sc, CAM_CMD_TIMEOUT);
/*
* Reset the chip to a known state.
@@ -589,27 +651,42 @@ ncr53c9x_init(struct ncr53c9x_softc *sc, int doreset)
sc->sc_msgpriq = sc->sc_msgout = sc->sc_msgoutq = 0;
sc->sc_phase = sc->sc_prevphase = INVALID_PHASE;
- for (r = 0; r < sc->sc_ntarg; r++) {
- ti = &sc->sc_tinfo[r];
+ /*
+ * If we're the first time through, set the default parameters
+ * for all targets. Otherwise we only clear their current transfer
+ * settings so we'll renegotiate their goal settings with the next
+ * command.
+ */
+ if (sc->sc_state == 0) {
+ for (r = 0; r < sc->sc_ntarg; r++) {
+ ti = &sc->sc_tinfo[r];
/* XXX - config flags per target: low bits: no reselect; high bits: no synch */
- ti->flags = ((sc->sc_minsync != 0 &&
- (sc->sc_cfflags & (1 << ((r & 7) + 8))) == 0) ?
- 0 : T_SYNCHOFF) |
- ((sc->sc_cfflags & (1 << (r & 7))) == 0 ?
- 0 : T_RSELECTOFF);
-#ifdef DEBUG
- if (ncr53c9x_notag)
- ti->flags &= ~T_TAG;
-#endif
- ti->period = sc->sc_minsync;
- ti->offset = 0;
- ti->cfg3 = 0;
+ ti->flags = ((sc->sc_minsync != 0 &&
+ (sc->sc_cfflags & (1 << ((r & 7) + 8))) == 0) ?
+ 0 : T_SYNCHOFF) |
+ ((sc->sc_cfflags & (1 << (r & 7))) == 0 ?
+ 0 : T_RSELECTOFF);
+ ti->curr.period = ti->goal.period = 0;
+ ti->curr.offset = ti->goal.offset = 0;
+ ti->curr.width = ti->goal.width =
+ MSG_EXT_WDTR_BUS_8_BIT;
+ }
+ } else {
+ for (r = 0; r < sc->sc_ntarg; r++) {
+ ti = &sc->sc_tinfo[r];
+ ti->flags &= ~(T_SDTRSENT | T_WDTRSENT);
+ ti->curr.period = 0;
+ ti->curr.offset = 0;
+ ti->curr.width = MSG_EXT_WDTR_BUS_8_BIT;
+ }
}
if (doreset) {
sc->sc_state = NCR_SBR;
NCRCMD(sc, NCRCMD_RSTSCSI);
+ /* Give the bus a fighting chance to settle. */
+ DELAY(250000);
} else {
sc->sc_state = NCR_IDLE;
ncr53c9x_sched(sc);
@@ -629,6 +706,8 @@ static inline void
ncr53c9x_readregs(struct ncr53c9x_softc *sc)
{
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
sc->sc_espstat = NCR_READ_REG(sc, NCR_STAT);
/* Only the step bits are of interest. */
sc->sc_espstep = NCR_READ_REG(sc, NCR_STEP) & NCRSTEP_MASK;
@@ -659,6 +738,9 @@ static inline int
ncr53c9x_stp2cpb(struct ncr53c9x_softc *sc, int period)
{
int v;
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
v = (sc->sc_freq * period) / 250;
if (ncr53c9x_cpb2stp(sc, v) < period)
/* Correct round-down error. */
@@ -669,18 +751,20 @@ ncr53c9x_stp2cpb(struct ncr53c9x_softc *sc, int period)
static inline void
ncr53c9x_setsync(struct ncr53c9x_softc *sc, struct ncr53c9x_tinfo *ti)
{
- u_char syncoff, synctp;
- u_char cfg3 = sc->sc_cfg3 | ti->cfg3;
+ u_char cfg3, syncoff, synctp;
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
- if (ti->flags & T_SYNCMODE) {
- syncoff = ti->offset;
- synctp = ncr53c9x_stp2cpb(sc, ti->period);
+ cfg3 = sc->sc_cfg3;
+ if (ti->curr.offset != 0) {
+ syncoff = ti->curr.offset;
+ synctp = ncr53c9x_stp2cpb(sc, ti->curr.period);
if (sc->sc_features & NCR_F_FASTSCSI) {
/*
* If the period is 200ns or less (ti->period <= 50),
* put the chip in Fast SCSI mode.
*/
- if (ti->period <= 50)
+ if (ti->curr.period <= 50)
/*
* There are (at least) 4 variations of the
* configuration 3 register. The drive attach
@@ -703,6 +787,11 @@ ncr53c9x_setsync(struct ncr53c9x_softc *sc, struct ncr53c9x_tinfo *ti)
synctp = 0;
}
+ if (ti->curr.width != MSG_EXT_WDTR_BUS_8_BIT) {
+ if (sc->sc_rev == NCR_VARIANT_FAS366)
+ cfg3 |= NCRFASCFG3_EWIDE;
+ }
+
if (sc->sc_features & NCR_F_HASCFG3)
NCR_WRITE_REG(sc, NCR_CFG3, cfg3);
@@ -727,18 +816,19 @@ ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
int lun = ecb->ccb->ccb_h.target_lun;
int target = ecb->ccb->ccb_h.target_id;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
NCR_TRACE(("[ncr53c9x_select(t%d,l%d,cmd:%x,tag:%x,%x)] ",
target, lun, ecb->cmd.cmd.opcode, ecb->tag[0], ecb->tag[1]));
ti = &sc->sc_tinfo[target];
sc->sc_state = NCR_SELECTING;
/*
- * Schedule the timeout now, the first time we will go away
+ * Schedule the callout now, the first time we will go away
* expecting to come back due to an interrupt, because it is
* always possible that the interrupt may never happen.
*/
- ecb->ccb->ccb_h.timeout_ch =
- timeout(ncr53c9x_timeout, ecb, mstohz(ecb->timeout));
+ callout_reset(&ecb->ch, mstohz(ecb->timeout), ncr53c9x_callout, ecb);
/*
* The docs say the target register is never reset, and I
@@ -746,41 +836,24 @@ ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
*/
if (sc->sc_rev == NCR_VARIANT_FAS366) {
NCRCMD(sc, NCRCMD_FLUSH);
- NCR_WRITE_REG(sc, NCR_SELID, target | NCR_BUSID_HME);
+ NCR_WRITE_REG(sc, NCR_SELID, target | NCR_BUSID_HMEXC32 |
+ NCR_BUSID_HMEENCID);
} else {
NCR_WRITE_REG(sc, NCR_SELID, target);
}
- ncr53c9x_setsync(sc, ti);
-
- if ((ecb->flags & ECB_SENSE) != 0) {
- /*
- * For REQUEST SENSE, we should not send an IDENTIFY or
- * otherwise mangle the target. There should be no MESSAGE IN
- * phase.
- */
- if (sc->sc_features & NCR_F_DMASELECT) {
- /* setup DMA transfer for command */
- dmasize = clen = ecb->clen;
- sc->sc_cmdlen = clen;
- sc->sc_cmdp = (caddr_t)&ecb->cmd.cmd;
- /* Program the SCSI counter */
- NCR_SET_COUNT(sc, dmasize);
-
- if (sc->sc_rev != NCR_VARIANT_FAS366)
- NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
-
- /* And get the target's attention */
- NCRCMD(sc, NCRCMD_SELNATN | NCRCMD_DMA);
- NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0,
- &dmasize);
- NCRDMA_GO(sc);
- } else {
- ncr53c9x_wrfifo(sc, (u_char *)&ecb->cmd.cmd, ecb->clen);
- NCRCMD(sc, NCRCMD_SELNATN);
- }
- return;
+ /*
+ * If we are requesting sense, force a renegotiation if we are
+ * currently using anything different from asynchronous at 8 bit
+ * as the target might have lost our transfer negotiations.
+ */
+ if ((ecb->flags & ECB_SENSE) != 0 && (ti->curr.offset != 0 ||
+ ti->curr.width != MSG_EXT_WDTR_BUS_8_BIT)) {
+ ti->curr.period = 0;
+ ti->curr.offset = 0;
+ ti->curr.width = MSG_EXT_WDTR_BUS_8_BIT;
}
+ ncr53c9x_setsync(sc, ti);
selatn3 = selatns = 0;
if (ecb->tag[0] != 0) {
@@ -792,7 +865,9 @@ ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
selatns = 1;
}
- if (ti->flags & T_NEGOTIATE) {
+ if (ti->curr.period != ti->goal.period ||
+ ti->curr.offset != ti->goal.offset ||
+ ti->curr.width != ti->goal.width) {
/* We have to use SELATNS to send sync/wide messages. */
selatn3 = 0;
selatns = 1;
@@ -819,7 +894,7 @@ ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
dmasize = clen;
sc->sc_cmdlen = clen;
sc->sc_cmdp = cmd;
-
+ NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmasize);
/* Program the SCSI counter. */
NCR_SET_COUNT(sc, dmasize);
@@ -834,7 +909,6 @@ ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
NCRCMD(sc, NCRCMD_SELATN3 | NCRCMD_DMA);
} else
NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);
- NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmasize);
NCRDMA_GO(sc);
return;
}
@@ -864,6 +938,8 @@ static void
ncr53c9x_free_ecb(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
{
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
ecb->flags = 0;
TAILQ_INSERT_TAIL(&sc->free_list, ecb, free_links);
}
@@ -873,6 +949,8 @@ ncr53c9x_get_ecb(struct ncr53c9x_softc *sc)
{
struct ncr53c9x_ecb *ecb;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
ecb = TAILQ_FIRST(&sc->free_list);
if (ecb) {
if (ecb->flags != 0)
@@ -895,7 +973,7 @@ ncr53c9x_get_ecb(struct ncr53c9x_softc *sc)
* SCSI-commands.
*/
-void
+static void
ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
{
struct ccb_pathinq *cpi;
@@ -908,21 +986,20 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
struct ncr53c9x_tinfo *ti;
int target;
- NCR_TRACE(("[ncr53c9x_action %d]", ccb->ccb_h.func_code));
-
sc = cam_sim_softc(sim);
- mtx_lock(&sc->sc_lock);
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
+ NCR_TRACE(("[ncr53c9x_action %d]", ccb->ccb_h.func_code));
switch (ccb->ccb_h.func_code) {
case XPT_RESET_BUS:
- ncr53c9x_scsi_reset(sc);
+ ncr53c9x_init(sc, 1);
ccb->ccb_h.status = CAM_REQ_CMP;
- mtx_unlock(&sc->sc_lock);
xpt_done(ccb);
return;
case XPT_CALC_GEOMETRY:
- mtx_unlock(&sc->sc_lock);
cam_calc_geometry(&ccb->ccg, sc->sc_extended_geom);
xpt_done(ccb);
return;
@@ -937,7 +1014,7 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_misc = 0;
cpi->hba_eng_cnt = 0;
cpi->max_target = sc->sc_ntarg - 1;
- cpi->max_lun = 8;
+ cpi->max_lun = 7;
cpi->initiator_id = sc->sc_id;
cpi->bus_id = 0;
cpi->base_transfer_speed = 3300;
@@ -950,7 +1027,6 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_2;
ccb->ccb_h.status = CAM_REQ_CMP;
- mtx_unlock(&sc->sc_lock);
xpt_done(ccb);
return;
@@ -966,9 +1042,9 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
cts->transport_version = 2;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
- spi->sync_period = ti->period;
- spi->sync_offset = ti->offset;
- spi->bus_width = ti->width;
+ spi->sync_period = ti->curr.period;
+ spi->sync_offset = ti->curr.offset;
+ spi->bus_width = ti->curr.width;
if ((ti->flags & T_TAG) != 0) {
spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
@@ -977,8 +1053,13 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
}
} else {
- spi->sync_period = sc->sc_maxsync;
- spi->sync_offset = sc->sc_maxoffset;
+ if ((ti->flags & T_SYNCHOFF) != 0) {
+ spi->sync_period = 0;
+ spi->sync_offset = 0;
+ } else {
+ spi->sync_period = sc->sc_minsync;
+ spi->sync_offset = sc->sc_maxoffset;
+ }
spi->bus_width = sc->sc_maxwidth;
spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
@@ -990,31 +1071,26 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
CTS_SPI_VALID_DISC;
scsi->valid = CTS_SCSI_VALID_TQ;
ccb->ccb_h.status = CAM_REQ_CMP;
- mtx_unlock(&sc->sc_lock);
xpt_done(ccb);
return;
case XPT_ABORT:
- printf("XPT_ABORT called\n");
+ device_printf(sc->sc_dev, "XPT_ABORT called\n");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- mtx_unlock(&sc->sc_lock);
xpt_done(ccb);
return;
case XPT_TERM_IO:
- printf("XPT_TERM_IO called\n");
+ device_printf(sc->sc_dev, "XPT_TERM_IO called\n");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- mtx_unlock(&sc->sc_lock);
xpt_done(ccb);
return;
case XPT_RESET_DEV:
- printf("XPT_RESET_DEV called\n");
case XPT_SCSI_IO:
if (ccb->ccb_h.target_id < 0 ||
ccb->ccb_h.target_id >= sc->sc_ntarg) {
ccb->ccb_h.status = CAM_PATH_INVALID;
- mtx_unlock(&sc->sc_lock);
xpt_done(ccb);
return;
}
@@ -1027,8 +1103,7 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
if (ecb == NULL) {
xpt_freeze_simq(sim, 1);
ccb->ccb_h.status = CAM_REQUEUE_REQ;
- printf("unable to allocate ecb\n");
- mtx_unlock(&sc->sc_lock);
+ device_printf(sc->sc_dev, "unable to allocate ecb\n");
xpt_done(ccb);
return;
}
@@ -1079,35 +1154,23 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
}
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
- if (spi->bus_width != 0) {
- NCR_MISC(("%s: target %d: wide negotiation\n",
- device_get_nameunit(sc->sc_dev), target));
- if (sc->sc_rev == NCR_VARIANT_FAS366) {
- ti->flags |= T_WIDE;
- ti->width = 1;
- }
- } else {
- ti->flags &= ~T_WIDE;
- ti->width = 0;
- }
- ti->flags |= T_NEGOTIATE;
+ NCR_MISC(("%s: target %d: wide negotiation\n",
+ device_get_nameunit(sc->sc_dev), target));
+ ti->goal.width = spi->bus_width;
}
if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
NCR_MISC(("%s: target %d: sync period negotiation\n",
device_get_nameunit(sc->sc_dev), target));
- ti->flags |= T_NEGOTIATE;
- ti->period = spi->sync_period;
+ ti->goal.period = spi->sync_period;
}
if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) {
NCR_MISC(("%s: target %d: sync offset negotiation\n",
device_get_nameunit(sc->sc_dev), target));
- ti->flags |= T_NEGOTIATE;
- ti->offset = spi->sync_offset;
+ ti->goal.offset = spi->sync_offset;
}
- mtx_unlock(&sc->sc_lock);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
@@ -1116,12 +1179,9 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb)
device_printf(sc->sc_dev, "Unhandled function code %d\n",
ccb->ccb_h.func_code);
ccb->ccb_h.status = CAM_PROVIDE_FAIL;
- mtx_unlock(&sc->sc_lock);
xpt_done(ccb);
return;
}
-
- mtx_unlock(&sc->sc_lock);
}
/*
@@ -1132,10 +1192,51 @@ ncr53c9x_poll(struct cam_sim *sim)
{
struct ncr53c9x_softc *sc;
- NCR_TRACE(("[ncr53c9x_poll] "));
sc = cam_sim_softc(sim);
- if (NCRDMA_ISINTR(sc)) {
- ncr53c9x_intr(sc);
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
+ NCR_TRACE(("[ncr53c9x_poll] "));
+
+ if (NCRDMA_ISINTR(sc))
+ ncr53c9x_intr1(sc);
+}
+
+/*
+ * Asynchronous notification handler
+ */
+static void
+ncr53c9x_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
+{
+ struct ncr53c9x_softc *sc;
+ struct ncr53c9x_tinfo *ti;
+ int target;
+
+ sc = cam_sim_softc(cbarg);
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
+ switch (code) {
+ case AC_LOST_DEVICE:
+ target = xpt_path_target_id(path);
+ if (target < 0 || target >= sc->sc_ntarg)
+ break;
+
+ /* Cancel outstanding disconnected commands. */
+ ncr53c9x_clear_target(sc, target, CAM_REQ_ABORTED);
+
+ /* Set the default parameters for the target. */
+ ti = &sc->sc_tinfo[target];
+/* XXX - config flags per target: low bits: no reselect; high bits: no synch */
+ ti->flags = ((sc->sc_minsync != 0 &&
+ (sc->sc_cfflags & (1 << ((target & 7) + 8))) == 0) ?
+ 0 : T_SYNCHOFF) |
+ ((sc->sc_cfflags & (1 << (target & 7))) == 0 ?
+ 0 : T_RSELECTOFF);
+ ti->curr.period = ti->goal.period = 0;
+ ti->curr.offset = ti->goal.offset = 0;
+ ti->curr.width = ti->goal.width = MSG_EXT_WDTR_BUS_8_BIT;
+ break;
}
}
@@ -1145,9 +1246,9 @@ ncr53c9x_poll(struct cam_sim *sim)
/*
* Schedule a SCSI operation. This has now been pulled out of the interrupt
- * handler so that we may call it from ncr53c9x_scsipi_request and
- * ncr53c9x_done. This may save us an unnecessary interrupt just to get
- * things going. Should only be called when state == NCR_IDLE and at bio pl.
+ * handler so that we may call it from ncr53c9x_action and ncr53c9x_done.
+ * This may save us an unnecessary interrupt just to get things going.
+ * Should only be called when state == NCR_IDLE and with sc_lock held.
*/
static void
ncr53c9x_sched(struct ncr53c9x_softc *sc)
@@ -1157,6 +1258,8 @@ ncr53c9x_sched(struct ncr53c9x_softc *sc)
struct ncr53c9x_tinfo *ti;
int lun, tag;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
NCR_TRACE(("[ncr53c9x_sched] "));
if (sc->sc_state != NCR_IDLE)
@@ -1166,15 +1269,12 @@ ncr53c9x_sched(struct ncr53c9x_softc *sc)
* Find first ecb in ready queue that is for a target/lunit
* combinations that is not busy.
*/
- for (ecb = TAILQ_FIRST(&sc->ready_list); ecb != NULL;
- ecb = TAILQ_NEXT(ecb, chain)) {
+ TAILQ_FOREACH(ecb, &sc->ready_list, chain) {
ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
lun = ecb->ccb->ccb_h.target_lun;
/* Select type of tag for this command */
- if ((ti->flags & (T_RSELECTOFF)) != 0)
- tag = 0;
- else if ((ti->flags & (T_TAG)) == 0)
+ if ((ti->flags & (T_RSELECTOFF | T_TAG)) != T_TAG)
tag = 0;
else if ((ecb->flags & ECB_SENSE) != 0)
tag = 0;
@@ -1254,6 +1354,8 @@ ncr53c9x_sense(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
struct scsi_request_sense *ss = (void *)&ecb->cmd.cmd;
int lun;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
NCR_TRACE(("requesting sense "));
lun = ccb->ccb_h.target_lun;
@@ -1297,57 +1399,65 @@ ncr53c9x_done(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
struct ncr53c9x_tinfo *ti;
int lun;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
NCR_TRACE(("[ncr53c9x_done(status:%x)] ", ccb->ccb_h.status));
ti = &sc->sc_tinfo[ccb->ccb_h.target_id];
lun = ccb->ccb_h.target_lun;
li = TINFO_LUN(ti, lun);
- untimeout(ncr53c9x_timeout, ecb, ccb->ccb_h.timeout_ch);
+ callout_stop(&ecb->ch);
/*
* Now, if we've come here with no error code, i.e. we've kept the
- * initial XS_NOERROR, and the status code signals that we should
+ * initial CAM_REQ_CMP, and the status code signals that we should
* check sense, we'll need to set up a request sense cmd block and
* push the command back into the ready queue *before* any other
* commands for this target/lunit, else we lose the sense info.
* We don't support chk sense conditions for the request sense cmd.
*/
if (ccb->ccb_h.status == CAM_REQ_CMP) {
+ ccb->csio.scsi_status = ecb->stat;
if ((ecb->flags & ECB_ABORT) != 0) {
ccb->ccb_h.status = CAM_CMD_TIMEOUT;
} else if ((ecb->flags & ECB_SENSE) != 0 &&
(ecb->stat != SCSI_STATUS_CHECK_COND)) {
- ccb->ccb_h.status = CAM_AUTOSNS_VALID;
+ ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
+ CAM_AUTOSNS_VALID;
} else if (ecb->stat == SCSI_STATUS_CHECK_COND) {
if ((ecb->flags & ECB_SENSE) != 0)
ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
else {
/* First, save the return values. */
ccb->csio.resid = ecb->dleft;
- ncr53c9x_sense(sc, ecb);
- return;
+ if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) ==
+ 0) {
+ ncr53c9x_sense(sc, ecb);
+ return;
+ }
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
}
} else {
ccb->csio.resid = ecb->dleft;
}
-#if 0
- if (xs->status == SCSI_QUEUE_FULL || xs->status == XS_BUSY)
- xs->error = XS_BUSY;
-#endif
+ if (ecb->stat == SCSI_STATUS_QUEUE_FULL)
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ else if (ecb->stat == SCSI_STATUS_BUSY)
+ ccb->ccb_h.status = CAM_SCSI_BUSY;
}
#ifdef NCR53C9X_DEBUG
if (ncr53c9x_debug & NCR_SHOWTRAC) {
if (ccb->csio.resid != 0)
printf("resid=%d ", ccb->csio.resid);
-#if 0
- if (xs->error == XS_SENSE)
+ if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
printf("sense=0x%02x\n",
- xs->sense.scsi_sense.error_code);
+ ccb->csio.sense_data.error_code);
else
- printf("error=%d\n", xs->error);
-#endif
+ printf("status SCSI=0x%x CAM=0x%x\n",
+ ccb->csio.scsi_status, ccb->ccb_h.status);
}
#endif
@@ -1385,6 +1495,8 @@ ncr53c9x_dequeue(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
struct ncr53c9x_tinfo *ti;
int64_t lun;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
lun = ecb->ccb->ccb_h.target_lun;
li = TINFO_LUN(ti, lun);
@@ -1408,6 +1520,7 @@ ncr53c9x_dequeue(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
li->queued[ecb->tag[1]] = NULL;
li->used--;
}
+ ecb->tag[0] = ecb->tag[1] = 0;
if ((ecb->flags & ECB_READY) != 0) {
ecb->flags &= ~ECB_READY;
@@ -1434,6 +1547,9 @@ ncr53c9x_dequeue(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
static void
ncr53c9x_flushfifo(struct ncr53c9x_softc *sc)
{
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
NCR_TRACE(("[flushfifo] "));
NCRCMD(sc, NCRCMD_FLUSH);
@@ -1449,6 +1565,8 @@ ncr53c9x_rdfifo(struct ncr53c9x_softc *sc, int how)
u_char *ibuf;
int i, n;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
switch (how) {
case NCR_RDFIFO_START:
ibuf = sc->sc_imess;
@@ -1511,6 +1629,8 @@ ncr53c9x_wrfifo(struct ncr53c9x_softc *sc, u_char *p, int len)
{
int i;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
#ifdef NCR53C9X_DEBUG
NCR_MSGS(("[wrfifo(%d):", len));
if (ncr53c9x_debug & NCR_SHOWMSGS) {
@@ -1537,6 +1657,7 @@ ncr53c9x_reselect(struct ncr53c9x_softc *sc, int message, int tagtype,
struct ncr53c9x_tinfo *ti;
u_char lun, selid, target;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
if (sc->sc_rev == NCR_VARIANT_FAS366) {
target = sc->sc_selid;
@@ -1651,6 +1772,8 @@ ncr53c9x_msgin(struct ncr53c9x_softc *sc)
u_char *pb;
int lun, plen;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
NCR_TRACE(("[ncr53c9x_msgin(curmsglen:%ld)] ", (long)sc->sc_imlen));
if (sc->sc_imlen == 0) {
@@ -1678,7 +1801,8 @@ ncr53c9x_msgin(struct ncr53c9x_softc *sc)
*/
if ((sc->sc_flags & NCR_DROP_MSGI) != 0) {
NCRCMD(sc, NCRCMD_MSGOK);
- printf("<dropping msg byte %x>", sc->sc_imess[sc->sc_imlen]);
+ device_printf(sc->sc_dev, "<dropping msg byte %x>",
+ sc->sc_imess[sc->sc_imlen]);
return;
}
@@ -1778,8 +1902,9 @@ gotit:
"rejected: target %d\n",
ecb->ccb->ccb_h.target_id);
- sc->sc_flags &= ~NCR_SYNCHNEGO;
- ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE);
+ ti->flags &= ~T_SDTRSENT;
+ ti->curr.period = ti->goal.period = 0;
+ ti->curr.offset = ti->goal.offset = 0;
ncr53c9x_setsync(sc, ti);
break;
@@ -1787,8 +1912,11 @@ gotit:
device_printf(sc->sc_dev, "wide transfer "
"rejected: target %d\n",
ecb->ccb->ccb_h.target_id);
- ti->flags &= ~(T_WIDE | T_WDTRSENT);
- ti->width = 0;
+
+ ti->flags &= ~T_WDTRSENT;
+ ti->curr.width = ti->goal.width =
+ MSG_EXT_WDTR_BUS_8_BIT;
+ ncr53c9x_setsync(sc, ti);
break;
case SEND_INIT_DET_ERR:
@@ -1842,71 +1970,63 @@ gotit:
sc->sc_imess[3], sc->sc_imess[4]));
if (sc->sc_imess[1] != 3)
goto reject;
- ti->period = sc->sc_imess[3];
- ti->offset = sc->sc_imess[4];
- ti->flags &= ~T_NEGOTIATE;
+ ti->curr.period = sc->sc_imess[3];
+ ti->curr.offset = sc->sc_imess[4];
if (sc->sc_minsync == 0 ||
- ti->offset == 0 ||
- ti->period > 124) {
+ ti->curr.offset == 0 ||
+ ti->curr.period > 124) {
#if 0
#ifdef NCR53C9X_DEBUG
xpt_print_path(ecb->ccb->ccb_h.path);
printf("async mode\n");
#endif
#endif
- ti->flags &= ~T_SYNCMODE;
- if ((sc->sc_flags & NCR_SYNCHNEGO) ==
- 0) {
+ if ((ti->flags & T_SDTRSENT) == 0) {
/*
* target initiated negotiation
*/
- ti->offset = 0;
+ ti->curr.offset = 0;
ncr53c9x_sched_msgout(
SEND_SDTR);
}
} else {
- ti->period =
+ ti->curr.period =
ncr53c9x_cpb2stp(sc,
ncr53c9x_stp2cpb(sc,
- ti->period));
- if ((sc->sc_flags & NCR_SYNCHNEGO) ==
- 0) {
+ ti->curr.period));
+ if ((ti->flags & T_SDTRSENT) == 0) {
/*
* target initiated negotiation
*/
- if (ti->period < sc->sc_minsync)
- ti->period =
+ if (ti->curr.period <
+ sc->sc_minsync)
+ ti->curr.period =
sc->sc_minsync;
- if (ti->offset > 15)
- ti->offset = 15;
- ti->flags &= ~T_SYNCMODE;
+ if (ti->curr.offset >
+ sc->sc_maxoffset)
+ ti->curr.offset =
+ sc->sc_maxoffset;
ncr53c9x_sched_msgout(
SEND_SDTR);
- } else {
- /* We are sync. */
- ti->flags |= T_SYNCMODE;
}
}
- sc->sc_flags &= ~NCR_SYNCHNEGO;
+ ti->flags &= ~T_SDTRSENT;
+ ti->goal.period = ti->curr.period;
+ ti->goal.offset = ti->curr.offset;
ncr53c9x_setsync(sc, ti);
break;
case MSG_EXT_WDTR:
-#ifdef NCR53C9X_DEBUG
- device_printf(sc->sc_dev, "wide mode %d\n",
- sc->sc_imess[3]);
-#endif
- if (sc->sc_imess[3] == 1) {
- ti->cfg3 |= NCRFASCFG3_EWIDE;
- ncr53c9x_setsync(sc, ti);
- } else
- ti->width = 0;
- /*
- * Device started width negotiation.
- */
+ NCR_MSGS(("wide mode %d ", sc->sc_imess[3]));
+ ti->curr.width = sc->sc_imess[3];
if (!(ti->flags & T_WDTRSENT))
+ /*
+ * target initiated negotiation
+ */
ncr53c9x_sched_msgout(SEND_WDTR);
- ti->flags &= ~(T_WIDE | T_WDTRSENT);
+ ti->flags &= ~T_WDTRSENT;
+ ti->goal.width = ti->curr.width;
+ ncr53c9x_setsync(sc, ti);
break;
default:
@@ -1968,8 +2088,10 @@ gotit:
}
/* If we have more messages to send set ATN. */
- if (sc->sc_msgpriq)
+ if (sc->sc_msgpriq) {
NCRCMD(sc, NCRCMD_SETATN);
+ sc->sc_flags |= NCR_ATN;
+ }
/* Acknowledge last message byte. */
NCRCMD(sc, NCRCMD_MSGOK);
@@ -1992,6 +2114,8 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
int i;
#endif
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
NCR_TRACE(("[ncr53c9x_msgout(priq:%x, prevphase:%x)]",
sc->sc_msgpriq, sc->sc_prevphase));
@@ -2033,13 +2157,9 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
sc->sc_omess[0] = MSG_EXTENDED;
sc->sc_omess[1] = MSG_EXT_SDTR_LEN;
sc->sc_omess[2] = MSG_EXT_SDTR;
- sc->sc_omess[3] = ti->period;
- sc->sc_omess[4] = ti->offset;
+ sc->sc_omess[3] = ti->goal.period;
+ sc->sc_omess[4] = ti->goal.offset;
sc->sc_omlen = 5;
- if ((sc->sc_flags & NCR_SYNCHNEGO) == 0) {
- ti->flags |= T_SYNCMODE;
- ncr53c9x_setsync(sc, ti);
- }
break;
case SEND_WDTR:
@@ -2048,7 +2168,7 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
sc->sc_omess[0] = MSG_EXTENDED;
sc->sc_omess[1] = MSG_EXT_WDTR_LEN;
sc->sc_omess[2] = MSG_EXT_WDTR;
- sc->sc_omess[3] = ti->width;
+ sc->sc_omess[3] = ti->goal.width;
sc->sc_omlen = 4;
break;
@@ -2078,10 +2198,9 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
sc->sc_omess[0] = MSG_BUS_DEV_RESET;
ecb = sc->sc_nexus;
ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
- ti->flags &= ~T_SYNCMODE;
- if ((ti->flags & T_SYNCHOFF) == 0)
- /* We can re-start sync negotiation. */
- ti->flags |= T_NEGOTIATE;
+ ti->curr.period = 0;
+ ti->curr.offset = 0;
+ ti->curr.width = MSG_EXT_WDTR_BUS_8_BIT;
break;
case SEND_PARITY_ERROR:
@@ -2138,7 +2257,7 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
NCRCMD(sc, NCRCMD_TRANS);
} else {
/* (Re)send the message. */
- size = min(sc->sc_omlen, sc->sc_maxxfer);
+ size = ulmin(sc->sc_omlen, sc->sc_maxxfer);
NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size);
/* Program the SCSI counter. */
NCR_SET_COUNT(sc, size);
@@ -2150,6 +2269,21 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
}
}
+void
+ncr53c9x_intr(void *arg)
+{
+ struct ncr53c9x_softc *sc = arg;
+
+ if (!NCRDMA_ISINTR(sc))
+ return;
+
+ NCR_LOCK(sc);
+
+ ncr53c9x_intr1(sc);
+
+ NCR_UNLOCK(sc);
+}
+
/*
* This is the most critical part of the driver, and has to know
* how to deal with *all* error conditions and phases from the SCSI
@@ -2159,10 +2293,9 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
*
* Most of this needs verifying.
*/
-void
-ncr53c9x_intr(void *arg)
+static void
+ncr53c9x_intr1(struct ncr53c9x_softc *sc)
{
- struct ncr53c9x_softc *sc = arg;
struct ncr53c9x_ecb *ecb;
struct ncr53c9x_linfo *li;
struct ncr53c9x_tinfo *ti;
@@ -2171,12 +2304,10 @@ ncr53c9x_intr(void *arg)
int i, nfifo;
u_char msg;
- NCR_INTS(("[ncr53c9x_intr: state %d]", sc->sc_state));
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
- if (!NCRDMA_ISINTR(sc))
- return;
+ NCR_INTS(("[ncr53c9x_intr: state %d]", sc->sc_state));
- mtx_lock(&sc->sc_lock);
again:
/* and what do the registers say... */
ncr53c9x_readregs(sc);
@@ -2206,10 +2337,10 @@ again:
if (sc->sc_state != NCR_SBR) {
device_printf(sc->sc_dev, "SCSI bus reset\n");
ncr53c9x_init(sc, 0); /* Restart everything. */
- goto out;
+ return;
}
#if 0
-/*XXX*/ printf("<expected bus reset: "
+/*XXX*/ device_printf(sc->sc_dev, "<expected bus reset: "
"[intr %x, stat %x, step %d]>\n",
sc->sc_espintr, sc->sc_espstat, sc->sc_espstep);
#endif
@@ -2235,7 +2366,7 @@ again:
ecb->ccb->ccb_h.status = CAM_SEL_TIMEOUT;
ncr53c9x_done(sc, ecb);
}
- goto out;
+ return;
}
if ((sc->sc_espintr & NCRINTR_ILL) != 0) {
@@ -2251,7 +2382,7 @@ again:
"activated\n");
#endif
sc->sc_flags &= ~NCR_EXPECT_ILLCMD;
- goto out;
+ return;
}
/* Illegal command, out of sync? */
device_printf(sc->sc_dev, "illegal command: 0x%x "
@@ -2262,8 +2393,7 @@ again:
NCRCMD(sc, NCRCMD_FLUSH);
DELAY(1);
}
- ncr53c9x_init(sc, 1); /* Restart everything. */
- goto out;
+ goto reset;
}
}
sc->sc_flags &= ~NCR_EXPECT_ILLCMD;
@@ -2278,12 +2408,11 @@ again:
if (NCRDMA_ISACTIVE(sc)) {
if (NCRDMA_INTR(sc) == -1) {
device_printf(sc->sc_dev, "DMA error; resetting\n");
- ncr53c9x_init(sc, 1);
- goto out;
+ goto reset;
}
/* If DMA active here, then go back to work... */
if (NCRDMA_ISACTIVE(sc))
- goto out;
+ return;
if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
/*
@@ -2333,7 +2462,7 @@ again:
sc->sc_espstep,
sc->sc_prevphase,
ecb ? ecb->dleft : -1);
- panic("esp: unrecoverable DMA error");
+ goto reset;
}
}
}
@@ -2390,15 +2519,24 @@ again:
goto finish;
case NCR_CONNECTED:
- if ((sc->sc_flags & NCR_SYNCHNEGO) != 0) {
-#ifdef NCR53C9X_DEBUG
- if (ecb != NULL)
- xpt_print_path(ecb->ccb->ccb_h.path);
- printf("sync nego not completed!\n");
-#endif
+ if (ecb != NULL) {
ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
- sc->sc_flags &= ~NCR_SYNCHNEGO;
- ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE);
+ if ((ti->flags & T_SDTRSENT) != 0) {
+ xpt_print_path(ecb->ccb->ccb_h.path);
+ printf("sync nego not completed!\n");
+ ti->flags &= ~T_SDTRSENT;
+ ti->curr.period = ti->goal.period = 0;
+ ti->curr.offset = ti->goal.offset = 0;
+ ncr53c9x_setsync(sc, ti);
+ }
+ if ((ti->flags & T_WDTRSENT) != 0) {
+ xpt_print_path(ecb->ccb->ccb_h.path);
+ printf("wide nego not completed!\n");
+ ti->flags &= ~T_WDTRSENT;
+ ti->curr.width = ti->goal.width =
+ MSG_EXT_WDTR_BUS_8_BIT;
+ ncr53c9x_setsync(sc, ti);
+ }
}
/* It may be OK to disconnect. */
@@ -2431,10 +2569,13 @@ again:
goto reset;
}
printf("sending REQUEST SENSE\n");
- untimeout(ncr53c9x_timeout, ecb,
- ecb->ccb->ccb_h.timeout_ch);
+ callout_stop(&ecb->ch);
ncr53c9x_sense(sc, ecb);
- goto out;
+ return;
+ } else if (ecb != NULL &&
+ (ecb->flags & ECB_RESET) != 0) {
+ ecb->ccb->ccb_h.status = CAM_REQ_CMP;
+ goto finish;
}
ecb->ccb->ccb_h.status = CAM_CMD_TIMEOUT;
@@ -2453,7 +2594,7 @@ again:
switch (sc->sc_state) {
case NCR_SBR:
device_printf(sc->sc_dev, "waiting for Bus Reset to happen\n");
- goto out;
+ return;
case NCR_RESELECTED:
/*
@@ -2461,8 +2602,7 @@ again:
*/
device_printf(sc->sc_dev, "unhandled reselect continuation, "
"state %d, intr %02x\n", sc->sc_state, sc->sc_espintr);
- ncr53c9x_init(sc, 1);
- goto out;
+ goto reset;
break;
case NCR_IDENTIFIED:
@@ -2479,8 +2619,7 @@ again:
while (i-- > 0)
printf("[%d] ", NCR_READ_REG(sc, NCR_FIFO));
- ncr53c9x_init(sc, 1);
- goto out;
+ goto reset;
} else
goto msgin;
@@ -2497,8 +2636,7 @@ again:
*/
if (sc->sc_state == NCR_SELECTING) {
NCR_INTS(("backoff selector "));
- untimeout(ncr53c9x_timeout, ecb,
- ecb->ccb->ccb_h.timeout_ch);
+ callout_stop(&ecb->ch);
ncr53c9x_dequeue(sc, ecb);
TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
ecb->flags |= ECB_READY;
@@ -2512,8 +2650,7 @@ again:
*/
device_printf(sc->sc_dev, "target didn't "
"identify\n");
- ncr53c9x_init(sc, 1);
- goto out;
+ goto reset;
}
/*
* The C90 only inhibits FIFO writes until reselection
@@ -2555,8 +2692,7 @@ again:
sc->sc_espstat,
sc->sc_espstep,
sc->sc_prevphase);
- ncr53c9x_init(sc, 1);
- goto out;
+ goto reset;
}
sc->sc_selid = sc->sc_imess[0];
NCR_INTS(("selid=%02x ", sc->sc_selid));
@@ -2570,8 +2706,7 @@ again:
device_printf(sc->sc_dev, "identify failed, "
"state %d, intr %02x\n", sc->sc_state,
sc->sc_espintr);
- ncr53c9x_init(sc, 1);
- goto out;
+ goto reset;
}
goto shortcut; /* i.e. next phase expected soon */
}
@@ -2590,7 +2725,7 @@ again:
*/
if (sc->sc_state == NCR_IDLE &&
sc->sc_espstep == 0)
- goto out;
+ return;
panic("ncr53c9x: no nexus");
}
@@ -2611,34 +2746,49 @@ again:
break;
case 1:
- if ((ti->flags & T_NEGOTIATE) == 0 &&
+ if (ti->curr.period == ti->goal.period &&
+ ti->curr.offset == ti->goal.offset &&
+ ti->curr.width == ti->goal.width &&
ecb->tag[0] == 0) {
- device_printf(sc->sc_dev, "step 1 & "
- "!NEG\n");
+ device_printf(sc->sc_dev, "step 1 "
+ "and no negotiation to perform "
+ "or tag to send\n");
goto reset;
}
if (sc->sc_phase != MESSAGE_OUT_PHASE) {
- device_printf(sc->sc_dev, "!MSGOUT\n");
+ device_printf(sc->sc_dev, "step 1 "
+ "but not in MESSAGE_OUT_PHASE\n");
goto reset;
}
- if (ti->flags & T_WIDE) {
- ti->flags |= T_WDTRSENT;
- ncr53c9x_sched_msgout(SEND_WDTR);
+ sc->sc_prevphase = MESSAGE_OUT_PHASE; /* XXX */
+ if (ecb->flags & ECB_RESET) {
+ /*
+ * A DEVICE RESET was scheduled and
+ * ATNS used. As SEND_DEV_RESET has
+ * the highest priority, the target
+ * will reset and disconnect and we
+ * will end up in ncr53c9x_done w/o
+ * negotiating or sending a TAG. So
+ * we just break here in order to
+ * avoid warnings about negotiation
+ * not having completed.
+ */
+ ncr53c9x_sched_msgout(SEND_DEV_RESET);
+ break;
}
- if (ti->flags & T_NEGOTIATE) {
- /* Start negotiating */
- sc->sc_flags |= NCR_SYNCHNEGO;
- if (ecb->tag[0])
- ncr53c9x_sched_msgout(
- SEND_TAG|SEND_SDTR);
- else
- ncr53c9x_sched_msgout(
- SEND_SDTR);
- } else {
+ if (ti->curr.width != ti->goal.width) {
+ ti->flags |= T_WDTRSENT | T_SDTRSENT;
+ ncr53c9x_sched_msgout(SEND_WDTR |
+ SEND_SDTR);
+ }
+ if (ti->curr.period != ti->goal.period ||
+ ti->curr.offset != ti->goal.offset) {
+ ti->flags |= T_SDTRSENT;
+ ncr53c9x_sched_msgout(SEND_SDTR);
+ }
+ if (ecb->tag[0] != 0)
/* Could not do ATN3 so send TAG. */
ncr53c9x_sched_msgout(SEND_TAG);
- }
- sc->sc_prevphase = MESSAGE_OUT_PHASE; /* XXXX */
break;
case 3:
@@ -2659,18 +2809,15 @@ again:
/* Hope for the best... */
break;
}
- printf("(%s:%d:%d): selection failed;"
- " %d left in FIFO "
+ xpt_print_path(ecb->ccb->ccb_h.path);
+ printf("selection failed; %d left in FIFO "
"[intr %x, stat %x, step %d]\n",
- device_get_nameunit(sc->sc_dev),
- ecb->ccb->ccb_h.target_id,
- ecb->ccb->ccb_h.target_lun,
NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF,
sc->sc_espintr, sc->sc_espstat,
sc->sc_espstep);
NCRCMD(sc, NCRCMD_FLUSH);
ncr53c9x_sched_msgout(SEND_ABORT);
- goto out;
+ return;
case 2:
/* Select stuck at Command Phase. */
@@ -2679,17 +2826,15 @@ again:
case 4:
if (sc->sc_features & NCR_F_DMASELECT &&
- sc->sc_cmdlen != 0)
- printf("(%s:%d:%d): select; "
- "%lu left in DMA buffer "
+ sc->sc_cmdlen != 0) {
+ xpt_print_path(ecb->ccb->ccb_h.path);
+ printf("select; %lu left in DMA buffer "
"[intr %x, stat %x, step %d]\n",
- device_get_nameunit(sc->sc_dev),
- ecb->ccb->ccb_h.target_id,
- ecb->ccb->ccb_h.target_lun,
(u_long)sc->sc_cmdlen,
sc->sc_espintr,
sc->sc_espstat,
sc->sc_espstep);
+ }
/* So far, everything went fine. */
break;
}
@@ -2710,7 +2855,7 @@ again:
}
if (sc->sc_state == NCR_IDLE) {
device_printf(sc->sc_dev, "stray interrupt\n");
- goto out;
+ return;
}
break;
@@ -2815,6 +2960,15 @@ msgin:
NCRCMD(sc, NCRCMD_FLUSH);
/* DELAY(1);*/
}
+ /*
+ * If we have more messages to send, e.g. WDTR or SDTR
+ * after we've sent a TAG, set ATN so we'll go back to
+ * MESSAGE_OUT_PHASE.
+ */
+ if (sc->sc_msgpriq) {
+ NCRCMD(sc, NCRCMD_SETATN);
+ sc->sc_flags |= NCR_ATN;
+ }
if (sc->sc_features & NCR_F_DMASELECT) {
/* Setup DMA transfer for command. */
size = ecb->clen;
@@ -2841,7 +2995,7 @@ msgin:
case DATA_OUT_PHASE:
NCR_PHASE(("DATA_OUT_PHASE [%ld] ", (long)sc->sc_dleft));
NCRCMD(sc, NCRCMD_FLUSH);
- size = min(sc->sc_dleft, sc->sc_maxxfer);
+ size = ulmin(sc->sc_dleft, sc->sc_maxxfer);
NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 0, &size);
sc->sc_prevphase = DATA_OUT_PHASE;
goto setup_xfer;
@@ -2850,7 +3004,7 @@ msgin:
NCR_PHASE(("DATA_IN_PHASE "));
if (sc->sc_rev == NCR_VARIANT_ESP100)
NCRCMD(sc, NCRCMD_FLUSH);
- size = min(sc->sc_dleft, sc->sc_maxxfer);
+ size = ulmin(sc->sc_dleft, sc->sc_maxxfer);
NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 1, &size);
sc->sc_prevphase = DATA_IN_PHASE;
setup_xfer:
@@ -2873,7 +3027,7 @@ msgin:
NCRCMD(sc,
(size == 0 ? NCRCMD_TRPAD : NCRCMD_TRANS) | NCRCMD_DMA);
NCRDMA_GO(sc);
- goto out;
+ return;
case STATUS_PHASE:
NCR_PHASE(("STATUS_PHASE "));
@@ -2891,22 +3045,20 @@ msgin:
goto reset;
}
-out:
- mtx_unlock(&sc->sc_lock);
return;
reset:
ncr53c9x_init(sc, 1);
- goto out;
+ return;
finish:
ncr53c9x_done(sc, ecb);
- goto out;
+ return;
sched:
sc->sc_state = NCR_IDLE;
ncr53c9x_sched(sc);
- goto out;
+ return;
shortcut:
/*
@@ -2929,13 +3081,14 @@ shortcut:
goto again;
microtime(&cur);
} while (cur.tv_sec <= wait.tv_sec && cur.tv_usec <= wait.tv_usec);
- goto out;
}
static void
ncr53c9x_abort(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
{
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
/* 2 secs for the abort */
ecb->timeout = NCR_ABORT_TIMEOUT;
ecb->flags |= ECB_ABORT;
@@ -2949,10 +3102,10 @@ ncr53c9x_abort(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
ncr53c9x_sched_msgout(SEND_ABORT);
/*
- * Reschedule timeout.
+ * Reschedule callout.
*/
- ecb->ccb->ccb_h.timeout_ch =
- timeout(ncr53c9x_timeout, ecb, mstohz(ecb->timeout));
+ callout_reset(&ecb->ch, mstohz(ecb->timeout),
+ ncr53c9x_callout, ecb);
} else {
/*
* Just leave the command where it is.
@@ -2965,13 +3118,16 @@ ncr53c9x_abort(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
}
static void
-ncr53c9x_timeout(void *arg)
+ncr53c9x_callout(void *arg)
{
struct ncr53c9x_ecb *ecb = arg;
union ccb *ccb = ecb->ccb;
struct ncr53c9x_softc *sc = ecb->sc;
- struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[ccb->ccb_h.target_id];
+ struct ncr53c9x_tinfo *ti;
+
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+ ti = &sc->sc_tinfo[ccb->ccb_h.target_id];
xpt_print_path(ccb->ccb_h.path);
device_printf(sc->sc_dev, "timed out [ecb %p (flags 0x%x, dleft %x, "
"stat %x)], <state %d, nexus %p, phase(l %x, c %x, p %x), "
@@ -2986,8 +3142,6 @@ ncr53c9x_timeout(void *arg)
printf("TRACE: %s.", ecb->trace);
#endif
- mtx_lock(&sc->sc_lock);
-
if (ecb->flags & ECB_ABORT) {
/* Abort timed out. */
printf(" AGAIN\n");
@@ -3000,17 +3154,14 @@ ncr53c9x_timeout(void *arg)
/* Disable sync mode if stuck in a data phase. */
if (ecb == sc->sc_nexus &&
- (ti->flags & T_SYNCMODE) != 0 &&
- (sc->sc_phase & (MSGI|CDI)) == 0) {
+ ti->curr.offset != 0 &&
+ (sc->sc_phase & (MSGI | CDI)) == 0) {
/* XXX ASYNC CALLBACK! */
+ ti->goal.offset = 0;
xpt_print_path(ccb->ccb_h.path);
printf("sync negotiation disabled\n");
- sc->sc_cfflags |=
- (1 << ((ccb->ccb_h.target_id & 7) + 8));
}
}
-
- mtx_unlock(&sc->sc_lock);
}
static void
@@ -3022,10 +3173,11 @@ ncr53c9x_watch(void *arg)
time_t old;
int t;
+ NCR_LOCK_ASSERT(sc, MA_OWNED);
+
/* Delete any structures that have not been used in 10min. */
old = time_second - (10 * 60);
- mtx_lock(&sc->sc_lock);
for (t = 0; t < sc->sc_ntarg; t++) {
ti = &sc->sc_tinfo[t];
li = LIST_FIRST(&ti->luns);
@@ -3044,6 +3196,5 @@ ncr53c9x_watch(void *arg)
li = LIST_NEXT(li, link);
}
}
- mtx_unlock(&sc->sc_lock);
callout_reset(&sc->sc_watchdog, 60 * hz, ncr53c9x_watch, sc);
}
diff --git a/sys/dev/esp/ncr53c9xreg.h b/sys/dev/esp/ncr53c9xreg.h
index c24f807..008692f 100644
--- a/sys/dev/esp/ncr53c9xreg.h
+++ b/sys/dev/esp/ncr53c9xreg.h
@@ -84,8 +84,8 @@
#define NCRSTAT_PHASE 0x07 /* Phase bits */
#define NCR_SELID 0x04 /* WO - Select/Reselect Bus ID */
-#define NCR_BUSID_HME 0x10 /* XXX HME reselect ID */
-#define NCR_BUSID_HME32 0x40 /* XXX HME to select more than 16 */
+#define NCR_BUSID_HMEXC32 0x40 /* HME xfer counter is 32bit */
+#define NCR_BUSID_HMEENCID 0x10 /* HME encode reselection ID */
#define NCR_INTR 0x05 /* RO - Interrupt */
#define NCRINTR_SBR 0x80 /* SCSI Bus Reset */
diff --git a/sys/dev/esp/ncr53c9xvar.h b/sys/dev/esp/ncr53c9xvar.h
index 1c81d92..7607e56 100644
--- a/sys/dev/esp/ncr53c9xvar.h
+++ b/sys/dev/esp/ncr53c9xvar.h
@@ -110,9 +110,9 @@
* ECB. Holds additional information for each SCSI command Comments: We
* need a separate scsi command block because we may need to overwrite it
* with a request sense command. Basicly, we refrain from fiddling with
- * the scsipi_xfer struct (except do the expected updating of return values).
- * We'll generally update: xs->{flags,resid,error,sense,status} and
- * occasionally xs->retries.
+ * the ccb union (except do the expected updating of return values).
+ * We'll generally update: ccb->ccb_h.status and ccb->csio.{resid,
+ * scsi_status,sense_data}.
*/
struct ncr53c9x_ecb {
/* These fields are preserved between alloc and free */
@@ -130,6 +130,7 @@ struct ncr53c9x_ecb {
#define ECB_RESET 0x80
#define ECB_TENTATIVE_DONE 0x100
int timeout;
+ struct callout ch;
struct {
u_char msg[3]; /* Selection Id msg and tags */
@@ -180,6 +181,12 @@ struct ncr53c9x_linfo {
struct ncr53c9x_ecb *queued[NCR_TAG_DEPTH];
};
+struct ncr53c9x_xinfo {
+ u_char period;
+ u_char offset;
+ u_char width;
+};
+
struct ncr53c9x_tinfo {
int cmds; /* # of commands processed */
int dconns; /* # of disconnects */
@@ -187,18 +194,13 @@ struct ncr53c9x_tinfo {
int perrs; /* # of parity errors */
int senses; /* # of request sense commands sent */
u_char flags;
-#define T_NEGOTIATE 0x02 /* (Re)Negotiate synchronous options */
-#define T_SYNCMODE 0x08 /* SYNC mode has been negotiated */
-#define T_SYNCHOFF 0x10 /* SYNC mode for is permanently off */
-#define T_RSELECTOFF 0x20 /* RE-SELECT mode is off */
-#define T_TAG 0x40 /* Turn on TAG QUEUEs */
-#define T_WIDE 0x80 /* Negotiate wide options */
-#define T_WDTRSENT 0x04 /* WDTR message has been sent to */
- u_char period; /* Period suggestion */
- u_char offset; /* Offset suggestion */
- u_char cfg3; /* per target config 3 */
- u_char nextag; /* Next available tag */
- u_char width; /* width suggesion */
+#define T_SYNCHOFF 0x01 /* SYNC mode is permanently off */
+#define T_RSELECTOFF 0x02 /* RE-SELECT mode is off */
+#define T_TAG 0x04 /* Turn on TAG QUEUEs */
+#define T_SDTRSENT 0x08 /* SDTR message has been sent to */
+#define T_WDTRSENT 0x10 /* WDTR message has been sent to */
+ struct ncr53c9x_xinfo curr;
+ struct ncr53c9x_xinfo goal;
LIST_HEAD(lun_list, ncr53c9x_linfo) luns;
struct ncr53c9x_linfo *lun[NCR_NLUN]; /* For speedy lookups */
};
@@ -352,7 +354,6 @@ struct ncr53c9x_softc {
int sc_features; /* Chip features */
int sc_minsync; /* Minimum sync period / 4 */
int sc_maxxfer; /* Maximum transfer size */
- int sc_maxsync; /* Maximum sync period */
int sc_maxoffset; /* Maximum offset */
int sc_maxwidth; /* Maximum width */
int sc_extended_geom; /* Should we return extended geometry */
@@ -377,12 +378,10 @@ struct ncr53c9x_softc {
/* values for sc_flags */
#define NCR_DROP_MSGI 0x01 /* Discard all msgs (parity err detected) */
#define NCR_ABORTING 0x02 /* Bailing out */
-#define NCR_DOINGDMA 0x04 /* The FIFO data path is active! */
-#define NCR_SYNCHNEGO 0x08 /* Synch negotiation in progress. */
-#define NCR_ICCS 0x10 /* Expect status phase results */
-#define NCR_WAITI 0x20 /* Waiting for non-DMA data to arrive */
-#define NCR_ATN 0x40 /* ATN asserted */
-#define NCR_EXPECT_ILLCMD 0x80 /* Expect Illegal Command Interrupt */
+#define NCR_ICCS 0x04 /* Expect status phase results */
+#define NCR_WAITI 0x08 /* Waiting for non-DMA data to arrive */
+#define NCR_ATN 0x10 /* ATN asserted */
+#define NCR_EXPECT_ILLCMD 0x20 /* Expect Illegal Command Interrupt */
/* values for sc_features */
#define NCR_F_HASCFG3 0x01 /* chip has CFG3 register */
@@ -397,9 +396,9 @@ struct ncr53c9x_softc {
#define SEND_REJECT 0x0008
#define SEND_IDENTIFY 0x0010
#define SEND_ABORT 0x0020
-#define SEND_WDTR 0x0040
-#define SEND_SDTR 0x0080
-#define SEND_TAG 0x0100
+#define SEND_TAG 0x0040
+#define SEND_WDTR 0x0080
+#define SEND_SDTR 0x0100
/* SCSI Status codes */
#define ST_MASK 0x3e /* bit 0,6,7 is reserved */
@@ -444,6 +443,17 @@ struct ncr53c9x_softc {
#endif
/*
+ * Macros for locking
+ */
+#define NCR_LOCK_INIT(_sc) \
+ mtx_init(&(_sc)->sc_lock, "ncr", "ncr53c9x lock", MTX_DEF);
+#define NCR_LOCK_INITIALIZED(_sc) mtx_initialized(&(_sc)->sc_lock)
+#define NCR_LOCK(_sc) mtx_lock(&(_sc)->sc_lock)
+#define NCR_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_lock)
+#define NCR_LOCK_ASSERT(_sc, _what) mtx_assert(&(_sc)->sc_lock, (_what))
+#define NCR_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_lock)
+
+/*
* DMA macros for NCR53c9x
*/
#define NCRDMA_ISINTR(sc) (*(sc)->sc_glue->gl_dma_isintr)((sc))
@@ -452,6 +462,7 @@ struct ncr53c9x_softc {
#define NCRDMA_SETUP(sc, addr, len, datain, dmasize) \
(*(sc)->sc_glue->gl_dma_setup)((sc), (addr), (len), (datain), (dmasize))
#define NCRDMA_GO(sc) (*(sc)->sc_glue->gl_dma_go)((sc))
+#define NCRDMA_STOP(sc) (*(sc)->sc_glue->gl_dma_stop)((sc))
#define NCRDMA_ISACTIVE(sc) (*(sc)->sc_glue->gl_dma_isactive)((sc))
/*
@@ -463,9 +474,6 @@ struct ncr53c9x_softc {
int ncr53c9x_attach(struct ncr53c9x_softc *sc);
int ncr53c9x_detach(struct ncr53c9x_softc *sc);
-void ncr53c9x_action(struct cam_sim *sim, union ccb *ccb);
-void ncr53c9x_reset(struct ncr53c9x_softc *sc);
void ncr53c9x_intr(void *arg);
-void ncr53c9x_init(struct ncr53c9x_softc *sc, int doreset);
#endif /* _DEV_IC_NCR53C9XVAR_H_ */
diff --git a/sys/dev/le/if_le_ledma.c b/sys/dev/le/if_le_ledma.c
index affd5c8..b07e610 100644
--- a/sys/dev/le/if_le_ledma.c
+++ b/sys/dev/le/if_le_ledma.c
@@ -78,12 +78,8 @@ __FBSDID("$FreeBSD$");
struct le_dma_softc {
struct am7990_softc sc_am7990; /* glue to MI code */
- int sc_rrid;
struct resource *sc_rres;
- bus_space_tag_t sc_regt;
- bus_space_handle_t sc_regh;
- int sc_irid;
struct resource *sc_ires;
void *sc_ih;
@@ -115,6 +111,7 @@ static device_method_t le_dma_methods[] = {
DEFINE_CLASS_0(le, le_dma_driver, le_dma_methods, sizeof(struct le_dma_softc));
DRIVER_MODULE(le, dma, le_dma_driver, le_devclass, 0, 0);
+MODULE_DEPEND(le, dma, 1, 1, 1);
MODULE_DEPEND(le, ether, 1, 1, 1);
/*
@@ -142,10 +139,9 @@ le_dma_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
{
struct le_dma_softc *lesc = (struct le_dma_softc *)sc;
- bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port);
- bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2,
- BUS_SPACE_BARRIER_WRITE);
- bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP, val);
+ bus_write_2(lesc->sc_rres, LEREG1_RAP, port);
+ bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE);
+ bus_write_2(lesc->sc_rres, LEREG1_RDP, val);
}
static uint16_t
@@ -153,10 +149,9 @@ le_dma_rdcsr(struct lance_softc *sc, uint16_t port)
{
struct le_dma_softc *lesc = (struct le_dma_softc *)sc;
- bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port);
- bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2,
- BUS_SPACE_BARRIER_WRITE);
- return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP));
+ bus_write_2(lesc->sc_rres, LEREG1_RAP, port);
+ bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE);
+ return (bus_read_2(lesc->sc_rres, LEREG1_RDP));
}
static void
@@ -238,7 +233,7 @@ le_dma_hwreset(struct lance_softc *sc)
DMA_RESET(dma);
/* Write bits 24-31 of Lance address. */
- bus_space_write_4(dma->sc_regt, dma->sc_regh, L64854_REG_ENBAR,
+ bus_write_4(dma->sc_res, L64854_REG_ENBAR,
lesc->sc_laddr & 0xff000000);
DMA_ENINTR(dma);
@@ -319,7 +314,7 @@ le_dma_attach(device_t dev)
struct le_dma_softc *lesc;
struct lsi64854_softc *dma;
struct lance_softc *sc;
- int error;
+ int error, i;
lesc = device_get_softc(dev);
sc = &lesc->sc_am7990.lsc;
@@ -334,25 +329,30 @@ le_dma_attach(device_t dev)
lesc->sc_dma = dma;
lesc->sc_dma->sc_client = lesc;
- lesc->sc_rrid = 0;
+ i = 0;
lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &lesc->sc_rrid, RF_ACTIVE);
+ &i, RF_ACTIVE);
if (lesc->sc_rres == NULL) {
device_printf(dev, "cannot allocate registers\n");
error = ENXIO;
goto fail_mtx;
}
- lesc->sc_regt = rman_get_bustag(lesc->sc_rres);
- lesc->sc_regh = rman_get_bushandle(lesc->sc_rres);
- lesc->sc_irid = 0;
+ i = 0;
if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+ &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "cannot allocate interrupt\n");
error = ENXIO;
goto fail_rres;
}
+ /* Attach the DMA engine. */
+ error = lsi64854_attach(dma);
+ if (error != 0) {
+ device_printf(dev, "lsi64854_attach failed\n");
+ goto fail_ires;
+ }
+
sc->sc_memsize = LEDMA_MEMSIZE;
error = bus_dma_tag_create(
dma->sc_parent_dmat, /* parent */
@@ -369,7 +369,7 @@ le_dma_attach(device_t dev)
&lesc->sc_dmat);
if (error != 0) {
device_printf(dev, "cannot allocate buffer DMA tag\n");
- goto fail_ires;
+ goto fail_lsi;
}
error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
@@ -383,7 +383,7 @@ le_dma_attach(device_t dev)
error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
sc->sc_memsize, le_dma_dma_callback, lesc, 0);
if (error != 0 || lesc->sc_laddr == 0) {
- device_printf(dev, "cannot load DMA buffer map\n");
+ device_printf(dev, "cannot load DMA buffer map\n");
goto fail_dmem;
}
@@ -435,10 +435,14 @@ le_dma_attach(device_t dev)
bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
fail_dtag:
bus_dma_tag_destroy(lesc->sc_dmat);
+ fail_lsi:
+ lsi64854_detach(dma);
fail_ires:
- bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
+ bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires),
+ lesc->sc_ires);
fail_rres:
- bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres),
+ lesc->sc_rres);
fail_mtx:
LE_LOCK_DESTROY(sc);
return (error);
@@ -449,6 +453,7 @@ le_dma_detach(device_t dev)
{
struct le_dma_softc *lesc;
struct lance_softc *sc;
+ int error;
lesc = device_get_softc(dev);
sc = &lesc->sc_am7990.lsc;
@@ -458,8 +463,13 @@ le_dma_detach(device_t dev)
bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
bus_dma_tag_destroy(lesc->sc_dmat);
- bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
- bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres);
+ error = lsi64854_detach(lesc->sc_dma);
+ if (error != 0)
+ return (error);
+ bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires),
+ lesc->sc_ires);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres),
+ lesc->sc_rres);
LE_LOCK_DESTROY(sc);
return (0);
diff --git a/sys/sparc64/sbus/dma_sbus.c b/sys/sparc64/sbus/dma_sbus.c
index 924fa27..4623995 100644
--- a/sys/sparc64/sbus/dma_sbus.c
+++ b/sys/sparc64/sbus/dma_sbus.c
@@ -70,7 +70,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
-#include <sys/resource.h>
#include <sys/rman.h>
#include <dev/ofw/ofw_bus.h>
@@ -178,7 +177,7 @@ dma_attach(device_t dev)
char *cabletype;
uint32_t csr;
phandle_t child, node;
- int error, burst, children;
+ int error, i;
dsc = device_get_softc(dev);
lsc = &dsc->sc_lsi64854;
@@ -188,15 +187,13 @@ dma_attach(device_t dev)
dsc->sc_ign = sbus_get_ign(dev);
dsc->sc_slot = sbus_get_slot(dev);
- lsc->sc_rid = 0;
- lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &lsc->sc_rid,
+ i = 0;
+ lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
RF_ACTIVE);
if (lsc->sc_res == NULL) {
device_printf(dev, "cannot allocate resources\n");
return (ENXIO);
}
- lsc->sc_regt = rman_get_bustag(lsc->sc_res);
- lsc->sc_regh = rman_get_bushandle(lsc->sc_res);
if (strcmp(name, "espdma") == 0 || strcmp(name, "dma") == 0)
lsc->sc_channel = L64854_CHANNEL_SCSI;
@@ -246,23 +243,17 @@ dma_attach(device_t dev)
goto fail_lres;
}
- burst = sbus_get_burstsz(dev);
- lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
- (burst & SBUS_BURST_16) ? 16 : 0;
+ i = sbus_get_burstsz(dev);
+ lsc->sc_burst = (i & SBUS_BURST_32) ? 32 :
+ (i & SBUS_BURST_16) ? 16 : 0;
lsc->sc_dev = dev;
- error = lsi64854_attach(lsc);
- if (error != 0) {
- device_printf(dev, "lsi64854_attach failed\n");
- goto fail_lpdma;
- }
-
/* Attach children. */
- children = 0;
+ i = 0;
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
if ((ddi = dma_setup_dinfo(dev, dsc, child)) == NULL)
continue;
- if (children != 0) {
+ if (i != 0) {
device_printf(dev,
"<%s>: only one child per DMA channel supported\n",
ddi->ddi_obdinfo.obd_name);
@@ -276,14 +267,13 @@ dma_attach(device_t dev)
continue;
}
device_set_ivars(cdev, ddi);
- children++;
+ i++;
}
return (bus_generic_attach(dev));
- fail_lpdma:
- bus_dma_tag_destroy(lsc->sc_parent_dmat);
fail_lres:
- bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
+ lsc->sc_res);
return (error);
}
diff --git a/sys/sparc64/sbus/lsi64854.c b/sys/sparc64/sbus/lsi64854.c
index 7ee3bc1..94f28ba 100644
--- a/sys/sparc64/sbus/lsi64854.c
+++ b/sys/sparc64/sbus/lsi64854.c
@@ -70,9 +70,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
-#include <sys/resource.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/rman.h>
#include <machine/bus.h>
@@ -112,7 +112,7 @@ static int lsi64854_pp_intr(void *);
/*
* Finish attaching this DMA device.
* Front-end must fill in these fields:
- * sc_regs
+ * sc_res
* sc_burst
* sc_channel (one of SCSI, ENET, PP)
* sc_client (one of SCSI, ENET, PP `soft_c' pointers)
@@ -120,12 +120,24 @@ static int lsi64854_pp_intr(void *);
int
lsi64854_attach(struct lsi64854_softc *sc)
{
+ bus_dma_lock_t *lockfunc;
+ struct ncr53c9x_softc *nsc;
+ void *lockfuncarg;
uint32_t csr;
int error;
- /* Indirect functions */
+ lockfunc = NULL;
+ lockfuncarg = NULL;
+
switch (sc->sc_channel) {
case L64854_CHANNEL_SCSI:
+ nsc = sc->sc_client;
+ if (NCR_LOCK_INITIALIZED(nsc) == 0) {
+ device_printf(sc->sc_dev, "mutex not initialized\n");
+ return (ENXIO);
+ }
+ lockfunc = busdma_lock_mutex;
+ lockfuncarg = &nsc->sc_lock;
sc->intr = lsi64854_scsi_intr;
sc->setup = lsi64854_setup;
break;
@@ -141,29 +153,32 @@ lsi64854_attach(struct lsi64854_softc *sc)
}
sc->reset = lsi64854_reset;
- /* Allocate a dmamap */
- error = bus_dma_tag_create(
- sc->sc_parent_dmat, /* parent */
- 1, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MAX_DMA_SZ, /* maxsize */
- 1, /* nsegments */
- MAX_DMA_SZ, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->sc_buffer_dmat);
- if (error != 0) {
- device_printf(sc->sc_dev, "cannot allocate buffer DMA tag\n");
- return (error);
- }
-
- error = bus_dmamap_create(sc->sc_buffer_dmat, 0, &sc->sc_dmamap);
- if (error != 0) {
- device_printf(sc->sc_dev, "DMA map create failed\n");
- bus_dma_tag_destroy(sc->sc_buffer_dmat);
- return (error);
+ if (sc->setup != NULL) {
+ error = bus_dma_tag_create(
+ sc->sc_parent_dmat, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MAX_DMA_SZ, /* maxsize */
+ 1, /* nsegments */
+ MAX_DMA_SZ, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ lockfunc, lockfuncarg, /* lockfunc, lockfuncarg */
+ &sc->sc_buffer_dmat);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "cannot allocate buffer DMA tag\n");
+ return (error);
+ }
+
+ error = bus_dmamap_create(sc->sc_buffer_dmat, 0,
+ &sc->sc_dmamap);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "DMA map create failed\n");
+ bus_dma_tag_destroy(sc->sc_buffer_dmat);
+ return (error);
+ }
}
csr = L64854_GCSR(sc);
@@ -201,16 +216,20 @@ int
lsi64854_detach(struct lsi64854_softc *sc)
{
- if (sc->setup)
+ if (sc->setup != NULL) {
+ bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
+ (L64854_GCSR(sc) & L64854_WRITE) != 0 ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
- bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap);
- bus_dma_tag_destroy(sc->sc_buffer_dmat);
+ bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap);
+ bus_dma_tag_destroy(sc->sc_buffer_dmat);
+ }
return (0);
}
/*
- * DMAWAIT waits while condition is true
+ * DMAWAIT waits while condition is true.
*/
#define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \
int count = 500000; \
@@ -279,11 +298,12 @@ lsi64854_reset(struct lsi64854_softc *sc)
DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr));
- /*
- * XXX is sync needed?
- if (sc->sc_dmamap->dm_nsegs > 0)
+ if (sc->sc_dmasize != 0) {
+ bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
+ (csr & D_WRITE) != 0 ? BUS_DMASYNC_PREREAD :
+ BUS_DMASYNC_PREWRITE);
bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
- */
+ }
if (sc->sc_rev == DMAREV_HME)
L64854_SCSR(sc, csr | D_HW_RESET_FAS366);
@@ -332,7 +352,7 @@ lsi64854_reset(struct lsi64854_softc *sc)
L64854_SCSR(sc, csr);
if (sc->sc_rev == DMAREV_HME) {
- bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR, 0);
+ bus_write_4(sc->sc_res, L64854_REG_ADDR, 0);
sc->sc_dmactl = csr;
}
sc->sc_active = 0;
@@ -352,11 +372,10 @@ lsi64854_map_scsi(void *arg, bus_dma_segment_t *segs, int nseg, int error)
bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
sc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
- bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR,
- segs[0].ds_addr);
+ bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
}
-#define DMAMAX(a) (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ-1)))
+#define DMAMAX(a) (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ - 1)))
/*
* setup a DMA transfer
*/
@@ -382,7 +401,7 @@ lsi64854_setup(struct lsi64854_softc *sc, caddr_t *addr, size_t *len,
* and we cannot cross a 16Mb boundary.
*/
*dmasize = sc->sc_dmasize =
- ulmin(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
+ ulmin(*dmasize, DMAMAX((size_t)*sc->sc_dmaaddr));
DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
@@ -393,12 +412,11 @@ lsi64854_setup(struct lsi64854_softc *sc, caddr_t *addr, size_t *len,
L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET);
L64854_SCSR(sc, sc->sc_dmactl);
- bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_CNT,
- *dmasize);
+ bus_write_4(sc->sc_res, L64854_REG_CNT, *dmasize);
}
/* Program the DMA address */
- if (sc->sc_dmasize)
+ if (sc->sc_dmasize != 0)
if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
*sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_scsi, sc, 0))
panic("%s: cannot allocate DVMA address", __func__);
@@ -408,8 +426,7 @@ lsi64854_setup(struct lsi64854_softc *sc, caddr_t *addr, size_t *len,
bcnt = sc->sc_dmasize;
if (((bcnt + (long)*sc->sc_dmaaddr) & PAGE_MASK_8K) != 0)
bcnt = roundup(bcnt, PAGE_SIZE_8K);
- bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_CNT,
- bcnt);
+ bus_write_4(sc->sc_res, L64854_REG_CNT, bcnt);
}
/* Setup DMA control register */
@@ -447,8 +464,7 @@ lsi64854_scsi_intr(void *arg)
csr = L64854_GCSR(sc);
DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__,
- bus_space_read_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR), csr,
- DDMACSR_BITS));
+ bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, DDMACSR_BITS));
if (csr & (D_ERR_PEND|D_SLAVE_ERR)) {
device_printf(sc->sc_dev, "error: csr=%b\n", csr, DDMACSR_BITS);
@@ -530,14 +546,12 @@ lsi64854_scsi_intr(void *arg)
(nsc->sc_cfg2 & NCRCFG2_FE) ? NCR_READ_REG(nsc, NCR_TCH) : 0,
trans, resid));
-#if 0 /* XXX */
- if (sc->sc_dmamap->dm_nsegs > 0) {
+ if (sc->sc_dmasize != 0) {
bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
(csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD :
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
}
-#endif
*sc->sc_dmalen -= trans;
*sc->sc_dmaaddr += trans;
@@ -604,11 +618,9 @@ lsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, sc->sc_datain ?
BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
- bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR,
- segs[0].ds_addr);
+ bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
- bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_CNT,
- sc->sc_dmasize);
+ bus_write_4(sc->sc_res, L64854_REG_CNT, sc->sc_dmasize);
}
/*
@@ -635,12 +647,12 @@ lsi64854_setup_pp(struct lsi64854_softc *sc, caddr_t *addr, size_t *len,
* and we cannot cross a 16Mb boundary.
*/
*dmasize = sc->sc_dmasize =
- ulmin(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
+ ulmin(*dmasize, DMAMAX((size_t)*sc->sc_dmaaddr));
DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
/* Program the DMA address */
- if (sc->sc_dmasize)
+ if (sc->sc_dmasize != 0)
if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
*sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_pp, sc, 0))
panic("%s: pp cannot allocate DVMA address", __func__);
@@ -680,12 +692,10 @@ lsi64854_pp_intr(void *arg)
csr = L64854_GCSR(sc);
DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__,
- bus_space_read_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR), csr,
- PDMACSR_BITS));
+ bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, PDMACSR_BITS));
if (csr & (P_ERR_PEND|P_SLAVE_ERR)) {
- resid = bus_space_read_4(sc->sc_regt, sc->sc_regh,
- L64854_REG_CNT);
+ resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
device_printf(sc->sc_dev, "error: resid %d csr=%b\n", resid,
csr, PDMACSR_BITS);
csr &= ~P_EN_DMA; /* Stop DMA */
@@ -699,8 +709,7 @@ lsi64854_pp_intr(void *arg)
if (sc->sc_active != 0) {
DMA_DRAIN(sc, 0);
- resid = bus_space_read_4(sc->sc_regt, sc->sc_regh,
- L64854_REG_CNT);
+ resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
}
/* DMA has stopped */
@@ -714,14 +723,12 @@ lsi64854_pp_intr(void *arg)
*sc->sc_dmalen -= trans;
*sc->sc_dmaaddr += trans;
-#if 0 /* XXX */
- if (sc->sc_dmamap->dm_nsegs > 0) {
+ if (sc->sc_dmasize != 0) {
bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
(csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD :
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
}
-#endif
return (ret != 0);
}
diff --git a/sys/sparc64/sbus/lsi64854var.h b/sys/sparc64/sbus/lsi64854var.h
index 9cdd0e3..f0147e0 100644
--- a/sys/sparc64/sbus/lsi64854var.h
+++ b/sys/sparc64/sbus/lsi64854var.h
@@ -41,10 +41,7 @@
struct lsi64854_softc {
device_t sc_dev;
- int sc_rid;
struct resource *sc_res;
- bus_space_handle_t sc_regh;
- bus_space_tag_t sc_regt;
u_int sc_rev; /* revision */
int sc_burst; /* max suported burst size */
@@ -54,7 +51,7 @@ struct lsi64854_softc {
#define L64854_CHANNEL_PP 3
void *sc_client;
- int sc_active; /* DMA active ? */
+ int sc_active; /* DMA active? */
bus_dmamap_t sc_dmamap; /* DMA map for bus_dma_* */
bus_dma_tag_t sc_parent_dmat;
@@ -73,12 +70,8 @@ struct lsi64854_softc {
int sc_dodrain;
};
-#define L64854_GCSR(sc) \
- (bus_space_read_4((sc)->sc_regt, (sc)->sc_regh, L64854_REG_CSR))
-
-#define L64854_SCSR(sc, csr) \
- bus_space_write_4((sc)->sc_regt, (sc)->sc_regh, L64854_REG_CSR, csr)
-
+#define L64854_GCSR(sc) bus_read_4((sc)->sc_res, L64854_REG_CSR)
+#define L64854_SCSR(sc, csr) bus_write_4((sc)->sc_res, L64854_REG_CSR, csr)
/*
* DMA engine interface functions.
@@ -86,7 +79,6 @@ struct lsi64854_softc {
#define DMA_RESET(sc) (((sc)->reset)(sc))
#define DMA_INTR(sc) (((sc)->intr)(sc))
#define DMA_SETUP(sc, a, l, d, s) (((sc)->setup)(sc, a, l, d, s))
-
#define DMA_ISACTIVE(sc) ((sc)->sc_active)
#define DMA_ENINTR(sc) do { \
@@ -104,6 +96,5 @@ struct lsi64854_softc {
sc->sc_active = 1; \
} while (0)
-
int lsi64854_attach(struct lsi64854_softc *);
int lsi64854_detach(struct lsi64854_softc *);
OpenPOWER on IntegriCloud