- Don't use bitfields.

- Cosmetic changes.
- Shut down all HBAs "simultaneously", not individually.
- Don't bother grokking HA_ST_MORE. It causes problems.
- Other bits and pieces.
This commit is contained in:
ad 2000-02-24 18:47:55 +00:00
parent 3559e78ed2
commit 50062f0914
3 changed files with 338 additions and 380 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dpt.c,v 1.18 2000/02/12 19:12:54 thorpej Exp $ */
/* $NetBSD: dpt.c,v 1.19 2000/02/24 18:47:55 ad Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999, 2000 The NetBSD Foundation, Inc.
@ -54,22 +54,8 @@
* functioning of this software in any circumstances.
*/
/*
* Driver for DPT EATA SCSI adapters.
*
* TODO:
*
* o Need a front-end for (newer) ISA boards.
* o Handle older firmware better.
* o Find a bunch of different firmware EEPROMs and try them out.
* o Test with a bunch of different boards.
* o dpt_readcfg() should not be using CP_PIO_GETCFG.
* o An interface to userland applications.
* o Some sysctls or a utility (eg dptctl(8)) to control parameters.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dpt.c,v 1.18 2000/02/12 19:12:54 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: dpt.c,v 1.19 2000/02/24 18:47:55 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -119,6 +105,9 @@ static char *dpt_cname[] = {
NULL, "unknown adapter, please report using send-pr(1)",
};
TAILQ_HEAD(, dpt_softc) dpt_hba; /* tailq of HBA softc's */
void *dpt_sdh; /* shutdown hook */
/*
* Handle an interrupt from the HBA.
*/
@ -129,57 +118,42 @@ dpt_intr(xxx_sc)
struct dpt_softc *sc;
struct dpt_ccb *ccb;
struct eata_sp *sp;
static int moretimo;
int more;
volatile int junk;
sc = xxx_sc;
sp = sc->sc_statpack;
more = 0;
sp = sc->sc_stp;
#ifdef DEBUG
if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0)
if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0) {
printf("%s: spurious intr\n", sc->sc_dv.dv_xname);
return (1);
}
#endif
/* Don't get stalled by HA_ST_MORE */
if (moretimo < DPT_MORE_TIMEOUT / 100)
moretimo = 0;
for (;;) {
/*
* HBA might have interrupted while we were dealing with the
* last completed command, since we ACK before we deal; keep
* polling. If no interrupt is signalled, but the HBA has
* indicated that more data will be available soon, hang
* around.
* polling.
*/
if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0) {
if (more != 0 && moretimo++ < DPT_MORE_TIMEOUT / 100) {
DELAY(10);
continue;
}
if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0)
break;
}
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb, sc->sc_spoff,
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
sizeof(struct eata_sp), BUS_DMASYNC_POSTREAD);
/* Might have looped before HBA can reset HBA_AUX_INTR */
if (sp->sp_ccbid == -1) {
DELAY(50);
#ifdef DIAGNOSTIC
printf("%s: slow reset of HA_AUX_STATUS?",
sc->sc_dv.dv_xname);
#endif
if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0)
return (0);
#ifdef DIAGNOSTIC
printf("%s: was a slow reset of HA_AUX_STATUS",
sc->sc_dv.dv_xname);
#endif
printf("%s: no status\n", sc->sc_dv.dv_xname);
/* Re-sync DMA map */
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb,
sc->sc_spoff, sizeof(struct eata_sp),
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
sc->sc_stpoff, sizeof(struct eata_sp),
BUS_DMASYNC_POSTREAD);
}
@ -188,7 +162,7 @@ dpt_intr(xxx_sc)
/* Sync up DMA map and cache cmd status */
ccb = sc->sc_ccbs + sp->sp_ccbid;
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb,
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
CCB_OFF(sc, ccb), sizeof(struct dpt_ccb),
BUS_DMASYNC_POSTWRITE);
@ -199,9 +173,9 @@ dpt_intr(xxx_sc)
* Ack the interrupt and process the CCB. If this
* is a private CCB it's up to dpt_poll() to notice.
*/
junk = dpt_inb(sc, HA_STATUS);
sp->sp_ccbid = -1;
ccb->ccb_flg |= CCB_INTR;
more = dpt_inb(sc, HA_STATUS) & HA_ST_MORE;
if ((ccb->ccb_flg & CCB_PRIVATE) == 0)
dpt_done_ccb(sc, ccb);
} else {
@ -209,16 +183,12 @@ dpt_intr(xxx_sc)
sc->sc_dv.dv_xname, sp->sp_ccbid);
/* Ack the interrupt */
junk = dpt_inb(sc, HA_STATUS);
sp->sp_ccbid = -1;
more = dpt_inb(sc, HA_STATUS) & HA_ST_MORE;
}
/* Don't get stalled by HA_ST_MORE */
if (moretimo < DPT_MORE_TIMEOUT / 100)
moretimo = 0;
}
return (0);
return (1);
}
/*
@ -231,55 +201,56 @@ dpt_init(sc, intrstr)
const char *intrstr;
{
struct eata_inquiry_data *ei;
int i, j, error, rseg, mapsize;
int i, j, error, rseg, maxchannel, maxtarget;
bus_dma_segment_t seg;
struct eata_cfg *ec;
struct scsipi_link *link;
char model[16];
ec = &sc->sc_ec;
/* Allocate the CCB/status packet/scratch DMA map and load */
sc->sc_nccbs = min(be16toh(*(int16_t *)ec->ec_queuedepth), DPT_MAX_CCBS);
sc->sc_spoff = sc->sc_nccbs * sizeof(struct dpt_ccb);
sc->sc_scroff = sc->sc_spoff + sizeof(struct eata_sp);
sc->sc_scrlen = 256; /* XXX */
mapsize = sc->sc_nccbs * sizeof(struct dpt_ccb) + sc->sc_scrlen +
sizeof(struct eata_sp);
sc->sc_nccbs =
min(be16toh(*(int16_t *)ec->ec_queuedepth), DPT_MAX_CCBS);
sc->sc_stpoff = sc->sc_nccbs * sizeof(struct dpt_ccb);
sc->sc_scroff = sc->sc_stpoff + sizeof(struct eata_sp);
sc->sc_scrlen = DPT_SCRATCH_SIZE;
sc->sc_dmamapsize = sc->sc_nccbs * sizeof(struct dpt_ccb) +
sc->sc_scrlen + sizeof(struct eata_sp);
if ((error = bus_dmamem_alloc(sc->sc_dmat, mapsize, NBPG, 0,
if ((error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmamapsize, NBPG, 0,
&seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
printf("%s: unable to allocate CCBs, error = %d\n",
sc->sc_dv.dv_xname, error);
return;
}
if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, mapsize,
if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, sc->sc_dmamapsize,
(caddr_t *)&sc->sc_ccbs, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
printf("%s: unable to map CCBs, error = %d\n",
sc->sc_dv.dv_xname, error);
return;
}
if ((error = bus_dmamap_create(sc->sc_dmat, mapsize, mapsize, 1, 0,
BUS_DMA_NOWAIT, &sc->sc_dmamap_ccb)) != 0) {
if ((error = bus_dmamap_create(sc->sc_dmat, sc->sc_dmamapsize,
sc->sc_dmamapsize, 1, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
printf("%s: unable to create CCB DMA map, error = %d\n",
sc->sc_dv.dv_xname, error);
return;
}
if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_ccb,
sc->sc_ccbs, mapsize, NULL, BUS_DMA_NOWAIT)) != 0) {
if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
sc->sc_ccbs, sc->sc_dmamapsize, NULL, BUS_DMA_NOWAIT)) != 0) {
printf("%s: unable to load CCB DMA map, error = %d\n",
sc->sc_dv.dv_xname, error);
return;
}
sc->sc_statpack = (struct eata_sp *)((caddr_t)sc->sc_ccbs +
sc->sc_spoff);
sc->sc_sppa = sc->sc_dmamap_ccb->dm_segs[0].ds_addr + sc->sc_spoff;
sc->sc_stp = (struct eata_sp *)((caddr_t)sc->sc_ccbs + sc->sc_stpoff);
sc->sc_stppa = sc->sc_dmamap->dm_segs[0].ds_addr + sc->sc_stpoff;
sc->sc_scr = (caddr_t)sc->sc_ccbs + sc->sc_scroff;
sc->sc_scrpa = sc->sc_dmamap_ccb->dm_segs[0].ds_addr + sc->sc_scroff;
sc->sc_statpack->sp_ccbid = -1;
sc->sc_scrpa = sc->sc_dmamap->dm_segs[0].ds_addr + sc->sc_scroff;
sc->sc_stp->sp_ccbid = -1;
/* Initialize the CCBs */
TAILQ_INIT(&sc->sc_free_ccb);
@ -295,7 +266,10 @@ dpt_init(sc, intrstr)
}
/* Set shutdownhook before we start any device activity */
sc->sc_sdh = shutdownhook_establish(dpt_shutdown, sc);
if (dpt_sdh == NULL) {
TAILQ_INIT(&dpt_hba);
dpt_sdh = shutdownhook_establish(dpt_shutdown, NULL);
}
/* Get the page 0 inquiry data from the HBA */
dpt_hba_inquire(sc, &ei);
@ -325,38 +299,43 @@ dpt_init(sc, intrstr)
if (intrstr != NULL)
printf("%s: interrupting at %s\n", sc->sc_dv.dv_xname, intrstr);
printf("%s: %d queued commands, %d channel(s), adapter on ID(s)",
sc->sc_dv.dv_xname, sc->sc_nccbs, ec->ec_maxchannel + 1);
maxchannel = (ec->ec_feat3 & EC_F3_MAX_CHANNEL_MASK) >>
EC_F3_MAX_CHANNEL_SHIFT;
maxtarget = (ec->ec_feat3 & EC_F3_MAX_TARGET_MASK) >>
EC_F3_MAX_TARGET_SHIFT;
for (i = 0; i <= ec->ec_maxchannel; i++)
printf(" %d", ec->ec_hba[3 - i]);
printf("%s: %d queued commands, %d channel(s), adapter on ID(s)",
sc->sc_dv.dv_xname, sc->sc_nccbs, maxchannel + 1);
for (i = 0; i <= maxchannel; i++) {
sc->sc_hbaid[i] = ec->ec_hba[3 - i];
printf(" %d", sc->sc_hbaid[i]);
}
printf("\n");
/* Reset the SCSI bus */
if (dpt_cmd(sc, NULL, 0, CP_IMMEDIATE, CPI_BUS_RESET))
panic("%s: dpt_cmd failed", sc->sc_dv.dv_xname);
DELAY(20000);
/* Fill in the adapter, each link and attach in turn */
sc->sc_adapter.scsipi_cmd = dpt_scsi_cmd;
sc->sc_adapter.scsipi_minphys = dpt_minphys;
for (i = 0; i <= ec->ec_maxchannel; i++) {
struct scsipi_link *link;
sc->sc_hbaid[i] = ec->ec_hba[3 - i];
for (i = 0; i <= maxchannel; i++) {
link = &sc->sc_link[i];
link->scsipi_scsi.channel = i;
link->scsipi_scsi.adapter_target = sc->sc_hbaid[i];
link->scsipi_scsi.max_lun = ec->ec_maxlun;
link->scsipi_scsi.max_target = ec->ec_maxtarget;
link->scsipi_scsi.max_target = maxtarget;
link->type = BUS_SCSI;
link->device = &dpt_dev;
link->adapter = &sc->sc_adapter;
link->adapter_softc = sc;
link->openings = sc->sc_nccbs;
link->openings = sc->sc_nccbs; /* XXX */
config_found(&sc->sc_dv, link, scsiprint);
}
TAILQ_INSERT_TAIL(&dpt_hba, sc, sc_chain);
}
/*
@ -369,9 +348,12 @@ dpt_shutdown(xxx_sc)
{
struct dpt_softc *sc;
sc = xxx_sc;
printf("shutting down %s...", sc->sc_dv.dv_xname);
dpt_cmd(sc, NULL, 0, CP_IMMEDIATE, CPI_POWEROFF_WARN);
printf("shutting down DPT HBAs...");
for (sc = TAILQ_FIRST(&dpt_hba); sc != NULL;
sc = TAILQ_NEXT(sc, sc_chain))
dpt_cmd(sc, NULL, 0, CP_IMMEDIATE, CPI_POWEROFF_WARN);
DELAY(5000*1000);
printf(" done\n");
}
@ -415,8 +397,8 @@ dpt_cmd(sc, cp, addr, eatacmd, icmd)
dpt_outb(sc, HA_ICMD, icmd);
}
dpt_outb(sc, HA_COMMAND, eatacmd);
return (0);
dpt_outb(sc, HA_COMMAND, eatacmd);
return (0);
}
/*
@ -424,17 +406,17 @@ dpt_cmd(sc, cp, addr, eatacmd, icmd)
*/
int
dpt_wait(sc, mask, state, ms)
struct dpt_softc *sc;
u_int8_t mask, state;
int ms;
struct dpt_softc *sc;
u_int8_t mask, state;
int ms;
{
for (ms *= 10; ms; ms--) {
if ((dpt_inb(sc, HA_STATUS) & mask) == state)
return (0);
DELAY(100);
}
return (-1);
for (ms *= 10; ms; ms--) {
if ((dpt_inb(sc, HA_STATUS) & mask) == state)
return (0);
DELAY(100);
}
return (-1);
}
/*
@ -446,8 +428,8 @@ dpt_wait(sc, mask, state, ms)
*/
int
dpt_poll(sc, ccb)
struct dpt_softc *sc;
struct dpt_ccb *ccb;
struct dpt_softc *sc;
struct dpt_ccb *ccb;
{
int i;
@ -457,18 +439,18 @@ dpt_poll(sc, ccb)
#endif
if ((ccb->ccb_flg & CCB_INTR) != 0)
return (0);
return (0);
for (i = ccb->ccb_timeout * 20; i; i--) {
if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) != 0) {
dpt_intr(sc);
if ((ccb->ccb_flg & CCB_INTR) != 0)
for (i = ccb->ccb_timeout * 20; i; i--) {
if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) != 0) {
dpt_intr(sc);
if ((ccb->ccb_flg & CCB_INTR) != 0)
return (0);
}
DELAY(50);
}
}
return (-1);
return (-1);
}
/*
@ -486,7 +468,7 @@ dpt_readcfg(sc)
/* Older firmware may puke if we talk to it too soon after reset */
dpt_outb(sc, HA_COMMAND, CP_RESET);
DELAY(750000);
DELAY(750000);
for (i = 1000; i; i--) {
if ((dpt_inb(sc, HA_STATUS) & HA_ST_READY) != 0)
@ -501,18 +483,18 @@ dpt_readcfg(sc)
}
while((((stat = dpt_inb(sc, HA_STATUS))
!= (HA_ST_READY|HA_ST_SEEK_COMPLETE))
&& (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR))
&& (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR|HA_ST_DRQ)))
|| (dpt_wait(sc, HA_ST_BUSY, 0, 2000))) {
/* RAID drives still spinning up? */
if((dpt_inb(sc, HA_ERROR) != 'D')
|| (dpt_inb(sc, HA_ERROR + 1) != 'P')
|| (dpt_inb(sc, HA_ERROR + 2) != 'T')) {
printf("%s: HBA not ready\n", sc->sc_dv.dv_xname);
return (-1);
!= (HA_ST_READY|HA_ST_SEEK_COMPLETE))
&& (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR))
&& (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR|HA_ST_DRQ)))
&& dpt_wait(sc, HA_ST_BUSY, 0, 2000)) {
/* RAID drives still spinning up? */
if((dpt_inb(sc, HA_ERROR) != 'D')
|| (dpt_inb(sc, HA_ERROR + 1) != 'P')
|| (dpt_inb(sc, HA_ERROR + 2) != 'T')) {
printf("%s: HBA not ready\n", sc->sc_dv.dv_xname);
return (-1);
}
}
}
/*
* Issue the read-config command and wait for the data to appear.
@ -535,45 +517,45 @@ dpt_readcfg(sc)
while (i--)
*p++ = dpt_inw(sc, HA_DATA);
if ((i = ec->ec_cfglen) > (sizeof(struct eata_cfg)
- (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
- sizeof(ec->ec_cfglen)))
i = sizeof(struct eata_cfg)
- (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
- sizeof(ec->ec_cfglen);
if ((i = ec->ec_cfglen) > (sizeof(struct eata_cfg)
- (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
- sizeof(ec->ec_cfglen)))
i = sizeof(struct eata_cfg)
- (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
- sizeof(ec->ec_cfglen);
j = i + (int)(&(((struct eata_cfg *)0L)->ec_cfglen)) +
sizeof(ec->ec_cfglen);
i >>= 1;
j = i + (int)(&(((struct eata_cfg *)0L)->ec_cfglen)) +
sizeof(ec->ec_cfglen);
i >>= 1;
while (i--)
*p++ = dpt_inw(sc, HA_DATA);
/* Flush until we have read 512 bytes. */
i = (512 - j + 1) >> 1;
*p++ = dpt_inw(sc, HA_DATA);
/* Flush until we have read 512 bytes. */
i = (512 - j + 1) >> 1;
while (i--)
dpt_inw(sc, HA_DATA);
/* Defaults for older Firmware */
/* Defaults for older Firmware */
if (p <= (u_short *)&ec->ec_hba[DPT_MAX_CHANNELS - 1])
ec->ec_hba[DPT_MAX_CHANNELS - 1] = 7;
if ((dpt_inb(sc, HA_STATUS) & HA_ST_ERROR) != 0) {
printf("%s: HBA error\n", sc->sc_dv.dv_xname);
return (-1);
}
if ((dpt_inb(sc, HA_STATUS) & HA_ST_ERROR) != 0) {
printf("%s: HBA error\n", sc->sc_dv.dv_xname);
return (-1);
}
if (memcmp(ec->ec_eatasig, "EATA", 4) != 0) {
printf("%s: EATA signature mismatch\n", sc->sc_dv.dv_xname);
return (-1);
}
if (!ec->ec_hbavalid) {
printf("%s: ec_hba field invalid\n", sc->sc_dv.dv_xname);
if ((ec->ec_feat0 & EC_F0_HBA_VALID) == 0) {
printf("%s: ec_hba field invalid\n", sc->sc_dv.dv_xname);
return (-1);
}
if (!ec->ec_dmasupported) {
if ((ec->ec_feat0 & EC_F0_DMA_SUPPORTED) == 0) {
printf("%s: DMA not supported\n", sc->sc_dv.dv_xname);
return (-1);
}
@ -636,7 +618,7 @@ dpt_init_ccb(sc, ccb)
}
ccb->ccb_flg = 0;
ccb->ccb_ccbpa = sc->sc_dmamap_ccb->dm_segs[0].ds_addr +
ccb->ccb_ccbpa = sc->sc_dmamap->dm_segs[0].ds_addr +
CCB_OFF(sc, ccb);
return (0);
}
@ -684,19 +666,17 @@ dpt_alloc_ccb(sc, flg)
s = splbio();
for (;;) {
ccb = TAILQ_FIRST(&sc->sc_free_ccb);
if (ccb) {
if ((ccb = TAILQ_FIRST(&sc->sc_free_ccb)) != NULL) {
TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_chain);
break;
}
if ((flg & XS_CTL_NOSLEEP) != 0) {
splx(s);
return (NULL);
ccb = NULL;
break;
}
tsleep(&sc->sc_free_ccb, PRIBIO, "dptccb", 0);
}
ccb->ccb_flg |= CCB_ALLOC;
splx(s);
return (ccb);
}
@ -724,7 +704,7 @@ dpt_done_ccb(sc, ccb)
* If we were a data transfer, unload the map that described the
* data buffer.
*/
if (xs->datalen) {
if (xs->datalen != 0) {
bus_dmamap_sync(dmat, ccb->ccb_dmamap_xfer, 0,
ccb->ccb_dmamap_xfer->dm_mapsize,
(xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
@ -732,24 +712,13 @@ dpt_done_ccb(sc, ccb)
bus_dmamap_unload(dmat, ccb->ccb_dmamap_xfer);
}
/*
* Otherwise, put the results of the operation into the xfer and
* call whoever started it.
*/
#ifdef DIAGNOSTIC
if ((ccb->ccb_flg & CCB_ALLOC) == 0) {
panic("%s: done ccb not allocated!\n", sc->sc_dv.dv_xname);
return;
}
#endif
if (xs->error == XS_NOERROR) {
if (ccb->ccb_hba_status != HA_NO_ERROR) {
if (ccb->ccb_hba_status != SP_HBA_NO_ERROR) {
switch (ccb->ccb_hba_status) {
case HA_ERROR_SEL_TO:
case SP_HBA_ERROR_SEL_TO:
xs->error = XS_SELTIMEOUT;
break;
case HA_ERROR_RESET:
case SP_HBA_ERROR_RESET:
xs->error = XS_RESET;
break;
default: /* Other scsi protocol messes */
@ -839,7 +808,10 @@ dpt_scsi_cmd(xs)
return (COMPLETE);
}
/* XXX we can't reset devices just yet */
/*
* XXX we can't reset devices just yet. Apparently some
* older firmware revisions don't even support it.
*/
if ((flags & XS_CTL_RESET) != 0) {
xs->error = XS_DRIVER_STUFFUP;
return (COMPLETE);
@ -897,39 +869,42 @@ dpt_scsi_cmd(xs)
ccb->ccb_timeout = xs->timeout;
cp = &ccb->ccb_eata_cp;
memcpy(&cp->cp_scsi_cmd, xs->cmd, xs->cmdlen);
memcpy(&cp->cp_cdb_cmd, xs->cmd, xs->cmdlen);
cp->cp_ccbid = ccb->ccb_id;
cp->cp_id = sc_link->scsipi_scsi.target;
cp->cp_lun = sc_link->scsipi_scsi.lun;
cp->cp_channel = sc_link->scsipi_scsi.channel;
cp->cp_senselen = sizeof(ccb->ccb_sense);
cp->cp_stataddr = htobe32(sc->sc_sppa);
cp->cp_dispri = 1;
cp->cp_identify = 1;
cp->cp_autosense = 1;
cp->cp_datain = ((flags & XS_CTL_DATA_IN) != 0);
cp->cp_dataout = ((flags & XS_CTL_DATA_OUT) != 0);
cp->cp_interpret = (sc->sc_hbaid[sc_link->scsipi_scsi.channel] ==
sc_link->scsipi_scsi.target);
cp->cp_stataddr = htobe32(sc->sc_stppa);
cp->cp_ctl0 = CP_C0_AUTO_SENSE;
cp->cp_ctl1 = 0;
cp->cp_ctl2 = 0;
cp->cp_ctl3 = sc_link->scsipi_scsi.target << CP_C3_ID_SHIFT;
cp->cp_ctl3 |= sc_link->scsipi_scsi.channel << CP_C3_CHANNEL_SHIFT;
cp->cp_ctl4 = sc_link->scsipi_scsi.lun << CP_C4_LUN_SHIFT;
cp->cp_ctl4 |= CP_C4_DIS_PRI | CP_C4_IDENTIFY;
if ((flags & XS_CTL_DATA_IN) != 0)
cp->cp_ctl0 |= CP_C0_DATA_IN;
if ((flags & XS_CTL_DATA_OUT) != 0)
cp->cp_ctl0 |= CP_C0_DATA_OUT;
if (sc->sc_hbaid[sc_link->scsipi_scsi.channel] ==
sc_link->scsipi_scsi.target)
cp->cp_ctl0 |= CP_C0_INTERPRET;
/* Synchronous xfers musn't write-back through the cache */
if (xs->bp != NULL && (xs->bp->b_flags & (B_ASYNC | B_READ)) == 0)
cp->cp_nocache = 1;
else
cp->cp_nocache = 0;
cp->cp_ctl2 |= CP_C2_NO_CACHE;
cp->cp_senseaddr = htobe32(sc->sc_dmamap_ccb->dm_segs[0].ds_addr +
cp->cp_senseaddr = htobe32(sc->sc_dmamap->dm_segs[0].ds_addr +
CCB_OFF(sc, ccb) + offsetof(struct dpt_ccb, ccb_sense));
if (xs->datalen != 0) {
xfer = ccb->ccb_dmamap_xfer;
#ifdef TFS
#ifdef TFS
if ((flags & XS_CTL_DATA_UIO) != 0) {
error = bus_dmamap_load_uio(dmat, xfer,
(struct uio *)xs->data, (flags & XS_CTL_NOSLEEP) ?
BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
} else
#endif /*TFS */
#endif /* TFS */
{
error = bus_dmamap_load(dmat, xfer, xs->data,
xs->datalen, NULL, (flags & XS_CTL_NOSLEEP) ?
@ -956,7 +931,6 @@ dpt_scsi_cmd(xs)
if (xfer->dm_nsegs == 1) {
cp->cp_dataaddr = htobe32(xfer->dm_segs[0].ds_addr);
cp->cp_datalen = htobe32(xfer->dm_segs[0].ds_len);
cp->cp_scatter = 0;
} else {
/*
* Load the hardware scatter/gather map with the
@ -968,21 +942,20 @@ dpt_scsi_cmd(xs)
sg->sg_len = htobe32(xfer->dm_segs[i].ds_len);
}
cp->cp_dataaddr = htobe32(CCB_OFF(sc, ccb) +
sc->sc_dmamap_ccb->dm_segs[0].ds_addr +
sc->sc_dmamap->dm_segs[0].ds_addr +
offsetof(struct dpt_ccb, ccb_sg));
cp->cp_datalen = htobe32(i * sizeof(struct eata_sg));
cp->cp_scatter = 1;
cp->cp_ctl0 |= CP_C0_SCATTER;
}
} else {
cp->cp_dataaddr = 0;
cp->cp_datalen = 0;
cp->cp_scatter = 0;
}
/* Sync up CCB and status packet */
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb, CCB_OFF(sc, ccb),
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
sizeof(struct dpt_ccb), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb, sc->sc_spoff,
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
sizeof(struct eata_sp), BUS_DMASYNC_PREREAD);
/*
@ -1031,7 +1004,7 @@ dpt_timeout(arg)
ccb = arg;
xs = ccb->ccb_xs;
sc_link = xs->sc_link;
sc = sc_link->adapter_softc;
sc = sc_link->adapter_softc;
scsi_print_addr(sc_link);
printf("timed out (status:%02x aux status:%02x)",
@ -1053,38 +1026,12 @@ dpt_timeout(arg)
/* Start the abort */
if (dpt_cmd(sc, &ccb->ccb_eata_cp, ccb->ccb_ccbpa,
CP_IMMEDIATE, CPI_SPEC_ABORT))
printf("%s: dpt_cmd failed\n", sc->sc_dv.dv_xname);
printf("%s: dpt_cmd failed\n", sc->sc_dv.dv_xname);
}
splx(s);
}
#ifdef DEBUG
/*
* Dump the contents of an EATA status packet.
*/
void
dpt_dump_sp(sp)
struct eata_sp *sp;
{
int i;
printf("\thba_status\t%02x\n", sp->sp_hba_status);
printf("\tscsi_status\t%02x\n", sp->sp_scsi_status);
printf("\tinv_residue\t%d\n", sp->sp_inv_residue);
printf("\tccbid\t\t%d\n", sp->sp_ccbid);
printf("\tid_message\t%d\n", sp->sp_id_message);
printf("\tque_message\t%d\n", sp->sp_que_message);
printf("\ttag_message\t%d\n", sp->sp_tag_message);
printf("\tmessages\t");
for (i = 0; i < 9; i++)
printf("%d ", sp->sp_messages[i]);
printf("\n");
}
#endif /* DEBUG */
/*
* Get inquiry data from the adapter.
*/
@ -1110,34 +1057,28 @@ dpt_hba_inquire(sc, ei)
/* Put all the arguments into the CCB */
cp = &ccb->ccb_eata_cp;
cp->cp_ccbid = ccb->ccb_id;
cp->cp_id = sc->sc_hbaid[0];
cp->cp_lun = 0;
cp->cp_channel = 0;
cp->cp_senselen = sizeof(ccb->ccb_sense);
cp->cp_stataddr = htobe32(sc->sc_sppa);
cp->cp_dispri = 1;
cp->cp_identify = 1;
cp->cp_autosense = 0;
cp->cp_interpret = 1;
cp->cp_nocache = 0;
cp->cp_datain = 1;
cp->cp_dataout = 0;
cp->cp_senseaddr = 0;
cp->cp_senseaddr = 0;
cp->cp_stataddr = htobe32(sc->sc_stppa);
cp->cp_dataaddr = htobe32(sc->sc_scrpa);
cp->cp_datalen = htobe32(sizeof(struct eata_inquiry_data));
cp->cp_scatter = 0;
cp->cp_ctl0 = CP_C0_DATA_IN | CP_C0_INTERPRET;
cp->cp_ctl1 = 0;
cp->cp_ctl2 = 0;
cp->cp_ctl3 = sc->sc_hbaid[0] << CP_C3_ID_SHIFT;
cp->cp_ctl4 = CP_C4_DIS_PRI | CP_C4_IDENTIFY;
/* Put together the SCSI inquiry command */
memset(&cp->cp_scsi_cmd, 0, 12); /* XXX */
cp->cp_scsi_cmd = INQUIRY;
cp->cp_len = sizeof(struct eata_inquiry_data);
memset(&cp->cp_cdb_cmd, 0, 12); /* XXX */
cp->cp_cdb_cmd = INQUIRY;
cp->cp_cdb_len = sizeof(struct eata_inquiry_data);
/* Sync up CCB, status packet and scratch area */
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb, CCB_OFF(sc, ccb),
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
sizeof(struct dpt_ccb), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb, sc->sc_spoff,
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
sizeof(struct eata_sp), BUS_DMASYNC_PREREAD);
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb, sc->sc_scroff,
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_scroff,
sizeof(struct eata_inquiry_data), BUS_DMASYNC_PREREAD);
/* Start the command and poll on completion */
@ -1147,14 +1088,14 @@ dpt_hba_inquire(sc, ei)
if (dpt_poll(sc, ccb))
panic("%s: inquiry timed out", sc->sc_dv.dv_xname);
if (ccb->ccb_hba_status != HA_NO_ERROR ||
if (ccb->ccb_hba_status != SP_HBA_NO_ERROR ||
ccb->ccb_scsi_status != SCSI_OK)
panic("%s: inquiry failed (hba:%02x scsi:%02x)",
sc->sc_dv.dv_xname, ccb->ccb_hba_status,
ccb->ccb_scsi_status);
/* Sync up the DMA map and free CCB, returning */
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ccb, sc->sc_scroff,
bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_scroff,
sizeof(struct eata_inquiry_data), BUS_DMASYNC_POSTREAD);
dpt_free_ccb(sc, ccb);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: dptreg.h,v 1.6 2000/01/18 16:50:38 ad Exp $ */
/* $NetBSD: dptreg.h,v 1.7 2000/02/24 18:47:55 ad Exp $ */
/*
* Copyright (c) 1999 Andy Doran <ad@NetBSD.org>
@ -27,8 +27,8 @@
*
*/
#ifndef _IC_DPTREG_H_
#define _IC_DPTREG_H_ 1
#ifndef _IC_DPTREG_H_
#define _IC_DPTREG_H_ 1
/* Hardware limits */
#define DPT_MAX_TARGETS 16
@ -41,6 +41,7 @@
#define DPT_SG_SIZE 64
#define DPT_ABORT_TIMEOUT 2000 /* milliseconds */
#define DPT_MORE_TIMEOUT 1000 /* microseconds */
#define DPT_SCRATCH_SIZE 256 /* bytes */
#ifdef _KERNEL
@ -111,64 +112,63 @@
* Structure of an EATA command packet.
*/
struct eata_cp {
u_int8_t cp_scsireset :1; /* cause a bus reset */
u_int8_t cp_hbainit :1; /* cause HBA to reinitialize */
u_int8_t cp_autosense :1; /* auto request sense on err */
u_int8_t cp_scatter :1; /* doing SG I/O */
u_int8_t cp_quick :1; /* return no status packet */
u_int8_t cp_interpret :1; /* HBA interprets SCSI CDB */
u_int8_t cp_dataout :1; /* data out phase */
u_int8_t cp_datain :1; /* data in phase */
u_int8_t cp_senselen; /* request sense length */
u_int8_t cp_unused0[3]; /* unused */
u_int8_t cp_tophys :1; /* send to RAID component */
u_int8_t cp_unused1 :7; /* unused */
u_int8_t cp_physunit :1; /* phys unit on mirrored pair */
u_int8_t cp_noat :1; /* no address translation */
u_int8_t cp_nocache :1; /* no HBA caching */
u_int8_t cp_unused2 :5; /* unused */
u_int8_t cp_id :5; /* SCSI device id of target */
u_int8_t cp_channel :3; /* SCSI channel id */
u_int8_t cp_lun :3; /* SCSI LUN id */
u_int8_t cp_unused3 :2; /* unused */
u_int8_t cp_luntar :1; /* CP is for target ROUTINE */
u_int8_t cp_dispri :1; /* give disconnect privilege */
u_int8_t cp_identify :1; /* always true */
u_int8_t cp_msg[3]; /* message bytes 0-3 */
/* Partial SCSI CDB ref */
u_int8_t cp_scsi_cmd;
u_int8_t cp_extent :1;
u_int8_t cp_bytchk :1;
u_int8_t cp_reladr :1;
u_int8_t cp_cmplst :1;
u_int8_t cp_fmtdata :1;
u_int8_t cp_cdblun :3;
u_int8_t cp_page;
u_int8_t cp_unused4;
u_int8_t cp_len;
u_int8_t cp_link :1;
u_int8_t cp_flag :1;
u_int8_t cp_unused5 :4;
u_int8_t cp_vendor :2;
u_int8_t cp_cdbmore[6];
u_int32_t cp_datalen; /* length in bytes of data/SG list */
u_int32_t cp_ccbid; /* ID of software CCB */
u_int32_t cp_dataaddr; /* address of data/SG list */
u_int32_t cp_stataddr; /* addr for status packet */
u_int32_t cp_senseaddr; /* addr of req. sense (err only) */
u_int8_t cp_ctl0; /* Control flags 0 */
u_int8_t cp_senselen; /* Request sense length */
u_int8_t cp_unused0[3]; /* Unused */
u_int8_t cp_ctl1; /* Control flags 1 */
u_int8_t cp_ctl2; /* Control flags 2 */
u_int8_t cp_ctl3; /* Control flags 3 */
u_int8_t cp_ctl4; /* Control flags 4 */
u_int8_t cp_msg[3]; /* Message bytes 0-3 */
u_int8_t cp_cdb_cmd; /* SCSI CDB */
u_int8_t cp_cdb_more0[3]; /* SCSI CDB */
u_int8_t cp_cdb_len; /* SCSI CDB */
u_int8_t cp_cdb_more1[7]; /* SCSI CDB */
u_int32_t cp_datalen; /* Bytes of data/SG list */
u_int32_t cp_ccbid; /* ID of software CCB */
u_int32_t cp_dataaddr; /* Addr of data/SG list */
u_int32_t cp_stataddr; /* Addr of status packet */
u_int32_t cp_senseaddr; /* Addr of req. sense */
};
#define CP_C0_SCSI_RESET 0x01 /* Cause a bus reset */
#define CP_C0_HBA_INIT 0x02 /* Reinitialize HBA */
#define CP_C0_AUTO_SENSE 0x04 /* Auto request sense on error */
#define CP_C0_SCATTER 0x08 /* Do scatter/gather I/O */
#define CP_C0_QUICK 0x10 /* Return no status packet */
#define CP_C0_INTERPRET 0x20 /* HBA interprets SCSI CDB */
#define CP_C0_DATA_OUT 0x40 /* Data out phase */
#define CP_C0_DATA_IN 0x80 /* Data in phase */
#define CP_C1_TO_PHYS 0x01 /* Send to RAID component */
#define CP_C1_RESERVED 0xfe
#define CP_C2_PHYS_UNIT 0x01 /* Physical unit on mirrored pair */
#define CP_C2_NO_AT 0x02 /* No address translation */
#define CP_C2_NO_CACHE 0x04 /* No HBA caching */
#define CP_C2_RESERVED 0xf8
#define CP_C3_ID_MASK 0x1f /* Target ID */
#define CP_C3_ID_SHIFT 0
#define CP_C3_CHANNEL_MASK 0xe0 /* Target channel */
#define CP_C3_CHANNEL_SHIFT 5
#define CP_C4_LUN_MASK 0x07 /* Target LUN */
#define CP_C4_LUN_SHIFT 0
#define CP_C4_RESERVED 0x18
#define CP_C4_LUN_TAR 0x20 /* CP is for target ROUTINE */
#define CP_C4_DIS_PRI 0x40 /* Give disconnect privilege */
#define CP_C4_IDENTIFY 0x80 /* Always true */
/*
* EATA status packet as returned by controller upon command completion. It
* contains status, message info and a handle on the initiating CCB.
*/
struct eata_sp {
u_int8_t sp_hba_status; /* host adapter status */
u_int8_t sp_hba_status; /* Host adapter status */
u_int8_t sp_scsi_status; /* SCSI bus status */
u_int8_t sp_reserved[2]; /* reserved */
u_int32_t sp_inv_residue; /* bytes not transfered */
u_int8_t sp_reserved[2]; /* Reserved */
u_int32_t sp_inv_residue; /* Bytes not transfered */
u_int32_t sp_ccbid; /* ID of software CCB */
u_int8_t sp_id_message;
u_int8_t sp_que_message;
@ -179,29 +179,29 @@ struct eata_sp {
/*
* HBA status as returned by status packet. Bit 7 signals end of command.
*/
#define HA_NO_ERROR 0x00 /* No error on command */
#define HA_ERROR_SEL_TO 0x01 /* Device selection timeout */
#define HA_ERROR_CMD_TO 0x02 /* Device command timeout */
#define HA_ERROR_RESET 0x03 /* SCSI bus was reset */
#define HA_INIT_POWERUP 0x04 /* Initial controller power up */
#define HA_UNX_BUSPHASE 0x05 /* Unexpected bus phase */
#define HA_UNX_BUS_FREE 0x06 /* Unexpected bus free */
#define HA_BUS_PARITY 0x07 /* SCSI bus parity error */
#define HA_SCSI_HUNG 0x08 /* SCSI bus hung */
#define HA_UNX_MSGRJCT 0x09 /* Unexpected message reject */
#define HA_RESET_STUCK 0x0A /* SCSI bus reset stuck */
#define HA_RSENSE_FAIL 0x0B /* Auto-request sense failed */
#define HA_PARITY 0x0C /* HBA memory parity error */
#define HA_ABORT_NA 0x0D /* CP aborted - not on bus */
#define HA_ABORTED 0x0E /* CP aborted - was on bus */
#define HA_RESET_NA 0x0F /* CP reset - not on bus */
#define HA_RESET 0x10 /* CP reset - was on bus */
#define HA_ECC 0x11 /* HBA memory ECC error */
#define HA_PCI_PARITY 0x12 /* PCI parity error */
#define HA_PCI_MASTER 0x13 /* PCI master abort */
#define HA_PCI_TARGET 0x14 /* PCI target abort */
#define HA_PCI_SIGNAL_TARGET 0x15 /* PCI signalled target abort */
#define HA_ABORT 0x20 /* Software abort (too many retries) */
#define SP_HBA_NO_ERROR 0x00 /* No error on command */
#define SP_HBA_ERROR_SEL_TO 0x01 /* Device selection timeout */
#define SP_HBA_ERROR_CMD_TO 0x02 /* Device command timeout */
#define SP_HBA_ERROR_RESET 0x03 /* SCSI bus was reset */
#define SP_HBA_INIT_POWERUP 0x04 /* Initial controller power up */
#define SP_HBA_UNX_BUSPHASE 0x05 /* Unexpected bus phase */
#define SP_HBA_UNX_BUS_FREE 0x06 /* Unexpected bus free */
#define SP_HBA_BUS_PARITY 0x07 /* SCSI bus parity error */
#define SP_HBA_SCSI_HUNG 0x08 /* SCSI bus hung */
#define SP_HBA_UNX_MSGRJCT 0x09 /* Unexpected message reject */
#define SP_HBA_RESET_STUCK 0x0a /* SCSI bus reset stuck */
#define SP_HBA_RSENSE_FAIL 0x0b /* Auto-request sense failed */
#define SP_HBA_PARITY 0x0c /* HBA memory parity error */
#define SP_HBA_ABORT_NA 0x0d /* CP aborted - not on bus */
#define SP_HBA_ABORTED 0x0e /* CP aborted - was on bus */
#define SP_HBA_RESET_NA 0x0f /* CP reset - not on bus */
#define SP_HBA_RESET 0x10 /* CP reset - was on bus */
#define SP_HBA_ECC 0x11 /* HBA memory ECC error */
#define SP_HBA_PCI_PARITY 0x12 /* PCI parity error */
#define SP_HBA_PCI_MASTER 0x13 /* PCI master abort */
#define SP_HBA_PCI_TARGET 0x14 /* PCI target abort */
#define SP_HBA_PCI_SIG_TARGET 0x15 /* PCI signalled target abort */
#define SP_HBA_ABORT 0x20 /* Software abort (too many retries) */
/*
* Scatter-gather list element.
@ -212,54 +212,72 @@ struct eata_sg {
};
/*
* EATA configuration data as returned by HBA. XXX this is bogus, some fields
* don't *seem* to be filled on my SmartCache III. Also, it doesn't sync up
* with the structure FreeBSD uses. [ad]
* EATA configuration data as returned by HBA. XXX this is bogus - it
* doesn't sync up with the structure FreeBSD uses. [ad]
*/
struct eata_cfg {
u_int8_t ec_devtype;
u_int8_t ec_pagecode;
u_int8_t ec_reserved0;
u_int8_t ec_cfglen; /* Length in bytes after this field */
u_int8_t ec_eatasig[4]; /* EATA signature */
u_int8_t ec_eataversion; /* EATA version number */
u_int8_t ec_overlapcmds : 1; /* Overlapped cmds supported */
u_int8_t ec_targetmode : 1; /* Target mode supported */
u_int8_t ec_trunnotrec : 1; /* Truncate cmd not supported */
u_int8_t ec_moresupported:1; /* More cmd supported */
u_int8_t ec_dmasupported : 1; /* DMA mode supported */
u_int8_t ec_dmanumvalid : 1; /* DMA channel field is valid */
u_int8_t ec_atadev : 1; /* This is an ATA device */
u_int8_t ec_hbavalid : 1; /* HBA field is valid */
u_int8_t ec_padlength[2]; /* Pad bytes for PIO cmds */
u_int8_t ec_hba[4]; /* Host adapter SCSI IDs */
u_int8_t ec_cplen[4]; /* Command packet length */
u_int8_t ec_splen[4]; /* Status packet length */
u_int8_t ec_queuedepth[2]; /* Controller queue depth */
u_int8_t ec_reserved1[2];
u_int8_t ec_sglen[2]; /* Maximum scatter gather list size */
u_int8_t ec_irqnum : 4; /* IRQ number */
u_int8_t ec_irqtrigger : 1; /* IRQ trigger: 0 = edge, 1 = level */
u_int8_t ec_secondary : 1; /* Controller not at address 0x170 */
u_int8_t ec_dmanum : 2; /* DMA channel index for ISA */
u_int8_t ec_irq; /* IRQ address */
u_int8_t ec_iodisable : 1; /* ISA I/O address disabled */
u_int8_t ec_forceaddr : 1; /* PCI forced to an EISA/ISA addr */
u_int8_t ec_sg64k : 1; /* 64K of SG space */
u_int8_t ec_sgunaligned : 1; /* Can do unaligned SG, otherwise 4 */
u_int8_t ec_reserved2 : 4; /* Reserved */
u_int8_t ec_maxtarget : 5; /* Maximun SCSI target ID supported */
u_int8_t ec_maxchannel : 3; /* Maximun channel number supported */
u_int8_t ec_maxlun; /* Maximum LUN supported */
u_int8_t ec_reserved3 : 3; /* Reserved field */
u_int8_t ec_autoterm : 1; /* Support auto term (low byte) */
u_int8_t ec_pcim1 : 1; /* PCI M1 chipset */
u_int8_t ec_bogusraidid : 1; /* Raid ID may be questionable */
u_int8_t ec_pci : 1; /* PCI adapter */
u_int8_t ec_eisa : 1; /* EISA adapter */
u_int8_t ec_raidnum; /* RAID host adapter humber */
u_int8_t ec_devtype;
u_int8_t ec_pagecode;
u_int8_t ec_reserved0;
u_int8_t ec_cfglen; /* Length in bytes past here */
u_int8_t ec_eatasig[4]; /* EATA signature */
u_int8_t ec_eataversion; /* EATA version number */
u_int8_t ec_feat0; /* First feature byte */
u_int8_t ec_padlength[2]; /* Pad bytes for PIO cmds */
u_int8_t ec_hba[4]; /* Host adapter SCSI IDs */
u_int8_t ec_cplen[4]; /* Command packet length */
u_int8_t ec_splen[4]; /* Status packet length */
u_int8_t ec_queuedepth[2]; /* Controller queue depth */
u_int8_t ec_reserved1[2];
u_int8_t ec_sglen[2]; /* Maximum s/g list size */
u_int8_t ec_feat1; /* 2nd feature byte */
u_int8_t ec_irq; /* IRQ address */
u_int8_t ec_feat2; /* 3rd feature byte */
u_int8_t ec_feat3; /* 4th feature byte */
u_int8_t ec_maxlun; /* Maximum LUN supported */
u_int8_t ec_feat4; /* 5th feature byte */
u_int8_t ec_raidnum; /* RAID host adapter humber */
};
#define EC_F0_OVERLAP_CMDS 0x01 /* Overlapped cmds supported */
#define EC_F0_TARGET_MODE 0x02 /* Target mode supported */
#define EC_F0_TRUNC_NOT_REC 0x04 /* Truncate cmd not supported */
#define EC_F0_MORE_SUPPORTED 0x08 /* More cmd supported */
#define EC_F0_DMA_SUPPORTED 0x10 /* DMA mode supported */
#define EC_F0_DMA_NUM_VALID 0x20 /* DMA channel field is valid */
#define EC_F0_ATA_DEV 0x40 /* This is an ATA device */
#define EC_F0_HBA_VALID 0x80 /* HBA field is valid */
#define EC_F1_IRQ_NUM_MASK 0x0f /* IRQ number mask */
#define EC_F1_IRQ_NUM_SHIFT 0
#define EC_F1_IRQ_TRIGGER 0x10 /* IRQ trigger: 0 = edge, 1 = level */
#define EC_F1_SECONDARY 0x20 /* Controller not at address 0x170 */
#define EC_F1_DMA_NUM_MASK 0xc0 /* DMA channel *index* for ISA */
#define EC_F1_DMA_NUM_SHIFT 6
#define EC_F2_ISA_IO_DISABLE 0x01 /* ISA I/O address disabled */
#define EC_F2_FORCE_ADDR 0x02 /* HBA forced to EISA/ISA address */
#define EC_F2_SG_64K 0x04 /* 64kB of scatter/gather space */
#define EC_F2_SG_UNALIGNED 0x08 /* Can do unaligned scatter/gather */
#define EC_F2_RESERVED0 0x10 /* Reserved */
#define EC_F2_RESERVED1 0x20 /* Reserved */
#define EC_F2_RESERVED2 0x40 /* Reserved */
#define EC_F2_RESERVED3 0x40 /* Reserved */
#define EC_F3_MAX_TARGET_MASK 0x1f /* Maximum target ID supported */
#define EC_F3_MAX_TARGET_SHIFT 0
#define EC_F3_MAX_CHANNEL_MASK 0xe0 /* Maximum channel ID supported */
#define EC_F3_MAX_CHANNEL_SHIFT 5
#define EC_F4_RESERVED0 0x01 /* Reserved */
#define EC_F4_RESERVED1 0x02 /* Reserved */
#define EC_F4_RESERVED2 0x04 /* Reserved */
#define EC_F4_AUTO_TERM 0x08 /* Supports auto termination */
#define EC_F4_PCIM1 0x10 /* PCI M1 chipset */
#define EC_F4_BOGUS_RAID_ID 0x20 /* RAID ID may be questionable */
#define EC_F4_HBA_PCI 0x40 /* PCI adapter */
#define EC_F4_HBA_EISA 0x80 /* EISA adapter */
/*
* How SCSI inquiry data breaks down for EATA boards.
*/
@ -271,11 +289,11 @@ struct eata_inquiry_data {
u_int8_t ei_additional_length;
u_int8_t ei_unused[2];
u_int8_t ei_flags;
char ei_vendor[8]; /* Vendor, e.g: DPT, NEC */
char ei_model[7]; /* Model number */
char ei_suffix[9]; /* Model number suffix */
char ei_fw[3]; /* Firmware */
char ei_fwrev[1]; /* Firmware revision */
char ei_vendor[8]; /* Vendor, e.g: DPT, NEC */
char ei_model[7]; /* Model number */
char ei_suffix[9]; /* Model number suffix */
char ei_fw[3]; /* Firmware */
char ei_fwrev[1]; /* Firmware revision */
u_int8_t ei_extra[8];
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: dptvar.h,v 1.5 1999/10/23 16:26:32 ad Exp $ */
/* $NetBSD: dptvar.h,v 1.6 2000/02/24 18:47:55 ad Exp $ */
/*
* Copyright (c) 1999 Andy Doran <ad@NetBSD.org>
@ -33,14 +33,17 @@
#define CCB_OFF(sc,m) ((u_long)(m) - (u_long)((sc)->sc_ccbs))
#define CCB_ALLOC 0x01 /* CCB allocated */
#define CCB_ABORT 0x02 /* abort has been issued on this CCB */
#define CCB_INTR 0x04 /* HBA interrupted for this CCB */
#define CCB_PRIVATE 0x08 /* ours; don't talk to scsipi when done */
#define CCB_ABORT 0x01 /* abort has been issued on this CCB */
#define CCB_INTR 0x02 /* HBA interrupted for this CCB */
#define CCB_PRIVATE 0x04 /* ours; don't talk to scsipi when done */
struct dpt_ccb {
/* Data that will be touched by the HBA */
struct eata_cp ccb_eata_cp; /* EATA command packet */
struct eata_sg ccb_sg[DPT_SG_SIZE]; /* SG element list */
struct scsipi_sense_data ccb_sense; /* SCSI sense data on error */
/* Data that will not be touched by the HBA */
volatile int ccb_flg; /* CCB flags */
int ccb_timeout; /* timeout in ms */
u_int32_t ccb_ccbpa; /* physical addr of this CCB */
@ -49,34 +52,33 @@ struct dpt_ccb {
int ccb_scsi_status; /* from status packet */
int ccb_id; /* unique ID of this CCB */
TAILQ_ENTRY(dpt_ccb) ccb_chain; /* link to next CCB */
struct scsipi_sense_data ccb_sense; /* SCSI sense data on error */
struct scsipi_xfer *ccb_xs; /* initiating SCSI command */
};
struct dpt_softc {
struct device sc_dv; /* generic device data */
struct device sc_dv; /* generic device data */
bus_space_handle_t sc_ioh; /* bus space handle */
struct scsipi_adapter sc_adapter;/* scsipi adapter */
struct scsipi_link sc_link[3]; /* prototype link for each channel */
struct eata_cfg sc_ec; /* EATA configuration data */
bus_space_tag_t sc_iot; /* bus space tag */
bus_dma_tag_t sc_dmat; /* bus DMA tag */
bus_dmamap_t sc_dmamap_ccb; /* maps the CCBs */
bus_dmamap_t sc_dmamap; /* maps the CCBs */
int sc_dmamapsize; /* size of above map in bytes */
void *sc_ih; /* interrupt handler cookie */
void *sc_sdh; /* shutdown hook */
struct dpt_ccb *sc_ccbs; /* all our CCBs */
struct eata_sp *sc_statpack; /* EATA status packet */
int sc_spoff; /* status packet offset in dmamap */
u_int32_t sc_sppa; /* status packet physical address */
struct eata_sp *sc_stp; /* EATA status packet */
int sc_stpoff; /* status packet offset in dmamap */
u_int32_t sc_stppa; /* status packet physical address */
caddr_t sc_scr; /* scratch area */
int sc_scrlen; /* scratch area length */
int sc_scroff; /* scratch area offset in dmamap */
u_int32_t sc_scrpa; /* scratch area physical address */
int sc_hbaid[3]; /* ID of HBA on each channel */
int sc_nccbs; /* number of CCBs available */
int sc_open; /* device is open */
TAILQ_HEAD(, dpt_ccb) sc_free_ccb;/* free ccb list */
TAILQ_HEAD(, scsipi_xfer) sc_queue;/* pending commands */
TAILQ_ENTRY(dpt_softc) sc_chain;/* link to next HBA's softc */
struct eata_cfg sc_ec; /* EATA configuration data */
};
int dpt_intr __P((void *));
@ -96,9 +98,6 @@ void dpt_done_ccb __P((struct dpt_softc *, struct dpt_ccb *));
int dpt_init_ccb __P((struct dpt_softc *, struct dpt_ccb *));
int dpt_create_ccbs __P((struct dpt_softc *, struct dpt_ccb *, int));
struct dpt_ccb *dpt_alloc_ccb __P((struct dpt_softc *, int));
#ifdef DEBUG
void dpt_dump_sp __P((struct eata_sp *));
#endif
#endif /* _KERNEL */
#endif /* !defined _IC_DPTVAR_H_ */