summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authordante <dante@NetBSD.org>1999-02-23 20:18:16 +0000
committerdante <dante@NetBSD.org>1999-02-23 20:18:16 +0000
commiteab52d94b3a2a1660534b732f9329fef772d1e1e (patch)
tree4ae5172b034f5c97d135a11eed8a7f4ed680a118 /sys/dev
parent874801e90610d064da590e82bd638fc8b246fe41 (diff)
Fixed AdvanSys Ultra Wide driver to work on Alpha.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/adw.c70
-rw-r--r--sys/dev/ic/adw.h10
-rw-r--r--sys/dev/ic/adwlib.c28
-rw-r--r--sys/dev/ic/adwlib.h22
4 files changed, 96 insertions, 34 deletions
diff --git a/sys/dev/ic/adw.c b/sys/dev/ic/adw.c
index 9c6f6815ecb..b9da7ea3186 100644
--- a/sys/dev/ic/adw.c
+++ b/sys/dev/ic/adw.c
@@ -1,4 +1,4 @@
-/* $NetBSD: adw.c,v 1.6 1998/12/09 08:47:18 thorpej Exp $ */
+/* $NetBSD: adw.c,v 1.7 1999/02/23 20:18:16 dante Exp $ */
/*
* Generic driver for the Advanced Systems Inc. SCSI controllers
@@ -81,7 +81,7 @@ static void adw_start_ccbs __P((ADW_SOFTC *));
static int adw_scsi_cmd __P((struct scsipi_xfer *));
static int adw_build_req __P((struct scsipi_xfer *, ADW_CCB *));
-static void adw_build_sglist __P((ADW_CCB *, ADW_SCSI_REQ_Q *));
+static void adw_build_sglist __P((ADW_CCB *, ADW_SCSI_REQ_Q *, ADW_SG_BLOCK *));
static void adwminphys __P((struct buf *));
static void adw_wide_isr_callback __P((ADW_SOFTC *, ADW_SCSI_REQ_Q *));
@@ -108,7 +108,7 @@ struct scsipi_device adw_dev =
/******************************************************************************/
-/* Control Blocks routines */
+/* Control Blocks routines */
/******************************************************************************/
@@ -224,7 +224,7 @@ adw_init_ccb(sc, ccb)
ADW_SOFTC *sc;
ADW_CCB *ccb;
{
- int error;
+ int hashnum, error;
/*
* Create the DMA map for this CCB.
@@ -238,6 +238,16 @@ adw_init_ccb(sc, ccb)
sc->sc_dev.dv_xname, error);
return (error);
}
+
+ /*
+ * put in the phystokv hash table
+ * Never gets taken out.
+ */
+ ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr +
+ ADW_CCB_OFF(ccb);
+ hashnum = CCB_HASH(ccb->hashkey);
+ ccb->nexthash = sc->sc_ccbhash[hashnum];
+ sc->sc_ccbhash[hashnum] = ccb;
adw_reset_ccb(ccb);
return (0);
}
@@ -283,6 +293,26 @@ out:
/*
+ * Given a physical address, find the ccb that it corresponds to.
+ */
+ADW_CCB *
+adw_ccb_phys_kv(sc, ccb_phys)
+ ADW_SOFTC *sc;
+ u_long ccb_phys;
+{
+ int hashnum = CCB_HASH(ccb_phys);
+ ADW_CCB *ccb = sc->sc_ccbhash[hashnum];
+
+ while (ccb) {
+ if (ccb->hashkey == ccb_phys)
+ break;
+ ccb = ccb->nexthash;
+ }
+ return (ccb);
+}
+
+
+/*
* Queue a CCB to be sent to the controller, and send it if possible.
*/
static void
@@ -322,7 +352,7 @@ adw_start_ccbs(sc)
/******************************************************************************/
-/* SCSI layer interfacing routines */
+/* SCSI layer interfacing routines */
/******************************************************************************/
@@ -587,9 +617,11 @@ adw_build_req(xs, ccb)
bzero(scsiqp, sizeof(ADW_SCSI_REQ_Q));
/*
- * Set the ADW_SCSI_REQ_Q 'ccb_ptr' to point to the CCB structure.
+ * Set the ADW_SCSI_REQ_Q 'ccb_ptr' to point to the
+ * physical CCB structure.
*/
- scsiqp->ccb_ptr = (ulong) ccb;
+ scsiqp->ccb_ptr = sc->sc_dmamap_control->dm_segs[0].ds_addr +
+ ADW_CCB_OFF(ccb);
/*
@@ -604,7 +636,7 @@ adw_build_req(xs, ccb)
scsiqp->target_id = sc_link->scsipi_scsi.target;
scsiqp->target_lun = sc_link->scsipi_scsi.lun;
- scsiqp->vsense_addr = (ulong) & ccb->scsi_sense;
+ scsiqp->vsense_addr = &ccb->scsi_sense;
scsiqp->sense_addr = sc->sc_dmamap_control->dm_segs[0].ds_addr +
ADW_CCB_OFF(ccb) + offsetof(struct adw_ccb, scsi_sense);
scsiqp->sense_len = sizeof(struct scsipi_sense_data);
@@ -655,12 +687,10 @@ adw_build_req(xs, ccb)
* Build scatter-gather list.
*/
scsiqp->data_cnt = xs->datalen;
- scsiqp->vdata_addr = (ulong) xs->data;
+ scsiqp->vdata_addr = xs->data;
scsiqp->data_addr = ccb->dmamap_xfer->dm_segs[0].ds_addr;
- scsiqp->sg_list_ptr = &ccb->sg_block[0];
- bzero(scsiqp->sg_list_ptr,
- sizeof(ADW_SG_BLOCK) * ADW_NUM_SG_BLOCK);
- adw_build_sglist(ccb, scsiqp);
+ bzero(ccb->sg_block, sizeof(ADW_SG_BLOCK) * ADW_NUM_SG_BLOCK);
+ adw_build_sglist(ccb, scsiqp, ccb->sg_block);
} else {
/*
* No data xfer, use non S/G values.
@@ -668,7 +698,6 @@ adw_build_req(xs, ccb)
scsiqp->data_cnt = 0;
scsiqp->vdata_addr = 0;
scsiqp->data_addr = 0;
- scsiqp->sg_list_ptr = NULL;
}
return (1);
@@ -679,13 +708,13 @@ adw_build_req(xs, ccb)
* Build scatter-gather list for Wide Boards.
*/
static void
-adw_build_sglist(ccb, scsiqp)
+adw_build_sglist(ccb, scsiqp, sg_block)
ADW_CCB *ccb;
ADW_SCSI_REQ_Q *scsiqp;
+ ADW_SG_BLOCK *sg_block;
{
struct scsipi_xfer *xs = ccb->xs;
ADW_SOFTC *sc = xs->sc_link->adapter_softc;
- ADW_SG_BLOCK *sg_block = scsiqp->sg_list_ptr;
ulong sg_block_next_addr; /* block and its next */
ulong sg_block_physical_addr;
int sg_block_index, i; /* how many SG entries */
@@ -838,7 +867,7 @@ adw_watchdog(arg)
/******************************************************************************/
-/* NARROW and WIDE boards Interrupt callbacks */
+/* WIDE boards Interrupt callbacks */
/******************************************************************************/
@@ -853,12 +882,15 @@ adw_wide_isr_callback(sc, scsiq)
ADW_SCSI_REQ_Q *scsiq;
{
bus_dma_tag_t dmat = sc->sc_dmat;
- ADW_CCB *ccb = (ADW_CCB *) scsiq->ccb_ptr;
- struct scsipi_xfer *xs = ccb->xs;
+ ADW_CCB *ccb;
+ struct scsipi_xfer *xs;
struct scsipi_sense_data *s1, *s2;
//int underrun = ASC_FALSE;
+ ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr);
+ xs = ccb->xs;
+
untimeout(adw_timeout, ccb);
/*
diff --git a/sys/dev/ic/adw.h b/sys/dev/ic/adw.h
index d60ecd7f5b5..0fb0fa67696 100644
--- a/sys/dev/ic/adw.h
+++ b/sys/dev/ic/adw.h
@@ -1,4 +1,4 @@
-/* $NetBSD: adw.h,v 1.1 1998/09/26 16:10:41 dante Exp $ */
+/* $NetBSD: adw.h,v 1.2 1999/02/23 20:18:16 dante Exp $ */
/*
* Generic driver definitions and exported functions for the Advanced
@@ -46,7 +46,10 @@
typedef int (* ADW_ISR_CALLBACK) (ADW_SOFTC *, ADW_SCSI_REQ_Q *);
typedef int (* ADW_SBRESET_CALLBACK) (ADW_SOFTC *);
-/* per request scatter-gather element limit */
+/*
+ * per request scatter-gather element limit
+ * We could have up to 256 SG lists.
+ */
#define ADW_MAX_SG_LIST 64
/*
@@ -68,6 +71,8 @@ struct adw_ccb
struct scsipi_sense_data scsi_sense;
TAILQ_ENTRY(adw_ccb) chain;
+ struct adw_ccb *nexthash;
+ u_long hashkey;
struct scsipi_xfer *xs; /* the scsipi_xfer for this cmd */
int flags; /* see below */
@@ -104,6 +109,7 @@ struct adw_control
int adw_init __P((ADW_SOFTC *sc));
void adw_attach __P((ADW_SOFTC *sc));
int adw_intr __P((void *arg));
+ADW_CCB *adw_ccb_phys_kv __P((ADW_SOFTC *, u_long));
/******************************************************************************/
diff --git a/sys/dev/ic/adwlib.c b/sys/dev/ic/adwlib.c
index a0c71aa0e50..05611715b3e 100644
--- a/sys/dev/ic/adwlib.c
+++ b/sys/dev/ic/adwlib.c
@@ -1,4 +1,4 @@
-/* $NetBSD: adwlib.c,v 1.2 1998/09/26 19:54:22 dante Exp $ */
+/* $NetBSD: adwlib.c,v 1.3 1999/02/23 20:18:16 dante Exp $ */
/*
* Low level routines for the Advanced Systems Inc. SCSI controllers chips
@@ -948,8 +948,17 @@ AdvISR(sc)
ADW_READ_WORD_LRAM(iot, ioh,
next_done_loc + RQL_PHYADDR + 2, msw);
- scsiq = (ADW_SCSI_REQ_Q *)
- (((u_int32_t) msw << 16) | lsw);
+ /*
+ * Here we retrive the virtual address of the
+ * ADW_SCSI_REQ_Q structure. This is accomplished
+ * retriving first the ccb physical address (which
+ * we passed to the board in AdvSendScsiCmd),
+ * translating then to a virtual address, and
+ * retrivieng the the ADW_SCSI_REQ_Q pointer stored
+ * into the ccb structure.
+ */
+ scsiq = &adw_ccb_phys_kv(sc,
+ (((u_int32_t) msw << 16) | lsw))->scsiq;
}
target_bit = ADW_TID_TO_TIDMASK(scsiq->target_id);
@@ -1096,13 +1105,15 @@ AdvSendScsiCmd(sc, scsiq)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- ADW_CCB *ccb = (ADW_CCB *) scsiq->ccb_ptr;
+ ADW_CCB *ccb;
u_int16_t next_ready_loc;
u_int8_t next_ready_loc_fwd;
long req_size;
u_int32_t q_phy_addr;
+ ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr);
+
if (sc->cur_host_qng >= sc->max_host_qng) {
return ADW_BUSY;
} else {
@@ -1138,7 +1149,14 @@ AdvSendScsiCmd(sc, scsiq)
q_phy_addr = sc->sc_dmamap_control->dm_segs[0].ds_addr +
ADW_CCB_OFF(ccb) + offsetof(struct adw_ccb, scsiq);
- scsiq->scsiq_ptr = scsiq;
+ /*
+ * The "scsiq" pointer must be passed to the board so we can retrive it
+ * during the interrupt condition: inside the Adv_ISR() function.
+ * It should contain the virtual address of ADW_SCSI_REQ_Q structure,
+ * but actually, to make it works under 64bits architecure it contains
+ * the physical address of ccb (ADW_CCB).
+ */
+ scsiq->ccb_scsiq_ptr = scsiq->ccb_ptr;
/*
* The RISC list structure, which 'next_ready_loc' is a pointer
diff --git a/sys/dev/ic/adwlib.h b/sys/dev/ic/adwlib.h
index 671cf193e3a..95b85584323 100644
--- a/sys/dev/ic/adwlib.h
+++ b/sys/dev/ic/adwlib.h
@@ -1,4 +1,4 @@
-/* $NetBSD: adwlib.h,v 1.3 1998/12/09 08:47:18 thorpej Exp $ */
+/* $NetBSD: adwlib.h,v 1.4 1999/02/23 20:18:16 dante Exp $ */
/*
* Definitions for low level routines and data structures
@@ -682,6 +682,10 @@ typedef struct adw_dvc_cfg {
* this field may be set, but later if a device is found to be incapable
* of the feature, the field is cleared.
*/
+#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
+#define CCB_HASH_SHIFT 9
+#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
+
typedef struct adw_softc {
struct device sc_dev;
@@ -693,6 +697,8 @@ typedef struct adw_softc {
void *sc_ih;
struct adw_control *sc_control; /* control structures */
+
+ struct adw_ccb *sc_ccbhash[CCB_HASH_SIZE];
TAILQ_HEAD(, adw_ccb) sc_free_ccb, sc_waiting_ccb;
struct scsipi_link sc_link; /* prototype for devs */
struct scsipi_adapter sc_adapter;
@@ -764,9 +770,9 @@ typedef struct adw_scsi_req_q {
ulong data_addr; /* Data buffer physical address. */
u_int32_t data_cnt; /* Data count. Ucode sets to residual. */
ulong sense_addr; /* Sense buffer physical address. */
- ulong ccb_ptr; /* Driver request pointer. */
+ ulong ccb_ptr; /* Driver request physical address. */
u_int8_t a_flag; /* Adv Library flag field. */
- u_int8_t sense_len; /* Auto-sense length. Ucode sets to residual. */
+ u_int8_t sense_len; /* Auto-sense length. uCode sets to residual. */
u_int8_t cdb_len; /* SCSI CDB length. */
u_int8_t tag_code; /* SCSI-2 Tag Queue Code: 00, 20-22. */
u_int8_t done_status; /* Completion status. */
@@ -775,16 +781,16 @@ typedef struct adw_scsi_req_q {
u_int8_t ux_sg_ix; /* Ucode working SG variable. */
u_int8_t cdb[12]; /* SCSI command block. */
ulong sg_real_addr; /* SG list physical address. */
- struct adw_scsi_req_q *free_scsiq_link;
+ u_int32_t free_scsiq_link;/* Iternal pointer to ADW_SCSI_REQ_Q */
ulong ux_wk_data_cnt; /* Saved data count at disconnection. */
- struct adw_scsi_req_q *scsiq_ptr;
- ADW_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
+ ulong ccb_scsiq_ptr; /* Pointer to ADW_SCSI_REQ_Q */
+ u_int32_t sg_list_ptr; /* SG list v-address. (ADW_SG_BLOCK* - unused) */
/*
* End of microcode structure - 60 bytes. The rest of the structure
* is used by the Adv Library and ignored by the microcode.
*/
- ulong vsense_addr; /* Sense buffer virtual address. */
- ulong vdata_addr; /* Data buffer virtual address. */
+ struct scsipi_sense_data *vsense_addr; /* Sense buffer virtual address. */
+ u_char *vdata_addr; /* Data buffer virtual address. */
u_int8_t orig_sense_len; /* Original length of sense buffer. */
u_int8_t pads[3]; /* padding bytes (align to long) */
} ADW_SCSI_REQ_Q;