Misc cleanups:

- correct trm_clock_period[] value
 - pass BUS_DMA_{READ,WRITE,STREAMING} to bus_dmamap_load() as appropriate
 - make sure to call bus_dmamap_unload() even after request sense
 - saved srb params on request sense do not seem to be used,
   so remove them from struct trm_srb
 - handle target status more properly in trm_srb_done() and no need
   to handle error retry in lower driver layer
 - fix some comments

XXX Maybe need more cleanup around TQING for MI SCSI callback..
This commit is contained in:
tsutsui 2001-11-18 13:02:30 +00:00
parent 59935b6103
commit acd87a7687
1 changed files with 88 additions and 165 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: trm.c,v 1.4 2001/11/13 07:48:49 lukem Exp $ */ /* $NetBSD: trm.c,v 1.5 2001/11/18 13:02:30 tsutsui Exp $ */
/* /*
* Device Driver for Tekram DC395U/UW/F, DC315/U * Device Driver for Tekram DC395U/UW/F, DC315/U
* PCI SCSI Bus Master Host Adapter * PCI SCSI Bus Master Host Adapter
@ -41,7 +41,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: trm.c,v 1.4 2001/11/13 07:48:49 lukem Exp $"); __KERNEL_RCSID(0, "$NetBSD: trm.c,v 1.5 2001/11/18 13:02:30 tsutsui Exp $");
/* #define TRM_DEBUG */ /* #define TRM_DEBUG */
@ -96,7 +96,7 @@ struct nvram_target {
#define NTC_DO_SEND_START 0x08 /* Send start command SPINUP */ #define NTC_DO_SEND_START 0x08 /* Send start command SPINUP */
#define NTC_DO_DISCONNECT 0x04 /* Enable SCSI disconnect */ #define NTC_DO_DISCONNECT 0x04 /* Enable SCSI disconnect */
#define NTC_DO_SYNC_NEGO 0x02 /* Sync negotiation */ #define NTC_DO_SYNC_NEGO 0x02 /* Sync negotiation */
#define NTC_DO_PARITY_CHK 0x01 /* (it should define at NAC) Parity check enable */ #define NTC_DO_PARITY_CHK 0x01 /* Parity check enable */
u_int8_t period; /* Target period */ u_int8_t period; /* Target period */
u_int8_t config2; /* Target configuration byte 2 */ u_int8_t config2; /* Target configuration byte 2 */
u_int8_t config3; /* Target configuration byte 3 */ u_int8_t config3; /* Target configuration byte 3 */
@ -153,16 +153,11 @@ struct trm_srb {
struct trm_dcb *dcb; struct trm_dcb *dcb;
struct trm_sg_entry *sgentry; struct trm_sg_entry *sgentry;
struct trm_sg_entry tempsg; /* Temp sgentry when Request Sense */ struct scsipi_xfer *xs; /* scsipi_xfer for this cmd */
/*
* the scsipi_xfer for this cmd
*/
struct scsipi_xfer *xs;
bus_dmamap_t dmap; bus_dmamap_t dmap;
bus_size_t sgoffset; /* Xfer buf offset */ bus_size_t sgoffset; /* Xfer buf offset */
u_int32_t buflen; /* Total xfer length */ u_int32_t buflen; /* Total xfer length */
u_int32_t templen; /* Temp buflen when Request Sense */
u_int32_t sgaddr; /* SGList physical starting address */ u_int32_t sgaddr; /* SGList physical starting address */
u_int state; /* SRB State */ u_int state; /* SRB State */
@ -218,12 +213,10 @@ struct trm_srb {
#define PARITY_ERROR 0x10 #define PARITY_ERROR 0x10
#define SRB_ERROR 0x20 #define SRB_ERROR 0x20
int tagnum; /* Tag number */ int tagnum; /* Tag number */
int retry; /* Retry Count */
int msgcnt; int msgcnt;
int cmdlen; /* SCSI command length */ int cmdlen; /* SCSI command length */
u_int8_t cmd[12]; /* SCSI command */ u_int8_t cmd[12]; /* SCSI command */
u_int8_t tempcmd[6]; /* Temp cmd when Request Sense */
u_int8_t msgin[6]; u_int8_t msgin[6];
u_int8_t msgout[6]; u_int8_t msgout[6];
@ -270,7 +263,6 @@ struct trm_dcb {
u_int8_t flag; u_int8_t flag;
#define ABORT_DEV_ 0x01 #define ABORT_DEV_ 0x01
#define SHOW_MESSAGE_ 0x02 #define SHOW_MESSAGE_ 0x02
u_int8_t type; /* Device Type */
}; };
/* /*
@ -372,7 +364,7 @@ static void trm_srb_done(struct trm_softc *, struct trm_dcb *,
static void trm_doing_srb_done(struct trm_softc *); static void trm_doing_srb_done(struct trm_softc *);
static void trm_scsi_reset_detect(struct trm_softc *); static void trm_scsi_reset_detect(struct trm_softc *);
static void trm_reset_scsi_bus(struct trm_softc *); static void trm_reset_scsi_bus(struct trm_softc *);
static void trm_request_sense(struct trm_softc *, struct trm_dcb *, static int trm_request_sense(struct trm_softc *, struct trm_dcb *,
struct trm_srb *); struct trm_srb *);
static void trm_msgout_abort(struct trm_softc *, struct trm_srb *); static void trm_msgout_abort(struct trm_softc *, struct trm_srb *);
static void trm_timeout(void *); static void trm_timeout(void *);
@ -434,7 +426,7 @@ static void *trm_scsi_phase1[] = {
/* real period: */ /* real period: */
static const u_int8_t trm_clock_period[] = { static const u_int8_t trm_clock_period[] = {
13, /* 52 ns 20.0 MB/sec */ 12, /* 48 ns 20.0 MB/sec */
18, /* 72 ns 13.3 MB/sec */ 18, /* 72 ns 13.3 MB/sec */
25, /* 100 ns 10.0 MB/sec */ 25, /* 100 ns 10.0 MB/sec */
31, /* 124 ns 8.0 MB/sec */ 31, /* 124 ns 8.0 MB/sec */
@ -708,7 +700,7 @@ trm_scsipi_request(chan, req, arg)
* Request Block for SCSI processor command doing. * Request Block for SCSI processor command doing.
*/ */
memcpy(srb->cmd, xs->cmd, xs->cmdlen); memcpy(srb->cmd, xs->cmd, xs->cmdlen);
if (xs->datalen > 0) { if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
#ifdef TRM_DEBUG #ifdef TRM_DEBUG
printf("xs->datalen...\n"); printf("xs->datalen...\n");
printf("sc->sc_dmat=%x\n", (int) sc->sc_dmat); printf("sc->sc_dmat=%x\n", (int) sc->sc_dmat);
@ -718,8 +710,11 @@ trm_scsipi_request(chan, req, arg)
#endif #endif
if ((error = bus_dmamap_load(sc->sc_dmat, srb->dmap, if ((error = bus_dmamap_load(sc->sc_dmat, srb->dmap,
xs->data, xs->datalen, NULL, xs->data, xs->datalen, NULL,
(xs->xs_control & XS_CTL_NOSLEEP) ? ((xs->xs_control & XS_CTL_NOSLEEP) ?
BUS_DMA_NOWAIT : BUS_DMA_WAITOK)) != 0) { BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
BUS_DMA_STREAMING |
((xs->xs_control & XS_CTL_DATA_IN) ?
BUS_DMA_READ : BUS_DMA_WRITE))) != 0) {
printf("%s: DMA transfer map unable to load, " printf("%s: DMA transfer map unable to load, "
"error = %d\n", sc->sc_dev.dv_xname, error); "error = %d\n", sc->sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP; xs->error = XS_DRIVER_STUFFUP;
@ -754,11 +749,6 @@ trm_scsipi_request(chan, req, arg)
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
srb->sgoffset, TRM_SG_SIZE, BUS_DMASYNC_PREWRITE); srb->sgoffset, TRM_SG_SIZE, BUS_DMASYNC_PREWRITE);
if (dcb->type != T_SEQUENTIAL)
srb->retry = 1;
else
srb->retry = 0;
srb->sgindex = 0; srb->sgindex = 0;
srb->hastat = 0; srb->hastat = 0;
srb->tastat = 0; srb->tastat = 0;
@ -968,8 +958,7 @@ trm_start_scsi(sc, dcb, srb)
idmsg = dcb->idmsg; idmsg = dcb->idmsg;
if ((srb->cmd[0] == INQUIRY) || if ((srb->cmd[0] == INQUIRY) ||
(srb->cmd[0] == REQUEST_SENSE) || (srb->cmd[0] == REQUEST_SENSE)) {
(srb->flag & AUTO_REQSENSE)) {
if (((dcb->mode & WIDE_NEGO_ENABLE) && if (((dcb->mode & WIDE_NEGO_ENABLE) &&
(dcb->mode & WIDE_NEGO_DONE) == 0) || (dcb->mode & WIDE_NEGO_DONE) == 0) ||
((dcb->mode & SYNC_NEGO_ENABLE) && ((dcb->mode & SYNC_NEGO_ENABLE) &&
@ -1015,18 +1004,7 @@ polling:
/* /*
* Send CDB ..command block... * Send CDB ..command block...
*/ */
if (srb->flag & AUTO_REQSENSE) { bus_space_write_multi_1(iot, ioh, TRM_SCSI_FIFO, srb->cmd, srb->cmdlen);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, REQUEST_SENSE);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO,
dcb->idmsg << SCSI_CMD_LUN_SHIFT);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, 0);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, 0);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO,
sizeof(struct scsipi_sense_data));
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, 0);
} else
bus_space_write_multi_1(iot, ioh, TRM_SCSI_FIFO,
srb->cmd, srb->cmdlen);
if (bus_space_read_2(iot, ioh, TRM_SCSI_STATUS) & SCSIINTERRUPT) { if (bus_space_read_2(iot, ioh, TRM_SCSI_STATUS) & SCSIINTERRUPT) {
/* /*
@ -1182,8 +1160,7 @@ trm_msgout_phase1(sc, srb, pstat)
srb->state = SRB_ABORT_SENT; srb->state = SRB_ABORT_SENT;
} else { } else {
if ((srb->cmd[0] == INQUIRY) || if ((srb->cmd[0] == INQUIRY) ||
(srb->cmd[0] == REQUEST_SENSE) || (srb->cmd[0] == REQUEST_SENSE))
(srb->flag & AUTO_REQSENSE))
if (dcb->mode & SYNC_NEGO_ENABLE) if (dcb->mode & SYNC_NEGO_ENABLE)
goto mop1; goto mop1;
@ -1270,24 +1247,9 @@ trm_command_phase1(sc, srb, pstat)
{ {
bus_space_tag_t iot = sc->sc_iot; bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh; bus_space_handle_t ioh = sc->sc_ioh;
struct trm_dcb *dcb;
bus_space_write_2(iot, ioh, TRM_SCSI_CONTROL, DO_CLRATN | DO_CLRFIFO); bus_space_write_2(iot, ioh, TRM_SCSI_CONTROL, DO_CLRATN | DO_CLRFIFO);
if (srb->flag & AUTO_REQSENSE) { bus_space_write_multi_1(iot, ioh, TRM_SCSI_FIFO, srb->cmd, srb->cmdlen);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, REQUEST_SENSE);
dcb = sc->sc_actdcb;
/* target id */
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO,
dcb->idmsg << SCSI_CMD_LUN_SHIFT);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, 0);
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, 0);
/* sizeof(struct scsi_sense_data) */
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO,
sizeof(struct scsipi_sense_data));
bus_space_write_1(iot, ioh, TRM_SCSI_FIFO, 0);
} else
bus_space_write_multi_1(iot, ioh, TRM_SCSI_FIFO,
srb->cmd, srb->cmdlen);
srb->state = SRB_COMMAND; srb->state = SRB_COMMAND;
/* it's important for atn stop */ /* it's important for atn stop */
@ -2196,99 +2158,36 @@ trm_srb_done(sc, dcb, srb)
struct scsipi_xfer *xs = srb->xs; struct scsipi_xfer *xs = srb->xs;
struct scsipi_inquiry_data *ptr; struct scsipi_inquiry_data *ptr;
struct trm_dcb *tempdcb; struct trm_dcb *tempdcb;
int i, j, id, lun, s, tastat; int i, j, id, lun, s;
u_int8_t bval; u_int8_t bval;
#ifdef TRM_DEBUG #ifdef TRM_DEBUG
printf("trm_srb_done..................\n"); printf("trm_srb_done..................\n");
#endif #endif
if ((xs->xs_control & XS_CTL_POLL) == 0)
callout_stop(&xs->xs_callout);
if (xs == NULL) if (xs == NULL)
return; return;
/* if ((xs->xs_control & XS_CTL_POLL) == 0)
* target status callout_stop(&xs->xs_callout);
*/
tastat = srb->tastat;
if (srb->flag & AUTO_REQSENSE) { if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT) ||
/* srb->flag & AUTO_REQSENSE) {
* status of auto request sense bus_dmamap_sync(sc->sc_dmat, srb->dmap, 0,
*/ srb->dmap->dm_mapsize,
srb->flag &= ~AUTO_REQSENSE; ((xs->xs_control & XS_CTL_DATA_IN) ||
srb->hastat = 0; (srb->flag & AUTO_REQSENSE)) ?
srb->tastat = SCSI_CHECK; BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
if (tastat == SCSI_CHECK) { bus_dmamap_unload(sc->sc_dmat, srb->dmap);
xs->error = XS_TIMEOUT;
goto ckc_e;
}
memcpy(srb->cmd, srb->tempcmd, sizeof(srb->tempcmd));
srb->buflen = srb->templen;
srb->sgentry[0].address = srb->tempsg.address;
srb->sgentry[0].length = srb->tempsg.length;
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, srb->sgoffset,
TRM_SG_SIZE, BUS_DMASYNC_PREWRITE);
xs->status = SCSI_CHECK;
goto ckc_e;
} }
/* /*
* target status * target status
*/ */
if (tastat) xs->status = srb->tastat;
switch (tastat) {
case SCSI_CHECK: switch (xs->status) {
trm_request_sense(sc, dcb, srb); case SCSI_OK:
return;
case SCSI_QUEUE_FULL:
dcb->maxcmd = dcb->gosrb_cnt - 1;
trm_rewait_srb(dcb, srb);
srb->hastat = 0;
srb->tastat = 0;
goto ckc_e;
case SCSI_SEL_TIMEOUT:
srb->hastat = H_SEL_TIMEOUT;
srb->tastat = 0;
xs->error = XS_TIMEOUT;
break;
case SCSI_BUSY:
xs->error = XS_BUSY;
break;
case SCSI_RESV_CONFLICT:
#ifdef TRM_DEBUG
printf("%s: target reserved at ", sc->sc_dev.dv_xname);
printf("%s %d\n", __FILE__, __LINE__);
#endif
xs->error = XS_BUSY;
break;
default:
srb->hastat = 0;
if (srb->retry) {
srb->retry--;
srb->tastat = 0;
srb->sgindex = 0;
if (trm_start_scsi(sc, dcb, srb))
/*
* If trm_start_scsi return 1 :
* current interrupt status is
* interrupt disreenable. It's said
* that SCSI processor has more one
* SRB need to do.
*/
trm_rewait_srb(dcb, srb);
return;
} else {
#ifdef TRM_DEBUG
printf("%s: driver stuffup at %s %d\n",
sc->sc_dev.dv_xname, __FILE__, __LINE__);
#endif
xs->error = XS_DRIVER_STUFFUP;
break;
}
}
else {
/* /*
* process initiator status...... * process initiator status......
* Adapter (initiator) status * Adapter (initiator) status
@ -2304,26 +2203,67 @@ trm_srb_done(sc, dcb, srb)
#endif #endif
/* Driver failed to perform operation */ /* Driver failed to perform operation */
xs->error = XS_DRIVER_STUFFUP; xs->error = XS_DRIVER_STUFFUP;
} else { /* No error */ } else {
/* No error */
srb->hastat = 0; srb->hastat = 0;
srb->tastat = 0; if (srb->flag & AUTO_REQSENSE) {
xs->error = XS_NOERROR; /* there is no error, (sense is invalid) */
/* there is no error, (sense is invalid) */ xs->error = XS_SENSE;
} else {
srb->tastat = 0;
xs->error = XS_NOERROR;
}
} }
break;
case SCSI_CHECK:
if ((srb->flag & AUTO_REQSENSE) != 0 ||
trm_request_sense(sc, dcb, srb) != 0) {
printf("%s: request sense failed\n",
sc->sc_dev.dv_xname);
xs->error = XS_DRIVER_STUFFUP;
break;
}
xs->error = XS_SENSE;
return;
case SCSI_QUEUE_FULL:
dcb->maxcmd = dcb->gosrb_cnt - 1;
trm_rewait_srb(dcb, srb);
srb->hastat = 0;
srb->tastat = 0;
break;
case SCSI_SEL_TIMEOUT:
srb->hastat = H_SEL_TIMEOUT;
srb->tastat = 0;
xs->error = XS_TIMEOUT;
break;
case SCSI_BUSY:
xs->error = XS_BUSY;
break;
case SCSI_RESV_CONFLICT:
#ifdef TRM_DEBUG
printf("%s: target reserved at ", sc->sc_dev.dv_xname);
printf("%s %d\n", __FILE__, __LINE__);
#endif
xs->error = XS_BUSY;
break;
default:
srb->hastat = 0;
#ifdef TRM_DEBUG
printf("%s: driver stuffup at %s %d\n",
sc->sc_dev.dv_xname, __FILE__, __LINE__);
#endif
xs->error = XS_DRIVER_STUFFUP;
break;
} }
ckc_e:
id = srb->xs->xs_periph->periph_target; id = srb->xs->xs_periph->periph_target;
lun = srb->xs->xs_periph->periph_lun; lun = srb->xs->xs_periph->periph_lun;
if (sc->devscan[id][lun]) { if (sc->devscan[id][lun]) {
/* /*
* if SCSI command in "scan devices" duty * if SCSI command in "scan devices" duty
* XXX XXX XXX should not be done here! XXX XXX XXX
*/ */
if (srb->cmd[0] == TEST_UNIT_READY) { if (srb->cmd[0] == INQUIRY) {
/* SCSI command phase: test unit ready */
#ifdef TRM_DEBUG
printf("srb->cmd[0] == TEST_UNIT_READY....\n");
#endif
} else if (srb->cmd[0] == INQUIRY) {
/* /*
* SCSI command phase: inquiry scsi device data * SCSI command phase: inquiry scsi device data
* (type,capacity,manufacture.... * (type,capacity,manufacture....
@ -2333,9 +2273,7 @@ ckc_e:
ptr = (struct scsipi_inquiry_data *)xs->data; ptr = (struct scsipi_inquiry_data *)xs->data;
bval = ptr->device & SID_TYPE; bval = ptr->device & SID_TYPE;
/*
* #define T_NODEVICE 0x1f Unknown or no device type
*/
if (bval == T_NODEVICE) { if (bval == T_NODEVICE) {
NO_DEV: NO_DEV:
#ifdef TRM_DEBUG #ifdef TRM_DEBUG
@ -2404,7 +2342,6 @@ ckc_e:
} }
splx(s); splx(s);
} else { } else {
dcb->type = bval;
if (bval == T_DIRECT || bval == T_OPTICAL) { if (bval == T_DIRECT || bval == T_OPTICAL) {
if ((((ptr->version & 0x07) >= 2) || if ((((ptr->version & 0x07) >= 2) ||
((ptr->response_format & 0x0F) ((ptr->response_format & 0x0F)
@ -2419,17 +2356,9 @@ ckc_e:
dcb->mode |= EN_ATN_STOP; dcb->mode |= EN_ATN_STOP;
} }
} }
/* srb->cmd[0] == INQUIRY */
} }
/* sc->devscan[id][lun] */
} }
exit: exit:
if (xs->datalen > 0) {
bus_dmamap_sync(sc->sc_dmat, srb->dmap, 0,
srb->dmap->dm_mapsize, (xs->xs_control & XS_CTL_DATA_IN) ?
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, srb->dmap);
}
trm_release_srb(sc, dcb, srb); trm_release_srb(sc, dcb, srb);
trm_wait_srb(sc); trm_wait_srb(sc);
xs->xs_status |= XS_STS_DONE; xs->xs_status |= XS_STS_DONE;
@ -2550,7 +2479,7 @@ trm_scsi_reset_detect(sc)
splx(s); splx(s);
} }
static void static int
trm_request_sense(sc, dcb, srb) trm_request_sense(sc, dcb, srb)
struct trm_softc *sc; struct trm_softc *sc;
struct trm_dcb *dcb; struct trm_dcb *dcb;
@ -2561,11 +2490,6 @@ trm_request_sense(sc, dcb, srb)
int error, lun = xs->xs_periph->periph_lun; int error, lun = xs->xs_periph->periph_lun;
srb->flag |= AUTO_REQSENSE; srb->flag |= AUTO_REQSENSE;
memcpy(srb->tempcmd, srb->cmd, sizeof(srb->tempcmd));
srb->templen = srb->buflen;
srb->tempsg.address = srb->sgentry[0].address;
srb->tempsg.length = srb->sgentry[0].length;
/* Status of initiator/target */ /* Status of initiator/target */
srb->hastat = 0; srb->hastat = 0;
@ -2586,9 +2510,7 @@ trm_request_sense(sc, dcb, srb)
if ((error = bus_dmamap_load(sc->sc_dmat, srb->dmap, if ((error = bus_dmamap_load(sc->sc_dmat, srb->dmap,
&xs->sense.scsi_sense, srb->buflen, NULL, &xs->sense.scsi_sense, srb->buflen, NULL,
BUS_DMA_READ|BUS_DMA_NOWAIT)) != 0) { BUS_DMA_READ|BUS_DMA_NOWAIT)) != 0) {
printf("trm_request_sense: can not bus_dmamap_load()\n"); return error;
xs->error = XS_DRIVER_STUFFUP;
return;
} }
bus_dmamap_sync(sc->sc_dmat, srb->dmap, 0, bus_dmamap_sync(sc->sc_dmat, srb->dmap, 0,
srb->buflen, BUS_DMASYNC_PREREAD); srb->buflen, BUS_DMASYNC_PREREAD);
@ -2605,6 +2527,7 @@ trm_request_sense(sc, dcb, srb)
* has more one SRB need to do. * has more one SRB need to do.
*/ */
trm_rewait_srb(dcb, srb); trm_rewait_srb(dcb, srb);
return 0;
} }
static void static void