- 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:
parent
3559e78ed2
commit
50062f0914
417
sys/dev/ic/dpt.c
417
sys/dev/ic/dpt.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in New Issue