summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2008-09-08 20:20:44 +0000
committermarius <marius@FreeBSD.org>2008-09-08 20:20:44 +0000
commit579a51f222627a676ded829197395af7b2a25f45 (patch)
treea53f69cd2327f0b79366b330bbd19da17347759b
parentf147e876b77207eff82e28394140c4b684077538 (diff)
downloadFreeBSD-src-579a51f222627a676ded829197395af7b2a25f45.zip
FreeBSD-src-579a51f222627a676ded829197395af7b2a25f45.tar.gz
o Move the MODULE_DEPEND() for cam(4) from the esp_sbus.c front-end to
the ncr53c9x.c core where it actually belongs so future front-ends don't need to add it. o Use the correct OFW property when looking for the initiator ID of the SBus device. o Don't specify an alignment when creating the parent DMA tag for SUNW,fas; their DMA engine doesn't require an alignment constraint and it's no inherited by the child DMA tags anyway (which probably is a bug though). o Drop the superfluous sc_maxsync and use sc_minsync instead. The former apparently was added due to a confusion with the maximum frequency used in cam(4), which basically corresponds to the inverse of minimum sync period. o Merge ncr53c9x.c from NetBSD: 1.116: NCRDMA_SETUP() should be called before NCR_SET_COUNT() and NCRCMD_DMA command in ncr53c9x_select(). 1.125: free allocated resources on detach. o Static'ize ncr53c9x_action(), ncr53c9x_init() and ncr53c9x_reset() as these are not required outside of ncr53c9x.c. o In ncr53c9x_attach() don't leak the device mutex in case attaching fails. o Register an asynchronous notification handler so in case cam(4) reports a lost device we can cancel outstanding commands and restore the default parameters for the target in question. o For FAS366 correctly support 16-bit target IDs and let it know that we use 32-bit transfers. o Overhaul the negotiation of transfer settings. This includes distinguishing between current and goal transfer settings of the target so we can renegotiate their goal settings when necessary and correcting the order in which tagged, wide and synchronous transfers are negotiated. o 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. o In case of an XPT_RESET_BUS just directly call ncr53c9x_init() instead of issuing a NCRCMD_RSTSCSI, which in turn will issue an interrupt that is treated as an unexpected SCSI bus reset by ncr53c9x_intr() and thus calls ncr53c9x_init(). Remove the now no longer used ncr53c9x_scsi_reset(). o Correct an off-by-one error when setting cpi->max_lun. o In replace printf(9) with device_printf(9) calls where appropriate and in ncr53c9x_action() remove some unnecessarily verbose messages. o In ncr53c9x_sched() use TAILQ_FOREACH() instead of reimplementing it and consolidate two tagging-related target info checks into one. o In ncr53c9x_done() set the CAM status to CAM_SCSI_STATUS_ERROR when appropriate, respect CAM_DIS_AUTOSENSE and teach it to return SCSI status information. o In ncr53c9x_dequeue() ensure the tags are cleared. o Use ulmin() instead of min() where appropriate. o In ncr53c9x_msgout() consistently use the reset label. o When we're interrupted during a data phase and the DMA engine is still active, don't panic but reset the core and the DMA engine as this should be sufficient. Also, the typical problem for triggering this was the lack of renegotiation when requesting sense. o Correctly handle DEVICE RESETs. o Adapt the locking of esp(4) to MPSAFE cam(4). This includes moving the calls of lsi64854_attach() to the bus front-ends so it can pass the esp(4) mutex to bus_dma_tag_create(9). o Change the LSI64854 driver to not create a DMA tag and map for the Ethernet channel as le(4) will handle these on its own as well as sync and unload the DMA maps for the SCSI and parallel port channel after a DMA transfer. o Cam(4)'ify some NetBSD-centric comments. o Use bus_{read,write}_*(9) instead of bus_space_{read,write}_*(9) and take advantage of rman_get_rid(9) in order to save some softc members. Reviewed by: scottl MFC after: 1 month
-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