+ Some basic deadchip detection.
+ Enable FIFO bursts, but also detect bogus 1040A with busted FIFO. + Use new MEMZERO crossplatform define. + Handle RQCS_QUEUE_FULL status case and let upper layer parse SCSI ststus byte if nonzero (should be 0x28- Queue Full status) + Fold ISP_NVRAM_FIFO_THRESHOLD_128 into isp_fifo_threshold tag.
This commit is contained in:
parent
f1dfa06e13
commit
9d702f60ed
136
sys/dev/ic/isp.c
136
sys/dev/ic/isp.c
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: isp.c,v 1.29 1998/12/28 19:10:43 mjacob Exp $ */
|
||||
/* release_12_28_98_A */
|
||||
/* $NetBSD: isp.c,v 1.30 1999/01/10 05:07:53 mjacob Exp $ */
|
||||
/* release_12_28_98_A+ */
|
||||
/*
|
||||
* Machine and OS Independent (well, as best as possible)
|
||||
* code for the Qlogic ISP SCSI adapters.
|
||||
@ -128,7 +128,7 @@ isp_reset(isp)
|
||||
{
|
||||
static char once = 1;
|
||||
mbreg_t mbs;
|
||||
int loops, i, dodnld = 1;
|
||||
int loops, i, dodnld = 1, deadchip;
|
||||
char *revname;
|
||||
|
||||
isp->isp_state = ISP_NILSTATE;
|
||||
@ -139,16 +139,26 @@ isp_reset(isp)
|
||||
* here.
|
||||
*/
|
||||
isp->isp_dblev = DFLT_DBLEVEL;
|
||||
deadchip = ISP_READ(isp, HCCR) & HCCR_RESET;
|
||||
if (deadchip) {
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
|
||||
if (ISP_READ(isp, HCCR) & HCCR_RESET) {
|
||||
isp_dumpregs(isp, "still reset after release");
|
||||
SYS_DELAY(1000);
|
||||
} else {
|
||||
deadchip = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (isp->isp_type & ISP_HA_FC) {
|
||||
revname = "2100";
|
||||
} else {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
|
||||
int rev = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
|
||||
switch (rev) {
|
||||
i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
|
||||
switch (i) {
|
||||
default:
|
||||
PRINTF("%s: unknown chip rev. 0x%x- assuming a 1020\n",
|
||||
isp->isp_name, rev);
|
||||
isp->isp_name, i);
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
revname = "1020";
|
||||
@ -185,16 +195,20 @@ isp_reset(isp)
|
||||
* Try and figure out if we're connected to a differential bus.
|
||||
* You have to pause the RISC processor to read SXP registers.
|
||||
*/
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
|
||||
i = 100;
|
||||
while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
|
||||
SYS_DELAY(20);
|
||||
if (--i == 0) {
|
||||
PRINTF("%s: unable to pause RISC processor\n",
|
||||
isp->isp_name);
|
||||
i = -1;
|
||||
break;
|
||||
if (deadchip == 0) {
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
|
||||
i = 100;
|
||||
while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
|
||||
SYS_DELAY(20);
|
||||
if (--i == 0) {
|
||||
isp_dumpregs(isp,
|
||||
"cannot stop RISC processor");
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
if (i > 0) {
|
||||
if (isp->isp_bustype != ISP_BT_SBUS) {
|
||||
@ -229,9 +243,10 @@ isp_reset(isp)
|
||||
sdp->isp_clock = 40;
|
||||
}
|
||||
/*
|
||||
* Restart processor
|
||||
* Restart processor, if necessary.
|
||||
*/
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
|
||||
if (deadchip == 0)
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
|
||||
}
|
||||
/*
|
||||
* Machine dependent clock (if set) overrides
|
||||
@ -249,7 +264,7 @@ isp_reset(isp)
|
||||
*/
|
||||
ISP_RESET0(isp);
|
||||
|
||||
if (once == 1) {
|
||||
if (once == 1 && deadchip == 0) {
|
||||
once = 0;
|
||||
/*
|
||||
* Get the current running firmware revision out of the
|
||||
@ -270,6 +285,7 @@ isp_reset(isp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Hit the chip over the head with hammer,
|
||||
* and give the ISP a chance to recover.
|
||||
@ -337,9 +353,21 @@ isp_reset(isp)
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
|
||||
SYS_DELAY(100);
|
||||
|
||||
/*
|
||||
* Establish some initial burst rate thingies
|
||||
* (only for the 1XX0 boards). This really should
|
||||
* be done later after fetching from NVRAM.
|
||||
*/
|
||||
if (isp->isp_type & ISP_HA_SCSI) {
|
||||
ISP_SETBITS(isp, BIU_CONF1, isp->isp_mdvec->dv_conf1);
|
||||
if (isp->isp_mdvec->dv_conf1 & BIU_BURST_ENABLE) {
|
||||
u_int16_t conf1 = isp->isp_mdvec->dv_conf1;
|
||||
/*
|
||||
* Busted FIFO. Turn off all but burst enables.
|
||||
*/
|
||||
if (isp->isp_type == ISP_HA_SCSI_1040A) {
|
||||
conf1 &= BIU_BURST_ENABLE;
|
||||
}
|
||||
ISP_SETBITS(isp, BIU_CONF1, conf1);
|
||||
if (conf1 & BIU_BURST_ENABLE) {
|
||||
ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);
|
||||
ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);
|
||||
}
|
||||
@ -737,7 +765,7 @@ isp_fibre_init(isp)
|
||||
|
||||
|
||||
icbp = (isp_icb_t *) fcp->isp_scratch;
|
||||
bzero(icbp, sizeof (*icbp));
|
||||
MEMZERO(icbp, sizeof (*icbp));
|
||||
|
||||
icbp->icb_version = ICB_VERSION1;
|
||||
#ifdef ISP_TARGET_MODE
|
||||
@ -936,7 +964,7 @@ ispscsicmd(xs)
|
||||
u_int8_t niptr;
|
||||
ispmarkreq_t *marker = (ispmarkreq_t *) reqp;
|
||||
|
||||
bzero((void *) marker, sizeof (*marker));
|
||||
MEMZERO((void *) marker, sizeof (*marker));
|
||||
marker->req_header.rqs_entry_count = 1;
|
||||
marker->req_header.rqs_entry_type = RQSTYPE_MARKER;
|
||||
marker->req_modifier = SYNC_ALL;
|
||||
@ -963,7 +991,7 @@ ispscsicmd(xs)
|
||||
iptr = niptr;
|
||||
}
|
||||
|
||||
bzero((void *) reqp, UZSIZE);
|
||||
MEMZERO((void *) reqp, UZSIZE);
|
||||
reqp->req_header.rqs_entry_count = 1;
|
||||
if (isp->isp_type & ISP_HA_FC) {
|
||||
reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
|
||||
@ -1030,7 +1058,7 @@ ispscsicmd(xs)
|
||||
#endif
|
||||
|
||||
}
|
||||
bcopy((void *)XS_CDBP(xs), reqp->req_cdb, XS_CDBLEN(xs));
|
||||
memcpy(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs));
|
||||
|
||||
IDPRINTF(5, ("%s(%d.%d): START%d cmd 0x%x datalen %d\n", isp->isp_name,
|
||||
XS_TGT(xs), XS_LUN(xs), reqp->req_header.rqs_seqno,
|
||||
@ -1291,14 +1319,14 @@ isp_intr(arg)
|
||||
XS_STS(xs) = sp->req_scsi_status & 0xff;
|
||||
if (isp->isp_type & ISP_HA_SCSI) {
|
||||
if (sp->req_state_flags & RQSF_GOT_SENSE) {
|
||||
bcopy(sp->req_sense_data, XS_SNSP(xs),
|
||||
memcpy(XS_SNSP(xs), sp->req_sense_data,
|
||||
XS_SNSLEN(xs));
|
||||
XS_SNS_IS_VALID(xs);
|
||||
}
|
||||
} else {
|
||||
if (XS_STS(xs) == SCSI_CHECK) {
|
||||
XS_SNS_IS_VALID(xs);
|
||||
bcopy(sp->req_sense_data, XS_SNSP(xs),
|
||||
memcpy(XS_SNSP(xs), sp->req_sense_data,
|
||||
XS_SNSLEN(xs));
|
||||
sp->req_state_flags |= RQSF_GOT_SENSE;
|
||||
}
|
||||
@ -1318,8 +1346,9 @@ isp_intr(arg)
|
||||
} else {
|
||||
PRINTF("%s: unknown return %x\n", isp->isp_name,
|
||||
sp->req_header.rqs_entry_type);
|
||||
if (XS_NOERR(xs))
|
||||
if (XS_NOERR(xs)) {
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
}
|
||||
if (isp->isp_type & ISP_HA_SCSI) {
|
||||
XS_RESID(xs) = sp->req_resid;
|
||||
@ -1663,7 +1692,7 @@ isp_handle_other_response(isp, sp, optrp)
|
||||
}
|
||||
PRINTF("%s: datalen %d cdb0=0x%x\n", isp->isp_name,
|
||||
at2->req_datalen, at2->req_cdb[0]);
|
||||
bzero ((void *) ct2, sizeof (*ct2));
|
||||
MEMZERO((void *) ct2, sizeof (*ct2));
|
||||
ct2->req_header.rqs_entry_type = RQSTYPE_CTIO2;
|
||||
ct2->req_header.rqs_entry_count = 1;
|
||||
ct2->req_header.rqs_flags = 0;
|
||||
@ -1689,10 +1718,10 @@ isp_handle_other_response(isp, sp, optrp)
|
||||
ct2->req_seg_count = 1;
|
||||
if (at2->req_cdb[0] == 0x12) {
|
||||
s = sizeof(tgtiqd);
|
||||
bcopy((void *)tgtiqd, fcp->isp_scratch, s);
|
||||
memcpy(fcp->isp_scratch, tgtiqd, s);
|
||||
} else {
|
||||
s = at2->req_datalen;
|
||||
bzero(fcp->isp_scratch, s);
|
||||
MEMZERO(fcp->isp_scratch, s);
|
||||
}
|
||||
ct2->req_m.mode0.req_dataseg[0].ds_base =
|
||||
fcp->isp_scdma;
|
||||
@ -1744,9 +1773,8 @@ isp_handle_other_response(isp, sp, optrp)
|
||||
ct2->req_m.mode1.req_sense_len = 18;
|
||||
ct2->req_m.mode1.req_scsi_status |=
|
||||
at2->req_scsi_status;
|
||||
bcopy((void *)at2->req_sense,
|
||||
(void *)ct2->req_m.mode1.req_response,
|
||||
sizeof (at2->req_sense));
|
||||
memcpy(ct2->req_m.mode1.req_response,
|
||||
at2->req_sense, sizeof (at2->req_sense));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1798,7 +1826,7 @@ isp_handle_other_response(isp, sp, optrp)
|
||||
PRINTF("%s: Request Queue Overflow other response\n",
|
||||
isp->isp_name);
|
||||
} else {
|
||||
bcopy(ireqp, reqp, reqsize);
|
||||
memcpy(reqp, ireqp, reqsize);
|
||||
ISP_WRITE(isp, INMAILBOX4, iptr);
|
||||
isp->isp_reqidx = iptr;
|
||||
}
|
||||
@ -1862,7 +1890,7 @@ isp_modify_lun(isp, lun, icnt, ccnt)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bzero((void *) ip, sizeof (*ip));
|
||||
MEMZERO((void *) ip, sizeof (*ip));
|
||||
ip->req_header.rqs_entry_type = RQSTYPE_ENABLE_LUN;
|
||||
ip->req_header.rqs_entry_count = 1;
|
||||
ip->req_header.rqs_seqno = isp->isp_seqno++;
|
||||
@ -1890,7 +1918,7 @@ isp_notify_ack(isp, ptrp)
|
||||
na_entry_t _nas;
|
||||
} un;
|
||||
|
||||
bzero((caddr_t)&un, sizeof (un));
|
||||
MEMZERO((caddr_t)&un, sizeof (un));
|
||||
un._nas.na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
|
||||
un._nas.na_header.rqs_entry_count = 1;
|
||||
|
||||
@ -1926,7 +1954,7 @@ isp_notify_ack(isp, ptrp)
|
||||
PRINTF("%s: Request Queue Overflow For isp_notify_ack\n",
|
||||
isp->isp_name);
|
||||
} else {
|
||||
bcopy(ireqp, reqp, sizeof (un));
|
||||
memcpy(reqp, ireqp, sizeof (un));
|
||||
ISP_WRITE(isp, INMAILBOX4, iptr);
|
||||
isp->isp_reqidx = iptr;
|
||||
}
|
||||
@ -1981,8 +2009,7 @@ isp_handle_atio (isp, aep)
|
||||
|
||||
|
||||
if (status & TGTSVALID) {
|
||||
bcopy((caddr_t) aep->at_sense,
|
||||
(caddr_t) &cdp->cd_sensedata,
|
||||
memcpy(&cdp->cd_sensedata, aep->at_sense,
|
||||
sizeof (cdp->cd_sensedata));
|
||||
PRINTF("%s: Bus Phase Sequence error key 0x%x\n",
|
||||
isp->isp_name, cdp->cd_sensedata[2] & 0xf);
|
||||
@ -2023,7 +2050,7 @@ isp_handle_atio (isp, aep)
|
||||
cdp->cd_lun = aep->at_lun;
|
||||
cdp->cd_tagtype = aep->at_tag_type;
|
||||
cdp->cd_tagval = aep->at_tag_val;
|
||||
bcopy(aep->at_cdb, cdp->cd_cdb, 16);
|
||||
memcpy(cdp->cd_cdb, aep->at_cdb, 16);
|
||||
PRINTF("%s: CDB 0x%x itl %d/%d/%d\n", isp->isp_name,
|
||||
cdp->cd_cdb[0], cdp->cd_iid, cdp->cd_tgt, cdp->cd_lun);
|
||||
(*isp->isp_tmd_newcmd)(isp, cdp);
|
||||
@ -2099,7 +2126,7 @@ isp_handle_atio2(isp, aep)
|
||||
cdp->cd_iid = aep->at_iid;
|
||||
cdp->cd_tgt = 0;
|
||||
cdp->cd_lun = aep->at_lun;
|
||||
bcopy(aep->at_cdb, cdp->cd_cdb, 16);
|
||||
memcpy(cdp->cd_cdb, aep->at_cdb, 16);
|
||||
cdp->cd_rxid = aep->at_rxid;
|
||||
cdp->cp_origdlen = aep->at_datalen;
|
||||
cdp->cp_totbytes = 0;
|
||||
@ -2296,8 +2323,17 @@ isp_parse_status(isp, sp, xs)
|
||||
break;
|
||||
|
||||
case RQCS_QUEUE_FULL:
|
||||
PRINTF("%s: internal queues full for target %d lun %d\n",
|
||||
isp->isp_name, XS_TGT(xs), XS_LUN(xs));
|
||||
PRINTF("%s: internal queues full for target %d lun %d "
|
||||
"status 0x%x\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs),
|
||||
XS_STS(xs));
|
||||
/*
|
||||
* If QFULL or some other status byte is set, then this
|
||||
* isn't an error, per se.
|
||||
*/
|
||||
if (XS_STS(xs) != 0) {
|
||||
XS_SETERR(xs, HBA_NOERROR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case RQCS_PHASE_SKIPPED:
|
||||
@ -3196,9 +3232,9 @@ isp_read_nvram(isp)
|
||||
if (isp->isp_type & ISP_HA_SCSI) {
|
||||
sdparam *sdp = (sdparam *) isp->isp_param;
|
||||
|
||||
/* XXX CHECK THIS FOR SANITY XXX */
|
||||
sdp->isp_fifo_threshold =
|
||||
ISP_NVRAM_FIFO_THRESHOLD(nvram_data);
|
||||
ISP_NVRAM_FIFO_THRESHOLD(nvram_data) |
|
||||
(ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2);
|
||||
|
||||
sdp->isp_initiator_id =
|
||||
ISP_NVRAM_INITIATOR_ID(nvram_data);
|
||||
@ -3240,8 +3276,6 @@ isp_read_nvram(isp)
|
||||
sdp->isp_tag_aging =
|
||||
ISP_NVRAM_TAG_AGE_LIMIT(nvram_data);
|
||||
|
||||
/* XXX ISP_NVRAM_FIFO_THRESHOLD_128 XXX */
|
||||
|
||||
sdp->isp_selection_timeout =
|
||||
ISP_NVRAM_SELECTION_TIMEOUT(nvram_data);
|
||||
|
||||
@ -3250,6 +3284,12 @@ isp_read_nvram(isp)
|
||||
|
||||
sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
|
||||
|
||||
#if 0
|
||||
PRINTF("%s: fifo_threshold = 0x%x cbena%d dbena%d\n",
|
||||
isp->isp_name, sdp->isp_fifo_threshold,
|
||||
sdp->isp_cmd_dma_burst_enable,
|
||||
sdp->isp_data_dma_burst_enabl);
|
||||
#endif
|
||||
for (i = 0; i < 16; i++) {
|
||||
sdp->isp_devparam[i].dev_enable =
|
||||
ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i);
|
||||
|
Loading…
Reference in New Issue
Block a user