diff options
| author | dante <dante@NetBSD.org> | 1999-02-23 20:18:16 +0000 |
|---|---|---|
| committer | dante <dante@NetBSD.org> | 1999-02-23 20:18:16 +0000 |
| commit | eab52d94b3a2a1660534b732f9329fef772d1e1e (patch) | |
| tree | 4ae5172b034f5c97d135a11eed8a7f4ed680a118 /sys/dev | |
| parent | 874801e90610d064da590e82bd638fc8b246fe41 (diff) | |
Fixed AdvanSys Ultra Wide driver to work on Alpha.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ic/adw.c | 70 | ||||
| -rw-r--r-- | sys/dev/ic/adw.h | 10 | ||||
| -rw-r--r-- | sys/dev/ic/adwlib.c | 28 | ||||
| -rw-r--r-- | sys/dev/ic/adwlib.h | 22 |
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; |
