- 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 used in the SBus front-end, the LSI64854 isn't limited to 32-bit DMA. - 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. - 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.
This commit is contained in:
parent
41264f106d
commit
e4f8c28c9e
@ -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_sbus_glue = {
|
||||
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 struct ncr53c9x_glue *gluep)
|
||||
|
||||
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 struct ncr53c9x_glue *gluep)
|
||||
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 struct ncr53c9x_glue *gluep)
|
||||
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 struct ncr53c9x_glue *gluep)
|
||||
|
||||
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 struct ncr53c9x_glue *gluep)
|
||||
*/
|
||||
device_printf(esc->sc_dev,
|
||||
"Unknown chip\n");
|
||||
goto fail_lsi;
|
||||
error = ENXIO;
|
||||
goto fail_lock;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -570,12 +567,6 @@ espattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep)
|
||||
printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid);
|
||||
#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
|
||||
@ -587,31 +578,27 @@ espattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep)
|
||||
*/
|
||||
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 struct ncr53c9x_glue *gluep)
|
||||
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,
|
||||
|
@ -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(struct ncr53c9x_softc *sc,
|
||||
#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 *sc)
|
||||
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 *sc)
|
||||
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->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 *sc, struct ncr53c9x_ecb *ecb)
|
||||
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 *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);
|
||||
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 *sc, struct ncr53c9x_ecb *ecb)
|
||||
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, union ccb *ccb)
|
||||
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, union ccb *ccb)
|
||||
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, union ccb *ccb)
|
||||
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, union ccb *ccb)
|
||||
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, union ccb *ccb)
|
||||
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, union ccb *ccb)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2030,8 +2031,8 @@ ncr53c9x_msgin(struct ncr53c9x_softc *sc)
|
||||
|
||||
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 +2040,8 @@ ncr53c9x_msgin(struct ncr53c9x_softc *sc)
|
||||
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 +2111,7 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
|
||||
struct ncr53c9x_tinfo *ti;
|
||||
struct ncr53c9x_ecb *ecb;
|
||||
size_t size;
|
||||
int error;
|
||||
#ifdef NCR53C9X_DEBUG
|
||||
int i;
|
||||
#endif
|
||||
@ -2246,17 +2249,14 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
|
||||
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 +2264,16 @@ ncr53c9x_msgout(struct ncr53c9x_softc *sc)
|
||||
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 +2308,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 +2983,14 @@ ncr53c9x_intr1(struct ncr53c9x_softc *sc)
|
||||
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 +3000,51 @@ ncr53c9x_intr1(struct ncr53c9x_softc *sc)
|
||||
/* 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;
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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 *sc)
|
||||
|
||||
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 *sc)
|
||||
}
|
||||
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 *sc)
|
||||
if (sc->setup != NULL) {
|
||||
error = bus_dma_tag_create(
|
||||
sc->sc_parent_dmat, /* parent */
|
||||
1, 0, /* alignment, boundary */
|
||||
1, BOUNDARY, /* alignment, boundary */
|
||||
BUS_SPACE_MAXADDR, /* 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 *sc)
|
||||
* 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 *sc)
|
||||
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_segment_t *segs, int nseg, int error)
|
||||
|
||||
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, void **addr, size_t *len,
|
||||
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, void **addr, size_t *len,
|
||||
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, void **addr, size_t *len,
|
||||
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;
|
||||
@ -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)));
|
||||
return (0);
|
||||
@ -499,7 +521,7 @@ lsi64854_scsi_intr(void *arg)
|
||||
* as residual since the NCR53C9X counter registers get decremented
|
||||
* as bytes are clocked into the FIFO.
|
||||
*/
|
||||
if (!(csr & D_WRITE) &&
|
||||
if ((csr & D_WRITE) == 0 &&
|
||||
(resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
|
||||
DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__,
|
||||
resid));
|
||||
@ -509,22 +531,21 @@ lsi64854_scsi_intr(void *arg)
|
||||
}
|
||||
|
||||
if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
|
||||
lxfer = nsc->sc_features & NCR_F_LARGEXFER;
|
||||
/*
|
||||
* `Terminal count' is off, so read the residue
|
||||
* "Terminal count" is off, so read the residue
|
||||
* out of the NCR53C9X counter registers.
|
||||
*/
|
||||
resid += (NCR_READ_REG(nsc, NCR_TCL) |
|
||||
(NCR_READ_REG(nsc, NCR_TCM) << 8) |
|
||||
((nsc->sc_cfg2 & NCRCFG2_FE) ?
|
||||
(NCR_READ_REG(nsc, NCR_TCH) << 16) : 0));
|
||||
(lxfer != 0 ? (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0));
|
||||
|
||||
if (resid == 0 && sc->sc_dmasize == 65536 &&
|
||||
(nsc->sc_cfg2 & NCRCFG2_FE) == 0)
|
||||
/* A transfer of 64K is encoded as `TCL=TCM=0' */
|
||||
if (resid == 0 && dmasize == 65536 && lxfer == 0)
|
||||
/* A transfer of 64k is encoded as TCL=TCM=0. */
|
||||
resid = 65536;
|
||||
}
|
||||
|
||||
trans = sc->sc_dmasize - resid;
|
||||
trans = dmasize - resid;
|
||||
if (trans < 0) { /* transferred < 0? */
|
||||
#if 0
|
||||
/*
|
||||
@ -533,21 +554,22 @@ lsi64854_scsi_intr(void *arg)
|
||||
* another target. As such, don't print the warning.
|
||||
*/
|
||||
device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans,
|
||||
sc->sc_dmasize);
|
||||
dmasize);
|
||||
#endif
|
||||
trans = sc->sc_dmasize;
|
||||
trans = dmasize;
|
||||
}
|
||||
|
||||
DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
|
||||
__func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM),
|
||||
(nsc->sc_cfg2 & NCRCFG2_FE) ? NCR_READ_REG(nsc, NCR_TCH) : 0,
|
||||
trans, resid));
|
||||
(nsc->sc_sc_features & NCR_F_LARGEXFER) != 0 ?
|
||||
NCR_READ_REG(nsc, NCR_TCH) : 0, trans, resid));
|
||||
|
||||
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);
|
||||
if (dmasize != 0) {
|
||||
dmat = sc->sc_buffer_dmat;
|
||||
dmam = sc->sc_dmamap;
|
||||
bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
|
||||
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(dmat, dmam);
|
||||
}
|
||||
|
||||
*sc->sc_dmalen -= trans;
|
||||
@ -565,7 +587,7 @@ lsi64854_scsi_intr(void *arg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Pseudo (chained) interrupt to le driver to handle DMA errors.
|
||||
* Pseudo (chained) interrupt to le(4) driver to handle DMA errors
|
||||
*/
|
||||
static int
|
||||
lsi64854_enet_intr(void *arg)
|
||||
@ -579,11 +601,12 @@ lsi64854_enet_intr(void *arg)
|
||||
/* If the DMA logic shows an interrupt, claim it */
|
||||
rv = ((csr & E_INT_PEND) != 0) ? 1 : 0;
|
||||
|
||||
if (csr & (E_ERR_PEND|E_SLAVE_ERR)) {
|
||||
device_printf(sc->sc_dev, "error: csr=%b\n", csr, EDMACSR_BITS);
|
||||
csr &= ~L64854_EN_DMA; /* Stop DMA */
|
||||
if (csr & (E_ERR_PEND | E_SLAVE_ERR)) {
|
||||
device_printf(sc->sc_dev, "error: csr=%b\n", csr,
|
||||
EDMACSR_BITS);
|
||||
csr &= ~L64854_EN_DMA; /* Stop DMA. */
|
||||
/* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
|
||||
csr |= E_INVALIDATE|E_SLAVE_ERR;
|
||||
csr |= E_INVALIDATE | E_SLAVE_ERR;
|
||||
L64854_SCSR(sc, csr);
|
||||
/* Will be drained with the LE_C0_IDON interrupt. */
|
||||
sc->sc_dodrain = 1;
|
||||
@ -610,23 +633,26 @@ lsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
|
||||
sc = (struct lsi64854_softc *)arg;
|
||||
|
||||
if (error != 0)
|
||||
return;
|
||||
if (nsegs != 1)
|
||||
panic("%s: cannot map %d segments\n", __func__, nsegs);
|
||||
|
||||
bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, sc->sc_datain ?
|
||||
BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
|
||||
bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
|
||||
sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
|
||||
bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
|
||||
|
||||
bus_write_4(sc->sc_res, L64854_REG_CNT, sc->sc_dmasize);
|
||||
}
|
||||
|
||||
/*
|
||||
* setup a DMA transfer
|
||||
* Setup a DMA transfer.
|
||||
*/
|
||||
static int
|
||||
lsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len,
|
||||
int datain, size_t *dmasize)
|
||||
{
|
||||
int error;
|
||||
uint32_t csr;
|
||||
|
||||
DMA_FLUSH(sc, 0);
|
||||
@ -636,25 +662,25 @@ lsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len,
|
||||
sc->sc_datain = datain;
|
||||
|
||||
DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", __func__,
|
||||
(long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0));
|
||||
(long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain != 0 ? 1 : 0));
|
||||
|
||||
/*
|
||||
* 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_PP, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
|
||||
sc->sc_dmasize = *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_pp, sc, 0))
|
||||
panic("%s: pp cannot allocate DVMA address", __func__);
|
||||
DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)*dmasize));
|
||||
|
||||
/* Setup DMA control register */
|
||||
/* Load the transfer buffer and program the DMA address. */
|
||||
if (*dmasize != 0) {
|
||||
error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
|
||||
*sc->sc_dmaaddr, *dmasize, lsi64854_map_pp, sc,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Setup the DMA control register. */
|
||||
csr = L64854_GCSR(sc);
|
||||
csr &= ~L64854_BURST_SIZE;
|
||||
if (sc->sc_burst == 32)
|
||||
@ -663,10 +689,10 @@ lsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len,
|
||||
csr |= L64854_BURST_16;
|
||||
else
|
||||
csr |= L64854_BURST_0;
|
||||
csr |= P_EN_DMA|P_INT_EN|P_EN_CNT;
|
||||
csr |= P_EN_DMA | P_INT_EN | P_EN_CNT;
|
||||
#if 0
|
||||
/* This bit is read-only in PP csr register */
|
||||
if (datain)
|
||||
/* This bit is read-only in PP csr register. */
|
||||
if (datain != 0)
|
||||
csr |= P_WRITE;
|
||||
else
|
||||
csr &= ~P_WRITE;
|
||||
@ -677,12 +703,15 @@ lsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len,
|
||||
}
|
||||
|
||||
/*
|
||||
* Parallel port DMA interrupt.
|
||||
* Parallel port DMA interrupt
|
||||
*/
|
||||
static int
|
||||
lsi64854_pp_intr(void *arg)
|
||||
{
|
||||
struct lsi64854_softc *sc = arg;
|
||||
bus_dma_tag_t dmat;
|
||||
bus_dmamap_t dmam;
|
||||
size_t dmasize;
|
||||
int ret, trans, resid = 0;
|
||||
uint32_t csr;
|
||||
|
||||
@ -691,13 +720,13 @@ lsi64854_pp_intr(void *arg)
|
||||
DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__,
|
||||
bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, PDMACSR_BITS));
|
||||
|
||||
if (csr & (P_ERR_PEND|P_SLAVE_ERR)) {
|
||||
if ((csr & (P_ERR_PEND | P_SLAVE_ERR)) != 0) {
|
||||
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 */
|
||||
csr &= ~P_EN_DMA; /* Stop DMA. */
|
||||
/* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
|
||||
csr |= P_INVALIDATE|P_SLAVE_ERR;
|
||||
csr |= P_INVALIDATE | P_SLAVE_ERR;
|
||||
L64854_SCSR(sc, csr);
|
||||
return (-1);
|
||||
}
|
||||
@ -714,17 +743,19 @@ lsi64854_pp_intr(void *arg)
|
||||
L64854_SCSR(sc, csr);
|
||||
sc->sc_active = 0;
|
||||
|
||||
trans = sc->sc_dmasize - resid;
|
||||
dmasize = sc->sc_dmasize;
|
||||
trans = dmasize - resid;
|
||||
if (trans < 0) /* transferred < 0? */
|
||||
trans = sc->sc_dmasize;
|
||||
trans = dmasize;
|
||||
*sc->sc_dmalen -= trans;
|
||||
*sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
|
||||
|
||||
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);
|
||||
if (dmasize != 0) {
|
||||
dmat = sc->sc_buffer_dmat;
|
||||
dmam = sc->sc_dmamap;
|
||||
bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
|
||||
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(dmat, dmam);
|
||||
}
|
||||
|
||||
return (ret != 0);
|
||||
|
@ -49,6 +49,7 @@ struct lsi64854_softc {
|
||||
|
||||
bus_dma_tag_t sc_parent_dmat;
|
||||
bus_dma_tag_t sc_buffer_dmat;
|
||||
bus_size_t sc_maxdmasize;
|
||||
int sc_datain;
|
||||
size_t sc_dmasize;
|
||||
void **sc_dmaaddr;
|
||||
|
Loading…
Reference in New Issue
Block a user