Change the way ADW_CARRIER is allocated and handled.
Increased ADW_MAX_CCB to 63 and ADW_MAX_CARRIER to 253 Print WDTR/SDTR negotiation result per target Protect AdvISR() inside splbio()/splx() pair Add a pending queue to keep track of all the CCBs that are being executed by the host adapter. Rewrote timeout handler in a more efficient way: After 3 timeout now the SCSI is resetted and all pending queues not completed are now reenqueued in the waiting queue so to get executed just after the BUS Reset (hoping that resetting the SCSI BUS and reinitializing the adapter could solve the problem).
This commit is contained in:
parent
2648a72bb2
commit
6644e670f7
319
sys/dev/ic/adw.c
319
sys/dev/ic/adw.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: adw.c,v 1.18 2000/05/03 19:15:27 thorpej Exp $ */
|
||||
/* $NetBSD: adw.c,v 1.19 2000/05/08 17:21:33 dante Exp $ */
|
||||
|
||||
/*
|
||||
* Generic driver for the Advanced Systems Inc. SCSI controllers
|
||||
|
@ -74,7 +74,6 @@
|
|||
static int adw_alloc_controls __P((ADW_SOFTC *));
|
||||
static int adw_alloc_carriers __P((ADW_SOFTC *));
|
||||
static int adw_create_carriers __P((ADW_SOFTC *));
|
||||
static int adw_init_carrier __P((ADW_SOFTC *, ADW_CARRIER *));
|
||||
static int adw_create_ccbs __P((ADW_SOFTC *, ADW_CCB *, int));
|
||||
static void adw_free_ccb __P((ADW_SOFTC *, ADW_CCB *));
|
||||
static void adw_reset_ccb __P((ADW_CCB *));
|
||||
|
@ -89,6 +88,8 @@ static void adwminphys __P((struct buf *));
|
|||
static void adw_isr_callback __P((ADW_SOFTC *, ADW_SCSI_REQ_Q *));
|
||||
static void adw_async_callback __P((ADW_SOFTC *, u_int8_t));
|
||||
|
||||
static void adw_print_info __P((ADW_SOFTC *, int));
|
||||
|
||||
static int adw_poll __P((ADW_SOFTC *, struct scsipi_xfer *, int));
|
||||
static void adw_timeout __P((void *));
|
||||
|
||||
|
@ -96,7 +97,7 @@ static void adw_timeout __P((void *));
|
|||
/******************************************************************************/
|
||||
|
||||
|
||||
/* the below structure is so we have a default dev struct for out link struct */
|
||||
/* the below structure is so we have a default dev struct for our link struct */
|
||||
struct scsipi_device adw_dev =
|
||||
{
|
||||
NULL, /* Use default error handler */
|
||||
|
@ -106,12 +107,8 @@ struct scsipi_device adw_dev =
|
|||
};
|
||||
|
||||
|
||||
#define ADW_ABORT_TIMEOUT 10000 /* time to wait for abort (mSec) */
|
||||
#define ADW_WATCH_TIMEOUT 10000 /* time to wait for watchdog (mSec) */
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Control Blocks routines */
|
||||
/* Control Blocks routines */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
|
@ -171,7 +168,7 @@ adw_alloc_carriers(sc)
|
|||
/*
|
||||
* Allocate the control structure.
|
||||
*/
|
||||
sc->sc_control->carriers = malloc(ADW_CARRIER_SIZE * ADW_MAX_CARRIER,
|
||||
sc->sc_control->carriers = malloc(sizeof(ADW_CARRIER) * ADW_MAX_CARRIER,
|
||||
M_DEVBUF, M_WAITOK);
|
||||
if(!sc->sc_control->carriers) {
|
||||
printf("%s: malloc() failed in allocating carrier structures\n",
|
||||
|
@ -180,14 +177,14 @@ adw_alloc_carriers(sc)
|
|||
}
|
||||
|
||||
if ((error = bus_dmamem_alloc(sc->sc_dmat,
|
||||
ADW_CARRIER_SIZE * ADW_MAX_CARRIER,
|
||||
NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
|
||||
sizeof(ADW_CARRIER) * ADW_MAX_CARRIER,
|
||||
0x10, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
|
||||
printf("%s: unable to allocate carrier structures,"
|
||||
" error = %d\n", sc->sc_dev.dv_xname, error);
|
||||
return (error);
|
||||
}
|
||||
if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
|
||||
ADW_CARRIER_SIZE * ADW_MAX_CARRIER,
|
||||
sizeof(ADW_CARRIER) * ADW_MAX_CARRIER,
|
||||
(caddr_t *) &sc->sc_control->carriers,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
|
||||
printf("%s: unable to map carrier structures,"
|
||||
|
@ -199,8 +196,8 @@ adw_alloc_carriers(sc)
|
|||
* Create and load the DMA map used for the control blocks.
|
||||
*/
|
||||
if ((error = bus_dmamap_create(sc->sc_dmat,
|
||||
ADW_CARRIER_SIZE * ADW_MAX_CARRIER, 1,
|
||||
ADW_CARRIER_SIZE * ADW_MAX_CARRIER, 0, BUS_DMA_NOWAIT,
|
||||
sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, 1,
|
||||
sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, 0,BUS_DMA_NOWAIT,
|
||||
&sc->sc_dmamap_carrier)) != 0) {
|
||||
printf("%s: unable to create carriers DMA map,"
|
||||
" error = %d\n", sc->sc_dev.dv_xname, error);
|
||||
|
@ -208,23 +205,13 @@ adw_alloc_carriers(sc)
|
|||
}
|
||||
if ((error = bus_dmamap_load(sc->sc_dmat,
|
||||
sc->sc_dmamap_carrier, sc->sc_control->carriers,
|
||||
ADW_CARRIER_SIZE * ADW_MAX_CARRIER, NULL,
|
||||
sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, NULL,
|
||||
BUS_DMA_NOWAIT)) != 0) {
|
||||
printf("%s: unable to load carriers DMA map,"
|
||||
" error = %d\n", sc->sc_dev.dv_xname, error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
error = bus_dmamap_create(sc->sc_dmat, ADW_CARRIER_SIZE* ADW_MAX_CARRIER,
|
||||
1, ADW_CARRIER_SIZE * ADW_MAX_CARRIER,
|
||||
0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
|
||||
&sc->sc_control->dmamap_xfer);
|
||||
if (error) {
|
||||
printf("%s: unable to create Carrier DMA map, error = %d\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -239,77 +226,30 @@ adw_create_carriers(sc)
|
|||
{
|
||||
ADW_CARRIER *carr;
|
||||
u_int32_t carr_next = NULL;
|
||||
int i, error;
|
||||
int i;
|
||||
|
||||
for(i=0; i < ADW_MAX_CARRIER; i++) {
|
||||
carr = (ADW_CARRIER *)(((u_int8_t *)sc->sc_control->carriers) +
|
||||
(ADW_CARRIER_SIZE * i));
|
||||
if ((error = adw_init_carrier(sc, carr)) != 0) {
|
||||
printf("%s: unable to initialize carrier, error = %d\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
return (i);
|
||||
}
|
||||
(sizeof(ADW_CARRIER) * i));
|
||||
carr->carr_pa = ADW_CARRIER_BADDR(sc, carr);
|
||||
carr->carr_id = i;
|
||||
carr->next_vpa = carr_next;
|
||||
carr_next = carr->carr_pa;
|
||||
carr->id = i;
|
||||
}
|
||||
sc->carr_freelist = carr;
|
||||
return (i);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
adw_init_carrier(sc, carr)
|
||||
ADW_SOFTC *sc;
|
||||
ADW_CARRIER *carr;
|
||||
{
|
||||
u_int32_t carr_pa;
|
||||
int /*error, */hashnum;
|
||||
|
||||
/*
|
||||
* Create the DMA map for all of the Carriers.
|
||||
*/
|
||||
/* error = bus_dmamap_create(sc->sc_dmat, ADW_CARRIER_SIZE,
|
||||
1, ADW_CARRIER_SIZE,
|
||||
0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
|
||||
&carr->dmamap_xfer);
|
||||
if (error) {
|
||||
printf("%s: unable to create Carrier DMA map, error = %d\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
return (error);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* put in the phystokv hash table
|
||||
* Never gets taken out.
|
||||
*/
|
||||
carr_pa = ADW_CARRIER_ADDR(sc, carr);
|
||||
carr->carr_pa = carr_pa;
|
||||
hashnum = CARRIER_HASH(carr_pa);
|
||||
carr->nexthash = sc->sc_carrhash[hashnum];
|
||||
sc->sc_carrhash[hashnum] = carr;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given a physical address, find the Carrier that it corresponds to.
|
||||
*/
|
||||
ADW_CARRIER *
|
||||
inline ADW_CARRIER *
|
||||
adw_carrier_phys_kv(sc, carr_phys)
|
||||
ADW_SOFTC *sc;
|
||||
u_int32_t carr_phys;
|
||||
{
|
||||
int hashnum = CARRIER_HASH(carr_phys);
|
||||
ADW_CARRIER *carr = sc->sc_carrhash[hashnum];
|
||||
|
||||
while (carr) {
|
||||
if (carr->carr_pa == carr_phys)
|
||||
break;
|
||||
carr = carr->nexthash;
|
||||
}
|
||||
return (carr);
|
||||
return (ADW_CARRIER_VADDR(sc, carr_phys));
|
||||
}
|
||||
|
||||
|
||||
|
@ -477,12 +417,11 @@ adw_queue_ccb(sc, ccb, retry)
|
|||
ADW_CCB *ccb;
|
||||
int retry;
|
||||
{
|
||||
int errcode;
|
||||
int errcode = ADW_SUCCESS;
|
||||
|
||||
if(!retry)
|
||||
if(!retry) {
|
||||
TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
|
||||
|
||||
errcode = ADW_SUCCESS;
|
||||
}
|
||||
|
||||
while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
|
||||
|
||||
|
@ -502,6 +441,7 @@ adw_queue_ccb(sc, ccb, retry)
|
|||
}
|
||||
|
||||
TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
|
||||
TAILQ_INSERT_TAIL(&sc->sc_pending_ccb, ccb, chain);
|
||||
|
||||
if ((ccb->xs->xs_control & XS_CTL_POLL) == 0)
|
||||
callout_reset(&ccb->xs->xs_callout,
|
||||
|
@ -580,6 +520,7 @@ adw_attach(sc)
|
|||
|
||||
TAILQ_INIT(&sc->sc_free_ccb);
|
||||
TAILQ_INIT(&sc->sc_waiting_ccb);
|
||||
TAILQ_INIT(&sc->sc_pending_ccb);
|
||||
TAILQ_INIT(&sc->sc_queue);
|
||||
|
||||
|
||||
|
@ -613,7 +554,7 @@ adw_attach(sc)
|
|||
if (error)
|
||||
return; /* (error) */ ;
|
||||
|
||||
bzero(sc->sc_control->carriers, ADW_CARRIER_SIZE * ADW_MAX_CARRIER);
|
||||
bzero(sc->sc_control->carriers, sizeof(ADW_CARRIER) * ADW_MAX_CARRIER);
|
||||
|
||||
i = adw_create_carriers(sc);
|
||||
if (i == 0) {
|
||||
|
@ -647,6 +588,16 @@ adw_attach(sc)
|
|||
}
|
||||
|
||||
switch (error) {
|
||||
case ASC_IERR_BIST_PRE_TEST:
|
||||
panic("%s: BIST pre-test error",
|
||||
sc->sc_dev.dv_xname);
|
||||
break;
|
||||
|
||||
case ASC_IERR_BIST_RAM_TEST:
|
||||
panic("%s: BIST RAM test error",
|
||||
sc->sc_dev.dv_xname);
|
||||
break;
|
||||
|
||||
case ASC_IERR_MCODE_CHKSUM:
|
||||
panic("%s: Microcode checksum error",
|
||||
sc->sc_dev.dv_xname);
|
||||
|
@ -662,6 +613,11 @@ adw_attach(sc)
|
|||
sc->sc_dev.dv_xname);
|
||||
break;
|
||||
|
||||
case ASC_IERR_HVD_DEVICE:
|
||||
panic("%s: HVD attached to LVD connector",
|
||||
sc->sc_dev.dv_xname);
|
||||
break;
|
||||
|
||||
case ASC_IERR_SINGLE_END_DEVICE:
|
||||
panic("%s: single-ended device is attached to"
|
||||
" one of the connectors",
|
||||
|
@ -814,7 +770,6 @@ retryagain:
|
|||
case ADW_ERROR:
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
return (COMPLETE);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1061,27 +1016,97 @@ adw_timeout(arg)
|
|||
s = splbio();
|
||||
|
||||
/*
|
||||
* If it has been through before, then a previous abort has failed,
|
||||
* If it has been through before, then previous aborts failed,
|
||||
* don't try abort again, reset the bus instead.
|
||||
*/
|
||||
if (ccb->flags & CCB_ABORTED) {
|
||||
/*
|
||||
* Abort Timed Out
|
||||
* Lets try resetting the bus!
|
||||
*
|
||||
* No more opportunities. Lets try resetting the bus!
|
||||
*/
|
||||
callout_stop(&xs->xs_callout);
|
||||
|
||||
printf(" AGAIN. Resetting SCSI Bus\n");
|
||||
ccb->flags &= ~CCB_ABORTED;
|
||||
/* AdvResetSCSIBus() will call sbreset_callback() */
|
||||
AdvResetSCSIBus(sc);
|
||||
|
||||
while((ccb = TAILQ_LAST(&sc->sc_pending_ccb,
|
||||
adw_pending_ccb)) != NULL) {
|
||||
callout_stop(&ccb->xs->xs_callout);
|
||||
TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain);
|
||||
TAILQ_INSERT_HEAD(&sc->sc_waiting_ccb, ccb, chain);
|
||||
}
|
||||
adw_queue_ccb(sc, TAILQ_FIRST(&sc->sc_waiting_ccb), 1);
|
||||
splx(s);
|
||||
return;
|
||||
} else if (ccb->flags & CCB_ABORTING) {
|
||||
/*
|
||||
* Abort the operation that has timed out
|
||||
*
|
||||
* Second opportunity.
|
||||
*/
|
||||
printf("\n");
|
||||
xs->error = XS_TIMEOUT;
|
||||
ccb->flags |= CCB_ABORTED;
|
||||
#if 0
|
||||
/*
|
||||
* - XXX - 3.3a microcode is BROKEN!!!
|
||||
*
|
||||
* We cannot abort a CCB, so we can only hope the command
|
||||
* get completed before the next timeout, otherwise a
|
||||
* Bus Reset will arrive inexorably.
|
||||
*/
|
||||
/*
|
||||
* ADW_ABORT_CCB() makes the board to generate an interrupt
|
||||
*
|
||||
* - XXX - The above assertion MUST be verified (and this
|
||||
* code changed as well [callout_*()]), when the
|
||||
* ADW_ABORT_CCB will be working again
|
||||
*/
|
||||
ADW_ABORT_CCB(sc, ccb);
|
||||
#endif
|
||||
/*
|
||||
* waiting for multishot callout_reset() let's restart it
|
||||
* by hand so the next time a timeout event will occour
|
||||
* we will reset the bus.
|
||||
*/
|
||||
callout_stop(&xs->xs_callout);
|
||||
callout_reset(&xs->xs_callout,
|
||||
(ccb->timeout * hz) / 1000, adw_timeout, ccb);
|
||||
} else {
|
||||
/*
|
||||
* Abort the operation that has timed out
|
||||
*
|
||||
* First opportunity.
|
||||
*/
|
||||
printf("\n");
|
||||
xs->error = XS_TIMEOUT;
|
||||
ccb->flags |= CCB_ABORTING;
|
||||
/* ADW_ABORT_CCB() will implicitly call isr_callback() */
|
||||
#if 0
|
||||
/*
|
||||
* - XXX - 3.3a microcode is BROKEN!!!
|
||||
*
|
||||
* We cannot abort a CCB, so we can only hope the command
|
||||
* get completed before the next 2 timeout, otherwise a
|
||||
* Bus Reset will arrive inexorably.
|
||||
*/
|
||||
/*
|
||||
* ADW_ABORT_CCB() makes the board to generate an interrupt
|
||||
*
|
||||
* - XXX - The above assertion MUST be verified (and this
|
||||
* code changed as well [callout_*()]), when the
|
||||
* ADW_ABORT_CCB will be working again
|
||||
*/
|
||||
ADW_ABORT_CCB(sc, ccb);
|
||||
#endif
|
||||
/*
|
||||
* waiting for multishot callout_reset() let's restart it
|
||||
* by hand so the next time a timeout event will occour
|
||||
* we will reset the bus.
|
||||
*/
|
||||
callout_stop(&xs->xs_callout);
|
||||
callout_reset(&xs->xs_callout,
|
||||
(ccb->timeout * hz) / 1000, adw_timeout, ccb);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
|
@ -1089,14 +1114,89 @@ adw_timeout(arg)
|
|||
|
||||
|
||||
/******************************************************************************/
|
||||
/* WIDE boards Interrupt callbacks */
|
||||
/* Host Adapter and Peripherals Information Routines */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
static void
|
||||
adw_print_info(sc, tid)
|
||||
ADW_SOFTC *sc;
|
||||
int tid;
|
||||
{
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
u_int16_t wdtr_able, wdtr_done, wdtr;
|
||||
u_int16_t sdtr_able, sdtr_done, sdtr, period;
|
||||
int wdtr_reneg = 0, sdtr_reneg = 0;
|
||||
|
||||
printf("%s: target %d ", sc->sc_dev.dv_xname, tid);
|
||||
|
||||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_SDTR_ABLE, wdtr_able);
|
||||
if(wdtr_able & ADW_TID_TO_TIDMASK(tid)) {
|
||||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_SDTR_DONE, wdtr_done);
|
||||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_DEVICE_HSHK_CFG_TABLE +
|
||||
(2 * tid), wdtr);
|
||||
printf("using %d-bits wide, ", (wdtr & 0x8000)? 16 : 8);
|
||||
if((wdtr_done & ADW_TID_TO_TIDMASK(tid)) == 0)
|
||||
wdtr_reneg = 1;
|
||||
} else {
|
||||
printf("wide transfers disabled, ");
|
||||
}
|
||||
|
||||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_SDTR_ABLE, sdtr_able);
|
||||
if(sdtr_able & ADW_TID_TO_TIDMASK(tid)) {
|
||||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_SDTR_DONE, sdtr_done);
|
||||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_DEVICE_HSHK_CFG_TABLE +
|
||||
(2 * tid), sdtr);
|
||||
sdtr &= ~0x8000;
|
||||
if((sdtr & 0x1F) != 0) {
|
||||
if((sdtr & 0x1F00) == 0x1100){
|
||||
printf("80.0 MHz");
|
||||
} else if((sdtr & 0x1F00) == 0x1000){
|
||||
printf("40.0 MHz");
|
||||
} else {
|
||||
/* <= 20.0 MHz */
|
||||
period = (((sdtr >> 8) * 25) + 50)/4;
|
||||
if(period == 0) {
|
||||
/* Should never happen. */
|
||||
printf("? MHz");
|
||||
} else {
|
||||
printf("%d.%d MHz", 250/period,
|
||||
ADW_TENTHS(250, period));
|
||||
}
|
||||
}
|
||||
printf(" synchronous transfers\n");
|
||||
} else {
|
||||
printf("asynchronous transfers\n");
|
||||
}
|
||||
if((sdtr_done & ADW_TID_TO_TIDMASK(tid)) == 0)
|
||||
sdtr_reneg = 1;
|
||||
} else {
|
||||
printf("synchronous transfers disabled\n");
|
||||
}
|
||||
|
||||
if(wdtr_reneg || sdtr_reneg) {
|
||||
printf("%s: target %d %s", sc->sc_dev.dv_xname, tid,
|
||||
(wdtr_reneg)? ((sdtr_reneg)? "wide/sync" : "wide") :
|
||||
((sdtr_reneg)? "sync" : "") );
|
||||
printf(" renegotiation pending before next command.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* WIDE boards Interrupt callbacks */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* adw__isr_callback() - Second Level Interrupt Handler called by AdvISR()
|
||||
* adw_isr_callback() - Second Level Interrupt Handler called by AdvISR()
|
||||
*
|
||||
* Interrupt callback function for the Wide SCSI Adv Library.
|
||||
*
|
||||
* Notice:
|
||||
* Intrrupts are disabled by the caller (AdvISR() function), and will be
|
||||
* enabled at the end of the caller.
|
||||
*/
|
||||
static void
|
||||
adw_isr_callback(sc, scsiq)
|
||||
|
@ -1107,23 +1207,12 @@ adw_isr_callback(sc, scsiq)
|
|||
ADW_CCB *ccb;
|
||||
struct scsipi_xfer *xs;
|
||||
struct scsipi_sense_data *s1, *s2;
|
||||
// int s;
|
||||
|
||||
|
||||
ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr);
|
||||
|
||||
callout_stop(&ccb->xs->xs_callout);
|
||||
|
||||
/* if(ccb->flags & CCB_ABORTING) {
|
||||
printf("Retrying request\n");
|
||||
ccb->flags &= ~CCB_ABORTING;
|
||||
ccb->flags |= CCB_ABORTED;
|
||||
s = splbio();
|
||||
adw_queue_ccb(sc, ccb);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
xs = ccb->xs;
|
||||
|
||||
/*
|
||||
|
@ -1159,6 +1248,10 @@ adw_isr_callback(sc, scsiq)
|
|||
case QHSTA_NO_ERROR:
|
||||
xs->error = XS_NOERROR;
|
||||
xs->resid = 0;
|
||||
if (scsiq->cdb[0] == INQUIRY &&
|
||||
scsiq->target_lun == 0) {
|
||||
adw_print_info(sc, scsiq->target_id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* QHSTA error occurred. */
|
||||
|
@ -1213,6 +1306,7 @@ adw_isr_callback(sc, scsiq)
|
|||
break;
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain);
|
||||
adw_free_ccb(sc, ccb);
|
||||
xs->xs_status |= XS_STS_DONE;
|
||||
scsipi_done(xs);
|
||||
|
@ -1232,22 +1326,31 @@ adw_async_callback(sc, code)
|
|||
/*
|
||||
* The firmware detected a SCSI Bus reset.
|
||||
*/
|
||||
printf("%s: SCSI Bus reset detected\n", sc->sc_dev.dv_xname);
|
||||
break;
|
||||
|
||||
case ADV_ASYNC_RDMA_FAILURE:
|
||||
/*
|
||||
* Handle RDMA failure by resetting the SCSI Bus and
|
||||
* possibly the chip if it is unresponsive. Log the error
|
||||
* with a unique code.
|
||||
* possibly the chip if it is unresponsive.
|
||||
*/
|
||||
AdvResetSCSIBus(sc);
|
||||
break;
|
||||
|
||||
case ADV_HOST_SCSI_BUS_RESET:
|
||||
/*
|
||||
* Host generated SCSI bus reset occurred.
|
||||
*/
|
||||
break;
|
||||
/*
|
||||
* Host generated SCSI bus reset occurred.
|
||||
*/
|
||||
printf("%s: Host generated SCSI bus reset occurred\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
break;
|
||||
|
||||
case ADV_ASYNC_CARRIER_READY_FAILURE:
|
||||
/*
|
||||
* Carrier Ready failure.
|
||||
*/
|
||||
printf("%s: Carrier Ready failure!\n", sc->sc_dev.dv_xname);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: adw.h,v 1.6 2000/04/30 18:52:15 dante Exp $ */
|
||||
/* $NetBSD: adw.h,v 1.7 2000/05/08 17:21:34 dante Exp $ */
|
||||
|
||||
/*
|
||||
* Generic driver definitions and exported functions for the Advanced
|
||||
|
@ -48,11 +48,12 @@ typedef void (* ADW_ASYNC_CALLBACK) (ADW_SOFTC *, u_int8_t);
|
|||
|
||||
|
||||
/*
|
||||
* ADW_CARRIER must be exactly 16 BYTES
|
||||
* Every adw_carrier structure _MUST_ always be aligned on a 16 bytes boundary
|
||||
*/
|
||||
struct adw_carrier {
|
||||
/* ---------- the microcode wants the field below ---------- */
|
||||
u_int32_t unused; /* Carrier Virtual Address -UNUSED- */
|
||||
u_int32_t carr_id; /* Carrier ID */
|
||||
u_int32_t carr_pa; /* Carrier Physical Address */
|
||||
u_int32_t areq_vpa; /* ADW_SCSI_REQ_Q Physical Address */
|
||||
/*
|
||||
|
@ -63,19 +64,10 @@ struct adw_carrier {
|
|||
*/
|
||||
u_int32_t next_vpa;
|
||||
/* ---------- ---------- */
|
||||
struct adw_carrier *nexthash; /* Carrier Virtual Address */
|
||||
|
||||
int id;
|
||||
/*
|
||||
* This DMA map maps the buffer involved in the carrier transfer.
|
||||
*/
|
||||
// bus_dmamap_t dmamap_xfer;
|
||||
};
|
||||
|
||||
typedef struct adw_carrier ADW_CARRIER;
|
||||
|
||||
#define ADW_CARRIER_SIZE ((((int)((sizeof(ADW_CARRIER)-1)/16))+1)*16)
|
||||
|
||||
|
||||
/*
|
||||
* Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
|
||||
|
@ -110,8 +102,6 @@ struct adw_ccb {
|
|||
ADW_SCSI_REQ_Q scsiq;
|
||||
ADW_SG_BLOCK sg_block[ADW_NUM_SG_BLOCK];
|
||||
|
||||
ADW_CARRIER *carr_list; /* carriers involved */
|
||||
|
||||
struct scsipi_sense_data scsi_sense;
|
||||
|
||||
TAILQ_ENTRY(adw_ccb) chain;
|
||||
|
@ -136,20 +126,28 @@ typedef struct adw_ccb ADW_CCB;
|
|||
#define CCB_ABORTED 0x04
|
||||
|
||||
|
||||
#define ADW_MAX_CARRIER 20 /* Max. number of host commands (253) */
|
||||
#define ADW_MAX_CCB 16 /* Max. number commands per device (63) */
|
||||
#define ADW_MAX_CARRIER 253 /* Max. number of host commands (253) */
|
||||
#define ADW_MAX_CCB 63 /* Max. number commands per device (63) */
|
||||
|
||||
struct adw_control {
|
||||
ADW_CCB ccbs[ADW_MAX_CCB]; /* all our control blocks */
|
||||
ADW_CARRIER *carriers; /* all our carriers */
|
||||
bus_dmamap_t dmamap_xfer;
|
||||
};
|
||||
|
||||
/*
|
||||
* Offset of a carrier from the beginning of the carriers DMA mapping.
|
||||
* Bus Address of a Carrier.
|
||||
* ba = base_ba + v_address - base_va
|
||||
*/
|
||||
#define ADW_CARRIER_ADDR(sc, x) ((sc)->sc_dmamap_carrier->dm_segs[0].ds_addr + \
|
||||
#define ADW_CARRIER_BADDR(sc,x) ((sc)->sc_dmamap_carrier->dm_segs[0].ds_addr + \
|
||||
(((u_long)x) - ((u_long)(sc)->sc_control->carriers)))
|
||||
/*
|
||||
* Virtual Address of a Carrier.
|
||||
* va = base_va + bus_address - base_ba
|
||||
*/
|
||||
#define ADW_CARRIER_VADDR(sc,x) ((ADW_CARRIER *) \
|
||||
(((u_int8_t *)(sc)->sc_control->carriers) + \
|
||||
((u_long)x) - \
|
||||
(sc)->sc_dmamap_carrier->dm_segs[0].ds_addr))
|
||||
/*
|
||||
* Offset of a CCB from the beginning of the control DMA mapping.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: adwlib.c,v 1.10 2000/04/30 18:52:15 dante Exp $ */
|
||||
/* $NetBSD: adwlib.c,v 1.11 2000/05/08 17:21:34 dante Exp $ */
|
||||
|
||||
/*
|
||||
* Low level routines for the Advanced Systems Inc. SCSI controllers chips
|
||||
|
@ -135,7 +135,7 @@ Default_3550_EEPROM_Config = {
|
|||
0, /* serial_number_word2 */
|
||||
0, /* serial_number_word3 */
|
||||
0, /* check_sum */
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* oem_name[16] */
|
||||
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */
|
||||
0, /* dvc_err_code */
|
||||
0, /* adv_err_code */
|
||||
0, /* adv_err_addr */
|
||||
|
@ -1023,8 +1023,8 @@ ADW_SOFTC *sc;
|
|||
}
|
||||
|
||||
/*
|
||||
* For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
|
||||
* bits for the default FIFO threshold.
|
||||
* For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and
|
||||
* START_CTL_TH [3:2] bits for the default FIFO threshold.
|
||||
*
|
||||
* Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
|
||||
*
|
||||
|
@ -1752,8 +1752,8 @@ ADW_SOFTC *sc;
|
|||
* COMMA register to the same value otherwise the RISC will
|
||||
* prematurely detect a command is available.
|
||||
*/
|
||||
ADW_WRITE_DWORD_LRAM(iot, ioh, ASC_MC_ICQ, sc->icq_sp->carr_pa);
|
||||
ADW_WRITE_DWORD_REGISTER(iot, ioh, IOPDW_COMMA, sc->icq_sp->carr_pa);
|
||||
ADW_WRITE_DWORD_LRAM(iot, ioh, ASC_MC_ICQ, sc->icq_sp->carr_pa);
|
||||
ADW_WRITE_DWORD_REGISTER(iot, ioh, IOPDW_COMMA, sc->icq_sp->carr_pa);
|
||||
|
||||
/*
|
||||
* Set-up the RISC->Host Initiator Response Queue (IRQ).
|
||||
|
@ -2817,7 +2817,6 @@ ADW_SCSI_REQ_Q *scsiq;
|
|||
*/
|
||||
|
||||
ccb = adw_ccb_phys_kv(sc, scsiq->ccb_ptr);
|
||||
// ccb->carr_list = sc->icq_sp;
|
||||
|
||||
/*
|
||||
* Allocate a carrier ensuring at least one carrier always
|
||||
|
@ -2869,25 +2868,15 @@ ADW_SCSI_REQ_Q *scsiq;
|
|||
* Set the host adapter stopper pointer to point to the new carrier.
|
||||
*/
|
||||
sc->icq_sp = new_carrp;
|
||||
/*
|
||||
bus_dmamap_load(sc->sc_dmat, sc->sc_control->dmamap_xfer,
|
||||
sc->sc_control->carriers,
|
||||
ADW_CARRIER_SIZE * ADW_MAX_CARRIER,
|
||||
NULL, BUS_DMA_NOWAIT);
|
||||
bus_dmamap_sync(sc->sc_dmat, sc->sc_control->dmamap_xfer, 0,
|
||||
sc->sc_control->dmamap_xfer->dm_mapsize,
|
||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
||||
*/
|
||||
|
||||
if (sc->chip_type == ADV_CHIP_ASC3550 ||
|
||||
sc->chip_type == ADV_CHIP_ASC38C0800)
|
||||
{
|
||||
sc->chip_type == ADV_CHIP_ASC38C0800) {
|
||||
/*
|
||||
* Tickle the RISC to tell it to read its Command Queue Head
|
||||
* pointer.
|
||||
*/
|
||||
ADW_WRITE_BYTE_REGISTER(iot, ioh, IOPB_TICKLE, ADV_TICKLE_A);
|
||||
if (sc->chip_type == ADV_CHIP_ASC3550)
|
||||
{
|
||||
if (sc->chip_type == ADV_CHIP_ASC3550) {
|
||||
/*
|
||||
* Clear the tickle value. In the ASC-3550 the RISC flag
|
||||
* command 'clr_tickle_a' does not work unless the host
|
||||
|
@ -2950,8 +2939,7 @@ ADW_SOFTC *sc;
|
|||
* the SCSI Bus Reset signal.
|
||||
*/
|
||||
status = AdvSendIdleCmd(sc, (u_int16_t) IDLE_CMD_SCSI_RESET_START, 0L);
|
||||
if (status != ADW_TRUE)
|
||||
{
|
||||
if (status != ADW_TRUE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -2968,8 +2956,7 @@ ADW_SOFTC *sc;
|
|||
* the SCSI Bus Reset signal and purges any pending requests.
|
||||
*/
|
||||
status = AdvSendIdleCmd(sc, (u_int16_t) IDLE_CMD_SCSI_RESET_END, 0L);
|
||||
if (status != ADW_TRUE)
|
||||
{
|
||||
if (status != ADW_TRUE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -3007,8 +2994,7 @@ ADW_SOFTC *sc;
|
|||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_PPR_ABLE, ppr_able);
|
||||
}
|
||||
ADW_READ_WORD_LRAM(iot, ioh, ASC_MC_TAGQNG_ABLE, tagqng_able);
|
||||
for (tid = 0; tid <= ADW_MAX_TID; tid++)
|
||||
{
|
||||
for (tid = 0; tid <= ADW_MAX_TID; tid++) {
|
||||
ADW_READ_BYTE_LRAM(iot, ioh, ASC_MC_NUMBER_OF_MAX_CMD + tid,
|
||||
max_cmd[tid]);
|
||||
}
|
||||
|
@ -3105,21 +3091,20 @@ ADW_SOFTC *sc;
|
|||
u_int32_t irq_next_pa;
|
||||
ADW_SCSI_REQ_Q *scsiq;
|
||||
ADW_CCB *ccb;
|
||||
int s;
|
||||
|
||||
|
||||
s = splbio();
|
||||
|
||||
/* Reading the register clears the interrupt. */
|
||||
int_stat = ADW_READ_BYTE_REGISTER(iot, ioh, IOPB_INTR_STATUS_REG);
|
||||
|
||||
if ((int_stat & (ADW_INTR_STATUS_INTRA | ADW_INTR_STATUS_INTRB |
|
||||
ADW_INTR_STATUS_INTRC)) == 0) {
|
||||
splx(s);
|
||||
return ADW_FALSE;
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, sc->sc_control->dmamap_xfer, 0,
|
||||
sc->sc_control->dmamap_xfer->dm_mapsize,
|
||||
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(sc->sc_dmat, sc->sc_control->dmamap_xfer);
|
||||
|
||||
/*
|
||||
* Notify the driver of an asynchronous microcode condition by
|
||||
* calling the ADV_DVC_VAR.async_callback function. The function
|
||||
|
@ -3226,6 +3211,8 @@ ADW_SOFTC *sc;
|
|||
*/
|
||||
}
|
||||
|
||||
splx(s);
|
||||
|
||||
return ADW_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: adwlib.h,v 1.8 2000/04/30 18:52:15 dante Exp $ */
|
||||
/* $NetBSD: adwlib.h,v 1.9 2000/05/08 17:21:34 dante Exp $ */
|
||||
|
||||
/*
|
||||
* Definitions for low level routines and data structures
|
||||
|
@ -63,6 +63,13 @@
|
|||
#define ADW_LIB_VERSION_MAJOR 5
|
||||
#define ADW_LIB_VERSION_MINOR 8
|
||||
|
||||
|
||||
/* If the result wraps when calculating tenths, return 0. */
|
||||
#define ADW_TENTHS(num, den) \
|
||||
(((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
|
||||
0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
|
||||
|
||||
|
||||
/*
|
||||
* Define Adv Reset Hold Time grater than 25 uSec.
|
||||
* See AdvResetSCSIBus() for more info.
|
||||
|
@ -987,10 +994,6 @@ typedef struct adw_sg_block {
|
|||
#define CCB_HASH_SHIFT 9
|
||||
#define CCB_HASH(x) ((((x)) >> CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
|
||||
|
||||
#define CARRIER_HASH_SIZE 32 /* hash table size for phystokv */
|
||||
#define CARRIER_HASH_SHIFT 9
|
||||
#define CARRIER_HASH(x) ((((x)) >> CARRIER_HASH_SHIFT) & (CARRIER_HASH_SIZE - 1))
|
||||
|
||||
typedef int (* ADW_CALLBACK) (int);
|
||||
|
||||
typedef struct adw_softc {
|
||||
|
@ -1006,9 +1009,9 @@ typedef struct adw_softc {
|
|||
|
||||
struct adw_control *sc_control; /* control structures */
|
||||
|
||||
struct adw_carrier *sc_carrhash[CARRIER_HASH_SIZE];
|
||||
struct adw_ccb *sc_ccbhash[CCB_HASH_SIZE];
|
||||
TAILQ_HEAD(, adw_ccb) sc_free_ccb, sc_waiting_ccb;
|
||||
TAILQ_HEAD(adw_pending_ccb, adw_ccb) sc_pending_ccb;
|
||||
struct scsipi_link sc_link; /* prototype for devs */
|
||||
struct scsipi_adapter sc_adapter;
|
||||
|
||||
|
@ -1086,8 +1089,6 @@ typedef struct adw_scsi_req_q {
|
|||
*/
|
||||
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;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue