svn commit: r227302 - in stable/9/sys: dev/esp sparc64/sbus
Marius Strobl
marius at FreeBSD.org
Mon Nov 7 13:16:51 UTC 2011
Author: marius
Date: Mon Nov 7 13:16:51 2011
New Revision: 227302
URL: http://svn.freebsd.org/changeset/base/227302
Log:
MFC: r226947, r226949, r227284
- Use device_t rather than the NetBSDish struct device.
- Move esp_devclass to ncr53c9x.c in order to allow different bus front-ends
to use it.
- Use KOBJMETHOD_END.
- Remove the gl_clear_latched_intr hook as it's not needed for any of the
chips nor the front-ends supported in FreeBSD and likely never will be.
- Correct the DMA constraints and only limit the tag used for the transfer
buffers to 32-bit DMA as that address is written into a 32-bit register.
- The ESP200 also only supports up to 64k transfers.
- Don't let the DMA and SBus front-end supply a maximum transfer size larger
than MAXPHYS as that's the maximum the upper layers use and we otherwise
just waste resources unnecessarily.
- Initialize the ECB callout and don't zero the handle when returning ECBs
to the free list so that ncr53c9x_callout() actually is called with the
driver lock held.
- On detach the driver lock should be held across cam_sim_free() according
to isp(4) and a panic received.
- Check the return value of NCRDMA_SETUP(), i.e. bus_dmamap_load(9), and try
to handle failures gracefully.
- In ncr53c9x_action() replace N calls to xpt_done() in a switch with just
one at the end.
- On XPT_PATH_INQ report "NCR" rather than "Sun" as the vendor as the former
is somewhat more correct as well as the maximum supported transfer size via
maxio in order to take advantage of controllers that that can handle more
than DFLTPHYS.
- Freeze the device queue if a request didn't complete without error and
isn't already frozen.
- Print the number of MESSAGE (EXTENDED) rejected.
- Fix the path encoded in the multiple inclusion protection of ncr53c9xvar.h.
- Correct the DMA constraints used in the LSI64854 core to not exceed the
maximum supported transfer size and include the boundary so we don't need
to check on every setup of a DMA transfer.
- Let the bus DMA map callbacks do nothing in case of an error.
- Correctly handle > 64k transfers for FAS366 in the LSI64854. A new feature
flag NCR_F_LARGEXFER was introduced so we just need to check for this one
and not for individual controllers supporting large transfers in several
places.
- Let the LSI64854 core load transfer buffers using BUS_DMA_NOWAIT as the
NCR53C9x core can't handle EINPROGRESS. Due to lack of bounce buffers
support, sparc64 doesn't actually use EINPROGRESS and likely never will,
as an example for writing additional front-ends for the NCR53C9x core it
makes sense to set BUS_DMA_NOWAIT anyway though.
- Some minor cleanup.
Approved by: re (kib)
Modified:
stable/9/sys/dev/esp/esp_sbus.c
stable/9/sys/dev/esp/ncr53c9x.c
stable/9/sys/dev/esp/ncr53c9xvar.h
stable/9/sys/sparc64/sbus/lsi64854.c
stable/9/sys/sparc64/sbus/lsi64854var.h
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/amd64/include/xen/ (props changed)
stable/9/sys/boot/ (props changed)
stable/9/sys/boot/i386/efi/ (props changed)
stable/9/sys/boot/ia64/efi/ (props changed)
stable/9/sys/boot/ia64/ski/ (props changed)
stable/9/sys/boot/powerpc/boot1.chrp/ (props changed)
stable/9/sys/boot/powerpc/ofw/ (props changed)
stable/9/sys/cddl/contrib/opensolaris/ (props changed)
stable/9/sys/conf/ (props changed)
stable/9/sys/contrib/dev/acpica/ (props changed)
stable/9/sys/contrib/octeon-sdk/ (props changed)
stable/9/sys/contrib/pf/ (props changed)
stable/9/sys/contrib/x86emu/ (props changed)
Modified: stable/9/sys/dev/esp/esp_sbus.c
==============================================================================
--- stable/9/sys/dev/esp/esp_sbus.c Mon Nov 7 11:31:37 2011 (r227301)
+++ stable/9/sys/dev/esp/esp_sbus.c Mon Nov 7 13:16:51 2011 (r227302)
@@ -68,13 +68,13 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/rman.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
#include <machine/ofw_machdep.h>
#include <machine/resource.h>
-#include <sys/rman.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -92,7 +92,7 @@ __FBSDID("$FreeBSD$");
struct esp_softc {
struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
- struct device *sc_dev;
+ device_t sc_dev;
struct resource *sc_res;
@@ -102,8 +102,6 @@ struct esp_softc {
struct lsi64854_softc *sc_dma; /* pointer to my DMA */
};
-static devclass_t esp_devclass;
-
static int esp_probe(device_t);
static int esp_dma_attach(device_t);
static int esp_dma_detach(device_t);
@@ -118,7 +116,8 @@ static device_method_t esp_dma_methods[]
DEVMETHOD(device_detach, esp_dma_detach),
DEVMETHOD(device_suspend, esp_suspend),
DEVMETHOD(device_resume, esp_resume),
- {0, 0}
+
+ KOBJMETHOD_END
};
static driver_t esp_dma_driver = {
@@ -136,7 +135,8 @@ static device_method_t esp_sbus_methods[
DEVMETHOD(device_detach, esp_sbus_detach),
DEVMETHOD(device_suspend, esp_suspend),
DEVMETHOD(device_resume, esp_resume),
- {0, 0}
+
+ KOBJMETHOD_END
};
static driver_t esp_sbus_driver = {
@@ -175,7 +175,6 @@ static const struct ncr53c9x_glue const
esp_dma_go,
esp_dma_stop,
esp_dma_isactive,
- NULL, /* gl_clear_latched_intr */
};
static int
@@ -245,9 +244,9 @@ esp_sbus_attach(device_t dev)
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
- 0, /* nsegments */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ BUS_SPACE_MAXSIZE, /* maxsize */
+ BUS_SPACE_UNRESTRICTED, /* nsegments */
+ BUS_SPACE_MAXSIZE, /* maxsegsize */
0, /* flags */
NULL, NULL, /* no locking */
&lsc->sc_parent_dmat);
@@ -292,8 +291,10 @@ esp_sbus_attach(device_t dev)
}
for (i = 0; i < nchildren; i++) {
if (device_is_attached(children[i]) &&
- sbus_get_slot(children[i]) == sbus_get_slot(dev) &&
- strcmp(ofw_bus_get_name(children[i]), "dma") == 0) {
+ 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 *)
device_get_softc(children[i]);
@@ -453,13 +454,6 @@ espattach(struct esp_softc *esc, const s
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;
- }
-
sc->sc_id = OF_getscsinitid(esc->sc_dev);
#ifdef ESP_SBUS_DEBUG
@@ -516,9 +510,9 @@ espattach(struct esp_softc *esc, const s
NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
- (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
+ (NCRCFG2_SCSI2 | NCRCFG2_RPE))
sc->sc_rev = NCR_VARIANT_ESP100;
- } else {
+ else {
sc->sc_cfg2 = NCRCFG2_SCSI2;
NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
sc->sc_cfg3 = 0;
@@ -526,9 +520,9 @@ espattach(struct esp_softc *esc, const s
sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
if (NCR_READ_REG(sc, NCR_CFG3) !=
- (NCRCFG3_CDB | NCRCFG3_FCLK)) {
+ (NCRCFG3_CDB | NCRCFG3_FCLK))
sc->sc_rev = NCR_VARIANT_ESP100A;
- } else {
+ else {
/* NCRCFG2_FE enables > 64K transfers. */
sc->sc_cfg2 |= NCRCFG2_FE;
sc->sc_cfg3 = 0;
@@ -543,9 +537,11 @@ espattach(struct esp_softc *esc, const s
case 0x02:
if ((uid & 0x07) == 0x02)
- sc->sc_rev = NCR_VARIANT_FAS216;
+ sc->sc_rev =
+ NCR_VARIANT_FAS216;
else
- sc->sc_rev = NCR_VARIANT_FAS236;
+ sc->sc_rev =
+ NCR_VARIANT_FAS236;
break;
case 0x0a:
@@ -560,7 +556,8 @@ espattach(struct esp_softc *esc, const s
*/
device_printf(esc->sc_dev,
"Unknown chip\n");
- goto fail_lsi;
+ error = ENXIO;
+ goto fail_lock;
}
}
}
@@ -571,12 +568,6 @@ espattach(struct esp_softc *esc, const s
#endif
/*
- * XXX minsync and maxxfer _should_ be set up in MI code,
- * XXX but it appears to have some dependency on what sort
- * XXX of DMA we're hooked up to, etc.
- */
-
- /*
* This is the value used to start sync negotiations
* Note that the NCR register "SYNCTP" is programmed
* in "clocks per byte", and has a minimum value of 4.
@@ -587,31 +578,27 @@ espattach(struct esp_softc *esc, const s
*/
sc->sc_minsync = 1000 / sc->sc_freq;
+ /*
+ * Except for some variants the maximum transfer size is 64k.
+ */
+ sc->sc_maxxfer = 64 * 1024;
sc->sc_maxoffset = 15;
sc->sc_extended_geom = 1;
/*
* Alas, we must now modify the value a bit, because it's
- * only valid when can switch on FASTCLK and FASTSCSI bits
- * in config register 3...
+ * only valid when we can switch on FASTCLK and FASTSCSI bits
+ * in the config register 3...
*/
switch (sc->sc_rev) {
case NCR_VARIANT_ESP100:
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 = 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 = MSG_EXT_WDTR_BUS_8_BIT;
- sc->sc_maxxfer = 16 * 1024 * 1024;
/* Min clocks/byte is 5 */
sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
break;
@@ -642,6 +629,19 @@ espattach(struct esp_softc *esc, const s
break;
}
+ /*
+ * Given that we allocate resources based on sc->sc_maxxfer it doesn't
+ * make sense to supply a value higher than the maximum actually used.
+ */
+ sc->sc_maxxfer = min(sc->sc_maxxfer, MAXPHYS);
+
+ /* 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;
+ }
+
/* Establish interrupt channel. */
i = 0;
if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ,
Modified: stable/9/sys/dev/esp/ncr53c9x.c
==============================================================================
--- stable/9/sys/dev/esp/ncr53c9x.c Mon Nov 7 11:31:37 2011 (r227301)
+++ stable/9/sys/dev/esp/ncr53c9x.c Mon Nov 7 13:16:51 2011 (r227302)
@@ -123,6 +123,8 @@ __FBSDID("$FreeBSD$");
#include <dev/esp/ncr53c9xreg.h>
#include <dev/esp/ncr53c9xvar.h>
+devclass_t esp_devclass;
+
MODULE_DEPEND(esp, cam, 1, 1, 1);
#ifdef NCR53C9X_DEBUG
@@ -179,8 +181,7 @@ static inline int ncr53c9x_stp2cpb(struc
#define NCR_SET_COUNT(sc, size) do { \
NCR_WRITE_REG((sc), NCR_TCL, (size)); \
NCR_WRITE_REG((sc), NCR_TCM, (size) >> 8); \
- if ((sc->sc_cfg2 & NCRCFG2_FE) || \
- (sc->sc_rev == NCR_VARIANT_FAS366)) \
+ if ((sc->sc_features & NCR_F_LARGEXFER) != 0) \
NCR_WRITE_REG((sc), NCR_TCH, (size) >> 16); \
if (sc->sc_rev == NCR_VARIANT_FAS366) \
NCR_WRITE_REG(sc, NCR_RCH, 0); \
@@ -391,6 +392,7 @@ ncr53c9x_attach(struct ncr53c9x_softc *s
ecb = &sc->ecb_array[i];
ecb->sc = sc;
ecb->tag_id = i;
+ callout_init_mtx(&ecb->ch, &sc->sc_lock, 0);
TAILQ_INSERT_HEAD(&sc->free_list, ecb, free_links);
}
@@ -449,10 +451,10 @@ ncr53c9x_detach(struct ncr53c9x_softc *s
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));
+ cam_sim_free(sc->sc_sim, TRUE);
NCR_UNLOCK(sc);
- cam_sim_free(sc->sc_sim, TRUE);
free(sc->ecb_array, M_DEVBUF);
free(sc->sc_tinfo, M_DEVBUF);
if (sc->sc_imess_self)
@@ -504,6 +506,8 @@ ncr53c9x_reset(struct ncr53c9x_softc *sc
/* FALLTHROUGH */
case NCR_VARIANT_ESP100A:
sc->sc_features |= NCR_F_SELATN3;
+ if ((sc->sc_cfg2 & NCRCFG2_FE) != 0)
+ sc->sc_features |= NCR_F_LARGEXFER;
NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
/* FALLTHROUGH */
case NCR_VARIANT_ESP100:
@@ -514,8 +518,8 @@ ncr53c9x_reset(struct ncr53c9x_softc *sc
break;
case NCR_VARIANT_FAS366:
- sc->sc_features |=
- NCR_F_HASCFG3 | NCR_F_FASTSCSI | NCR_F_SELATN3;
+ sc->sc_features |= NCR_F_HASCFG3 | NCR_F_FASTSCSI |
+ NCR_F_SELATN3 | NCR_F_LARGEXFER;
sc->sc_cfg3 = NCRFASCFG3_FASTCLK | NCRFASCFG3_OBAUTO;
if (sc->sc_id > 7)
sc->sc_cfg3 |= NCRFASCFG3_IDBIT3;
@@ -711,9 +715,6 @@ ncr53c9x_readregs(struct ncr53c9x_softc
sc->sc_espintr = NCR_READ_REG(sc, NCR_INTR);
- if (sc->sc_glue->gl_clear_latched_intr != NULL)
- (*sc->sc_glue->gl_clear_latched_intr)(sc);
-
/*
* Determine the SCSI bus phase, return either a real SCSI bus phase
* or some pseudo phase we use to detect certain exceptions.
@@ -806,7 +807,7 @@ ncr53c9x_select(struct ncr53c9x_softc *s
struct ncr53c9x_tinfo *ti;
uint8_t *cmd;
size_t dmasize;
- int clen, selatn3, selatns;
+ int clen, error, selatn3, selatns;
int lun = ecb->ccb->ccb_h.target_lun;
int target = ecb->ccb->ccb_h.target_id;
@@ -887,13 +888,19 @@ ncr53c9x_select(struct ncr53c9x_softc *s
dmasize = clen;
sc->sc_cmdlen = clen;
sc->sc_cmdp = cmd;
- NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmasize);
+ error = NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0,
+ &dmasize);
+ if (error != 0) {
+ sc->sc_cmdlen = 0;
+ sc->sc_cmdp = NULL;
+ goto cmd;
+ }
+
/* Program the SCSI counter. */
NCR_SET_COUNT(sc, dmasize);
/* Load the count in. */
- /* if (sc->sc_rev != NCR_VARIANT_FAS366) */
- NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
+ NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
/* And get the target's attention. */
if (selatn3) {
@@ -906,6 +913,7 @@ ncr53c9x_select(struct ncr53c9x_softc *s
return;
}
+cmd:
/*
* Who am I? This is where we tell the target that we are
* happy for it to disconnect etc.
@@ -989,13 +997,11 @@ ncr53c9x_action(struct cam_sim *sim, uni
case XPT_RESET_BUS:
ncr53c9x_init(sc, 1);
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- return;
+ break;
case XPT_CALC_GEOMETRY:
cam_calc_geometry(&ccb->ccg, sc->sc_extended_geom);
- xpt_done(ccb);
- return;
+ break;
case XPT_PATH_INQ:
cpi = &ccb->cpi;
@@ -1009,19 +1015,19 @@ ncr53c9x_action(struct cam_sim *sim, uni
cpi->max_target = sc->sc_ntarg - 1;
cpi->max_lun = 7;
cpi->initiator_id = sc->sc_id;
- cpi->bus_id = 0;
- cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
- strncpy(cpi->hba_vid, "Sun", HBA_IDLEN);
+ strncpy(cpi->hba_vid, "NCR", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
cpi->unit_number = cam_sim_unit(sim);
- cpi->transport = XPORT_SPI;
- cpi->transport_version = 2;
+ cpi->bus_id = 0;
+ cpi->base_transfer_speed = 3300;
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_2;
+ cpi->transport = XPORT_SPI;
+ cpi->transport_version = 2;
+ cpi->maxio = sc->sc_maxxfer;
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- return;
+ break;
case XPT_GET_TRAN_SETTINGS:
cts = &ccb->cts;
@@ -1064,28 +1070,24 @@ ncr53c9x_action(struct cam_sim *sim, uni
CTS_SPI_VALID_DISC;
scsi->valid = CTS_SCSI_VALID_TQ;
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- return;
+ break;
case XPT_ABORT:
device_printf(sc->sc_dev, "XPT_ABORT called\n");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- xpt_done(ccb);
- return;
+ break;
case XPT_TERM_IO:
device_printf(sc->sc_dev, "XPT_TERM_IO called\n");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- xpt_done(ccb);
- return;
+ break;
case XPT_RESET_DEV:
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;
- xpt_done(ccb);
- return;
+ goto done;
}
/* Get an ECB to use. */
ecb = ncr53c9x_get_ecb(sc);
@@ -1097,8 +1099,7 @@ ncr53c9x_action(struct cam_sim *sim, uni
xpt_freeze_simq(sim, 1);
ccb->ccb_h.status = CAM_REQUEUE_REQ;
device_printf(sc->sc_dev, "unable to allocate ecb\n");
- xpt_done(ccb);
- return;
+ goto done;
}
/* Initialize ecb. */
@@ -1127,7 +1128,7 @@ ncr53c9x_action(struct cam_sim *sim, uni
ecb->flags |= ECB_READY;
if (sc->sc_state == NCR_IDLE)
ncr53c9x_sched(sc);
- break;
+ return;
case XPT_SET_TRAN_SETTINGS:
cts = &ccb->cts;
@@ -1165,16 +1166,16 @@ ncr53c9x_action(struct cam_sim *sim, uni
}
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- return;
+ break;
default:
device_printf(sc->sc_dev, "Unhandled function code %d\n",
ccb->ccb_h.func_code);
ccb->ccb_h.status = CAM_PROVIDE_FAIL;
- xpt_done(ccb);
- return;
}
+
+done:
+ xpt_done(ccb);
}
/*
@@ -1329,11 +1330,10 @@ ncr53c9x_sched(struct ncr53c9x_softc *sc
sc->sc_nexus = ecb;
ncr53c9x_select(sc, ecb);
break;
- } else {
+ } else
NCR_TRACE(("[%s %d:%d busy] \n", __func__,
ecb->ccb->ccb_h.target_id,
ecb->ccb->ccb_h.target_lun));
- }
}
}
@@ -1412,10 +1412,10 @@ ncr53c9x_done(struct ncr53c9x_softc *sc,
*/
if (ccb->ccb_h.status == CAM_REQ_CMP) {
ccb->csio.scsi_status = ecb->stat;
- if ((ecb->flags & ECB_ABORT) != 0) {
+ 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)) {
+ else if ((ecb->flags & ECB_SENSE) != 0 &&
+ (ecb->stat != SCSI_STATUS_CHECK_COND)) {
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
CAM_AUTOSNS_VALID;
@@ -1439,13 +1439,15 @@ ncr53c9x_done(struct ncr53c9x_softc *sc,
}
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
}
- } else {
+ } else
ccb->csio.resid = ecb->dleft;
- }
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;
+ } else if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
+ ccb->ccb_h.status |= CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
}
#ifdef NCR53C9X_DEBUG
@@ -1473,7 +1475,7 @@ ncr53c9x_done(struct ncr53c9x_softc *sc,
}
}
- if (ccb->ccb_h.status == CAM_SEL_TIMEOUT) {
+ if ((ccb->ccb_h.status & CAM_SEL_TIMEOUT) != 0) {
/* Selection timeout -- discard this LUN if empty. */
if (li->untagged == NULL && li->used == 0) {
if (lun < NCR_NLUN)
@@ -2030,8 +2032,8 @@ gotit:
default:
xpt_print_path(ecb->ccb->ccb_h.path);
- printf("unrecognized MESSAGE EXTENDED;"
- " sending REJECT\n");
+ printf("unrecognized MESSAGE EXTENDED 0x%x;"
+ " sending REJECT\n", sc->sc_imess[2]);
goto reject;
}
break;
@@ -2039,7 +2041,8 @@ gotit:
default:
NCR_MSGS(("ident "));
xpt_print_path(ecb->ccb->ccb_h.path);
- printf("unrecognized MESSAGE; sending REJECT\n");
+ printf("unrecognized MESSAGE 0x%x; sending REJECT\n",
+ sc->sc_imess[0]);
/* FALLTHROUGH */
reject:
ncr53c9x_sched_msgout(SEND_REJECT);
@@ -2109,6 +2112,7 @@ ncr53c9x_msgout(struct ncr53c9x_softc *s
struct ncr53c9x_tinfo *ti;
struct ncr53c9x_ecb *ecb;
size_t size;
+ int error;
#ifdef NCR53C9X_DEBUG
int i;
#endif
@@ -2246,17 +2250,14 @@ ncr53c9x_msgout(struct ncr53c9x_softc *s
NCR_MSGS(("> "));
}
#endif
- if (sc->sc_rev == NCR_VARIANT_FAS366) {
- /*
- * XXX FIFO size
- */
- ncr53c9x_flushfifo(sc);
- ncr53c9x_wrfifo(sc, sc->sc_omp, sc->sc_omlen);
- NCRCMD(sc, NCRCMD_TRANS);
- } else {
+
+ if (sc->sc_rev != NCR_VARIANT_FAS366) {
/* (Re)send the message. */
size = ulmin(sc->sc_omlen, sc->sc_maxxfer);
- NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size);
+ error = NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size);
+ if (error != 0)
+ goto cmd;
+
/* Program the SCSI counter. */
NCR_SET_COUNT(sc, size);
@@ -2264,7 +2265,16 @@ ncr53c9x_msgout(struct ncr53c9x_softc *s
NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA);
NCRDMA_GO(sc);
+ return;
}
+
+cmd:
+ /*
+ * XXX FIFO size
+ */
+ ncr53c9x_flushfifo(sc);
+ ncr53c9x_wrfifo(sc, sc->sc_omp, sc->sc_omlen);
+ NCRCMD(sc, NCRCMD_TRANS);
}
void
@@ -2299,7 +2309,7 @@ ncr53c9x_intr1(struct ncr53c9x_softc *sc
struct ncr53c9x_tinfo *ti;
struct timeval cur, wait;
size_t size;
- int i, nfifo;
+ int error, i, nfifo;
uint8_t msg;
NCR_LOCK_ASSERT(sc, MA_OWNED);
@@ -2974,8 +2984,14 @@ msgin:
size = ecb->clen;
sc->sc_cmdlen = size;
sc->sc_cmdp = (void *)&ecb->cmd.cmd;
- NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen,
+ error = NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen,
0, &size);
+ if (error != 0) {
+ sc->sc_cmdlen = 0;
+ sc->sc_cmdp = NULL;
+ goto cmd;
+ }
+
/* Program the SCSI counter. */
NCR_SET_COUNT(sc, size);
@@ -2985,30 +3001,51 @@ msgin:
/* Start the command transfer. */
NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA);
NCRDMA_GO(sc);
- } else {
- ncr53c9x_wrfifo(sc, (uint8_t *)&ecb->cmd.cmd,
- ecb->clen);
- NCRCMD(sc, NCRCMD_TRANS);
+ sc->sc_prevphase = COMMAND_PHASE;
+ break;
}
+cmd:
+ ncr53c9x_wrfifo(sc, (uint8_t *)&ecb->cmd.cmd, ecb->clen);
+ NCRCMD(sc, NCRCMD_TRANS);
sc->sc_prevphase = COMMAND_PHASE;
break;
case DATA_OUT_PHASE:
NCR_PHASE(("DATA_OUT_PHASE [%ld] ", (long)sc->sc_dleft));
+ sc->sc_prevphase = DATA_OUT_PHASE;
NCRCMD(sc, NCRCMD_FLUSH);
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;
+ error = NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 0, &size);
goto setup_xfer;
case DATA_IN_PHASE:
NCR_PHASE(("DATA_IN_PHASE "));
+ sc->sc_prevphase = DATA_IN_PHASE;
if (sc->sc_rev == NCR_VARIANT_ESP100)
NCRCMD(sc, NCRCMD_FLUSH);
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:
+ error = NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft, 1, &size);
+setup_xfer:
+ if (error != 0) {
+ switch (error) {
+ case EFBIG:
+ ecb->ccb->ccb_h.status |= CAM_REQ_TOO_BIG;
+ break;
+ case EINPROGRESS:
+ panic("%s: cannot deal with deferred DMA",
+ __func__);
+ case EINVAL:
+ ecb->ccb->ccb_h.status |= CAM_REQ_INVALID;
+ break;
+ case ENOMEM:
+ ecb->ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ break;
+ default:
+ ecb->ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
+ }
+ goto finish;
+ }
+
/* Target returned to data phase: wipe "done" memory */
ecb->flags &= ~ECB_TENTATIVE_DONE;
Modified: stable/9/sys/dev/esp/ncr53c9xvar.h
==============================================================================
--- stable/9/sys/dev/esp/ncr53c9xvar.h Mon Nov 7 11:31:37 2011 (r227301)
+++ stable/9/sys/dev/esp/ncr53c9xvar.h Mon Nov 7 13:16:51 2011 (r227302)
@@ -68,8 +68,8 @@
/* $FreeBSD$ */
-#ifndef _DEV_IC_NCR53C9XVAR_H_
-#define _DEV_IC_NCR53C9XVAR_H_
+#ifndef _NCR53C9XVAR_H_
+#define _NCR53C9XVAR_H_
#include <sys/lock.h>
@@ -115,7 +115,8 @@
* scsi_status,sense_data}.
*/
struct ncr53c9x_ecb {
- /* These fields are preserved between alloc and free */
+ /* These fields are preserved between alloc and free. */
+ struct callout ch;
struct ncr53c9x_softc *sc;
int tag_id;
int flags;
@@ -130,7 +131,6 @@ struct ncr53c9x_ecb {
#define ECB_RESET 0x80
#define ECB_TENTATIVE_DONE 0x100
int timeout;
- struct callout ch;
struct {
uint8_t msg[3]; /* Selection Id msg and tags */
@@ -290,7 +290,7 @@ extern int ncr53c9x_debug;
struct ncr53c9x_softc;
/*
- * Function switch used as glue to MD code.
+ * Function switch used as glue to MD code
*/
struct ncr53c9x_glue {
/* Mandatory entry points. */
@@ -304,9 +304,6 @@ struct ncr53c9x_glue {
void (*gl_dma_go)(struct ncr53c9x_softc *);
void (*gl_dma_stop)(struct ncr53c9x_softc *);
int (*gl_dma_isactive)(struct ncr53c9x_softc *);
-
- /* Optional entry points. */
- void (*gl_clear_latched_intr)(struct ncr53c9x_softc *);
};
struct ncr53c9x_softc {
@@ -330,7 +327,7 @@ struct ncr53c9x_softc {
uint8_t sc_ccf; /* Clock Conversion */
uint8_t sc_timeout;
- /* register copies, see espreadregs() */
+ /* register copies, see ncr53c9x_readregs() */
uint8_t sc_espintr;
uint8_t sc_espstat;
uint8_t sc_espstep;
@@ -415,6 +412,7 @@ struct ncr53c9x_softc {
#define NCR_F_FASTSCSI 0x02 /* chip supports Fast mode */
#define NCR_F_DMASELECT 0x04 /* can do dmaselect */
#define NCR_F_SELATN3 0x08 /* chip supports SELATN3 command */
+#define NCR_F_LARGEXFER 0x10 /* chip supports transfers > 64k */
/* values for sc_msgout */
#define SEND_DEV_RESET 0x0001
@@ -499,8 +497,10 @@ struct ncr53c9x_softc {
#define ncr53c9x_cpb2stp(sc, cpb) \
((250 * (cpb)) / (sc)->sc_freq)
+extern devclass_t esp_devclass;
+
int ncr53c9x_attach(struct ncr53c9x_softc *sc);
int ncr53c9x_detach(struct ncr53c9x_softc *sc);
void ncr53c9x_intr(void *arg);
-#endif /* _DEV_IC_NCR53C9XVAR_H_ */
+#endif /* _NCR53C9XVAR_H_ */
Modified: stable/9/sys/sparc64/sbus/lsi64854.c
==============================================================================
--- stable/9/sys/sparc64/sbus/lsi64854.c Mon Nov 7 11:31:37 2011 (r227301)
+++ stable/9/sys/sparc64/sbus/lsi64854.c Mon Nov 7 13:16:51 2011 (r227302)
@@ -94,7 +94,12 @@ int lsi64854debug = 0;
#define DPRINTF(a,x)
#endif
-#define MAX_DMA_SZ (16*1024*1024)
+/*
+ * The rules say we cannot transfer more than the limit of this DMA chip (64k
+ * for old and 16Mb for new), and we cannot cross a 16Mb boundary.
+ */
+#define MAX_DMA_SZ (64 * 1024)
+#define BOUNDARY (16 * 1024 * 1024)
static void lsi64854_reset(struct lsi64854_softc *);
static void lsi64854_map_scsi(void *, bus_dma_segment_t *, int, int);
@@ -125,6 +130,7 @@ lsi64854_attach(struct lsi64854_softc *s
lockfunc = NULL;
lockfuncarg = NULL;
+ sc->sc_maxdmasize = MAX_DMA_SZ;
switch (sc->sc_channel) {
case L64854_CHANNEL_SCSI:
@@ -135,6 +141,7 @@ lsi64854_attach(struct lsi64854_softc *s
}
lockfunc = busdma_lock_mutex;
lockfuncarg = &nsc->sc_lock;
+ sc->sc_maxdmasize = nsc->sc_maxxfer;
sc->intr = lsi64854_scsi_intr;
sc->setup = lsi64854_setup;
break;
@@ -153,13 +160,13 @@ lsi64854_attach(struct lsi64854_softc *s
if (sc->setup != NULL) {
error = bus_dma_tag_create(
sc->sc_parent_dmat, /* parent */
- 1, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
+ 1, BOUNDARY, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- MAX_DMA_SZ, /* maxsize */
+ sc->sc_maxdmasize, /* maxsize */
1, /* nsegments */
- MAX_DMA_SZ, /* maxsegsize */
+ sc->sc_maxdmasize, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
lockfunc, lockfuncarg, /* lockfunc, lockfuncarg */
&sc->sc_buffer_dmat);
@@ -250,24 +257,25 @@ lsi64854_detach(struct lsi64854_softc *s
* other revs: D_ESC_R_PEND bit reads as 0 \
*/ \
DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
- if (sc->sc_rev != DMAREV_HME) { \
- /* \
- * Select drain bit based on revision \
- * also clears errors and D_TC flag \
- */ \
- csr = L64854_GCSR(sc); \
- if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0) \
- csr |= D_ESC_DRAIN; \
- else \
- csr |= L64854_INVALIDATE; \
+ if (sc->sc_rev != DMAREV_HME) { \
+ /* \
+ * Select drain bit based on revision \
+ * also clears errors and D_TC flag \
+ */ \
+ csr = L64854_GCSR(sc); \
+ if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0) \
+ csr |= D_ESC_DRAIN; \
+ else \
+ csr |= L64854_INVALIDATE; \
\
- L64854_SCSR(sc,csr); \
+ L64854_SCSR(sc, csr); \
} \
/* \
* Wait for draining to finish \
* rev0 & rev1 call this PACKCNT \
*/ \
- DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING", dontpanic);\
+ DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING", \
+ dontpanic); \
} while (/* CONSTCOND */0)
#define DMA_FLUSH(sc, dontpanic) do { \
@@ -282,12 +290,14 @@ lsi64854_detach(struct lsi64854_softc *s
csr = L64854_GCSR(sc); \
csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */ \
csr |= L64854_INVALIDATE; /* XXX FAS ? */ \
- L64854_SCSR(sc,csr); \
+ L64854_SCSR(sc, csr); \
} while (/* CONSTCOND */0)
static void
lsi64854_reset(struct lsi64854_softc *sc)
{
+ bus_dma_tag_t dmat;
+ bus_dmamap_t dmam;
uint32_t csr;
DMA_FLUSH(sc, 1);
@@ -296,10 +306,11 @@ lsi64854_reset(struct lsi64854_softc *sc
DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr));
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);
+ dmat = sc->sc_buffer_dmat;
+ dmam = sc->sc_dmamap;
+ bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+ bus_dmamap_unload(dmat, dmam);
}
if (sc->sc_rev == DMAREV_HME)
@@ -364,15 +375,16 @@ lsi64854_map_scsi(void *arg, bus_dma_seg
sc = (struct lsi64854_softc *)arg;
+ if (error != 0)
+ return;
if (nseg != 1)
panic("%s: cannot map %d segments\n", __func__, nseg);
bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
- sc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+ sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
}
-#define DMAMAX(a) (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ - 1)))
/*
* setup a DMA transfer
*/
@@ -381,6 +393,7 @@ lsi64854_setup(struct lsi64854_softc *sc
int datain, size_t *dmasize)
{
long bcnt;
+ int error;
uint32_t csr;
DMA_FLUSH(sc, 0);
@@ -392,15 +405,12 @@ lsi64854_setup(struct lsi64854_softc *sc
sc->sc_dmalen = len;
sc->sc_datain = datain;
- /*
- * The rules say we cannot transfer more than the limit
- * of this DMA chip (64k for old and 16Mb for new),
- * and we cannot cross a 16Mb boundary.
- */
- *dmasize = sc->sc_dmasize =
- ulmin(*dmasize, DMAMAX((size_t)*sc->sc_dmaaddr));
+ KASSERT(*dmasize <= sc->sc_maxdmasize,
+ ("%s: transfer size %ld too large", __func__, (long)*dmasize));
- DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
+ sc->sc_dmasize = *dmasize;
+
+ DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)*dmasize));
/*
* XXX what length?
@@ -412,24 +422,31 @@ lsi64854_setup(struct lsi64854_softc *sc
bus_write_4(sc->sc_res, L64854_REG_CNT, *dmasize);
}
- /* Program the DMA address */
- 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__);
+ /*
+ * Load the transfer buffer and program the DMA address.
+ * Note that the NCR53C9x core can't handle EINPROGRESS so we set
+ * BUS_DMA_NOWAIT.
+ */
+ if (*dmasize != 0) {
+ error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
+ *sc->sc_dmaaddr, *dmasize, lsi64854_map_scsi, sc,
+ BUS_DMA_NOWAIT);
+ if (error != 0)
+ return (error);
+ }
if (sc->sc_rev == DMAREV_ESC) {
/* DMA ESC chip bug work-around */
- bcnt = sc->sc_dmasize;
+ bcnt = *dmasize;
if (((bcnt + (long)*sc->sc_dmaaddr) & PAGE_MASK_8K) != 0)
bcnt = roundup(bcnt, PAGE_SIZE_8K);
bus_write_4(sc->sc_res, L64854_REG_CNT, bcnt);
}
- /* Setup DMA control register */
+ /* Setup the DMA control register. */
csr = L64854_GCSR(sc);
- if (datain)
+ if (datain != 0)
csr |= L64854_WRITE;
else
csr &= ~L64854_WRITE;
@@ -445,7 +462,7 @@ lsi64854_setup(struct lsi64854_softc *sc
/*
* Pseudo (chained) interrupt from the esp driver to kick the
- * current running DMA transfer. Called from ncr53c9x_intr()
+ * current running DMA transfer. Called from ncr53c9x_intr()
* for now.
*
* return 1 if it was a DMA continue.
@@ -455,19 +472,23 @@ lsi64854_scsi_intr(void *arg)
{
struct lsi64854_softc *sc = arg;
struct ncr53c9x_softc *nsc = sc->sc_client;
- int trans, resid;
+ bus_dma_tag_t dmat;
+ bus_dmamap_t dmam;
+ size_t dmasize;
+ int lxfer, resid, trans;
uint32_t csr;
csr = L64854_GCSR(sc);
DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__,
- bus_read_4(sc->sc_res, 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);
- csr &= ~D_EN_DMA; /* Stop DMA */
+ if (csr & (D_ERR_PEND | D_SLAVE_ERR)) {
+ device_printf(sc->sc_dev, "error: csr=%b\n", csr,
+ DDMACSR_BITS);
+ csr &= ~D_EN_DMA; /* Stop DMA. */
/* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
- csr |= D_INVALIDATE|D_SLAVE_ERR;
+ csr |= D_INVALIDATE | D_SLAVE_ERR;
L64854_SCSR(sc, csr);
return (-1);
}
@@ -483,10 +504,11 @@ lsi64854_scsi_intr(void *arg)
L64854_SCSR(sc, csr);
sc->sc_active = 0;
- if (sc->sc_dmasize == 0) {
- /* A "Transfer Pad" operation completed */
- DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, tcm=%d)\n",
- __func__, NCR_READ_REG(nsc, NCR_TCL) |
+ dmasize = sc->sc_dmasize;
+ if (dmasize == 0) {
+ /* A "Transfer Pad" operation completed. */
+ DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, "
+ "tcm=%d)\n", __func__, NCR_READ_REG(nsc, NCR_TCL) |
(NCR_READ_REG(nsc, NCR_TCM) << 8),
NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM)));
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-9
mailing list