diff options
author | mjacob <mjacob@FreeBSD.org> | 1998-12-05 01:33:57 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 1998-12-05 01:33:57 +0000 |
commit | 6b499c42bc3d7e3dc70bedf23e5d92e6e371516e (patch) | |
tree | ce7322e8da9a4c05c9796fc61787cab50650071f /sys/dev/isp | |
parent | ee4de20504e3edb71b0725bce3b9d63fe6098f4a (diff) | |
download | FreeBSD-src-6b499c42bc3d7e3dc70bedf23e5d92e6e371516e.zip FreeBSD-src-6b499c42bc3d7e3dc70bedf23e5d92e6e371516e.tar.gz |
Remove the Target mode functions until they're in better shape. Implement some
suggested compilation cleanups from Eklund. Wire down a hard loop id if we are
not on a platform that has the ability to get to a PCI BIOS (it still will
float to the ID it gets after a LIP but at least we can try). Clarify that the
expanded lun is based upon SCCLUN defines (in f/w).
Diffstat (limited to 'sys/dev/isp')
-rw-r--r-- | sys/dev/isp/isp.c | 625 |
1 files changed, 534 insertions, 91 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index b937750..cb62c5e 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -1,4 +1,5 @@ -/* $FreeBSD$ */ +/* $Id: $ */ +/* isp.c 1.27 */ /* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. @@ -63,7 +64,7 @@ /* * Local static data */ -#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) +#ifdef ISP_TARGET_MODE static const char tgtiqd[36] = { 0x03, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x51, 0x4C, 0x4F, 0x47, 0x49, 0x43, 0x20, 0x20, @@ -88,11 +89,16 @@ static const char tgtiqd[36] = { /* * Local function prototypes. */ -static int isp_parse_async __P((struct ispsoftc *, u_int16_t)); +static int isp_parse_async __P((struct ispsoftc *, int)); static int isp_handle_other_response __P((struct ispsoftc *, ispstatusreq_t *, u_int8_t *)); -#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) +#ifdef ISP_TARGET_MODE static int isp_modify_lun __P((struct ispsoftc *, int, int, int)); +static void isp_notify_ack __P((struct ispsoftc *, void *)); +static void isp_handle_atio __P((struct ispsoftc *, void *)); +static void isp_handle_atio2 __P((struct ispsoftc *, void *)); +static void isp_handle_ctio __P((struct ispsoftc *, void *)); +static void isp_handle_ctio2 __P((struct ispsoftc *, void *)); #endif static void isp_parse_status __P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *)); @@ -101,7 +107,7 @@ static void isp_fw_state __P((struct ispsoftc *)); static void isp_dumpregs __P((struct ispsoftc *, const char *)); static void isp_dumpxflist __P((struct ispsoftc *)); static void isp_prtstst __P((ispstatusreq_t *)); -static char *isp2100_fw_statename __P((u_int8_t)); +static char *isp2100_fw_statename __P((int)); static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *)); static void isp_update __P((struct ispsoftc *)); @@ -706,7 +712,7 @@ isp_fibre_init(isp) fcparam *fcp; isp_icb_t *icbp; mbreg_t mbs; - int count; + int count, loopid; u_int8_t lwfs; fcp = isp->isp_param; @@ -715,16 +721,41 @@ isp_fibre_init(isp) PRINTF("%s: can't setup DMA for mailboxes\n", isp->isp_name); return; } + /* + * For systems that don't have BIOS methods for which + * we can easily change the NVRAM based loopid, we'll + * override that here. Note that when we initialize + * the firmware we may get back a different loopid than + * we asked for anyway. XXX This is probably not the + * best way to figure this out XXX + */ +#ifndef __i386__ + loopid = DEFAULT_LOOPID; +#else + loopid = fcp->isp_loopid; +#endif + icbp = (isp_icb_t *) fcp->isp_scratch; bzero(icbp, sizeof (*icbp)); icbp->icb_version = ICB_VERSION1; - +#ifdef ISP_TARGET_MODE + fcp->isp_fwoptions = ICBOPT_TGT_ENABLE|ICBOPT_INI_TGTTYPE; +#else fcp->isp_fwoptions = 0; -#ifdef ISP2100_TARGET_MODE - fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE | ICBOPT_INI_TGTTYPE; - icbp->icb_iqdevtype = 0x23; /* DPQ_SUPPORTED/PROCESSOR */ +#endif + fcp->isp_fwoptions |= ICBOPT_INI_ADISC|ICBOPT_FAIRNESS; + fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; + fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; +#ifdef CHECKME + fcp->isp_fwoptions |= ICBOPT_USE_PORTNAME; +#endif +#ifdef THIS_WORKED + /* + * This has unhappiness in target mode + */ + fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; #endif icbp->icb_fwoptions = fcp->isp_fwoptions; icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; @@ -737,9 +768,13 @@ isp_fibre_init(isp) icbp->icb_execthrottle = fcp->isp_execthrottle; icbp->icb_retry_delay = fcp->isp_retry_delay; icbp->icb_retry_count = fcp->isp_retry_count; + icbp->icb_hardaddr = fcp->isp_loopid; MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwn); - + if (icbp->icb_fwoptions & ICBOPT_USE_PORTNAME) { + u_int64_t portname = fcp->isp_wwn | (2LL << 56); + MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, portname); + } icbp->icb_rqstqlen = RQUEST_QUEUE_LEN; icbp->icb_rsltqlen = RESULT_QUEUE_LEN; icbp->icb_rqstaddr[RQRSP_ADDR0015] = @@ -788,24 +823,15 @@ isp_fibre_init(isp) isp->isp_residx = 0; /* - * Wait up to 12 seconds for FW to go to READY state. - * This used to be 3 seconds, but that lost. - * - * This is all very much not right. The problem here - * is that the cable may not be plugged in, or there - * may be many many members of the loop that haven't - * been logged into. - * - * This model of doing things doesn't support dynamic - * attachment, so we just plain lose (for now). + * Wait up to 5 seconds for FW to go to READY state. */ lwfs = FW_CONFIG_WAIT; for (count = 0; count < 12000; count++) { isp_fw_state(isp); if (lwfs != fcp->isp_fwstate) { PRINTF("%s: Firmware State %s -> %s\n", - isp->isp_name, isp2100_fw_statename(lwfs), - isp2100_fw_statename(fcp->isp_fwstate)); + isp->isp_name, isp2100_fw_statename((int)lwfs), + isp2100_fw_statename((int)fcp->isp_fwstate)); lwfs = fcp->isp_fwstate; } if (fcp->isp_fwstate == FW_READY) { @@ -828,16 +854,14 @@ isp_fibre_init(isp) } fcp->isp_loopid = mbs.param[1]; fcp->isp_alpa = mbs.param[2]; - PRINTF("%s: Loop ID 0x%x, ALPA 0x%x\n", isp->isp_name, + PRINTF("%s: Loop ID %d, ALPA 0x%x\n", isp->isp_name, fcp->isp_loopid, fcp->isp_alpa); isp->isp_state = ISP_INITSTATE; -#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) +#ifdef ISP_TARGET_MODE DISABLE_INTS(isp); - if (isp->isp_fwrev >= ISP_FW_REV(1, 13)) { - if (isp_modify_lun(isp, 0, 1, 1)) { - PRINTF("%s: failed to establish target mode\n", - isp->isp_name); - } + if (isp_modify_lun(isp, 0, 1, 1)) { + PRINTF("%s: failed to enable target mode\n", + isp->isp_name); } ENABLE_INTS(isp); #endif @@ -1017,10 +1041,17 @@ ispscsicmd(xs) reqp->req_flags = 0; } } - reqp->req_lun_trn = XS_LUN(xs); reqp->req_target = XS_TGT(xs); if (isp->isp_type & ISP_HA_SCSI) { + reqp->req_lun_trn = XS_LUN(xs); reqp->req_cdblen = XS_CDBLEN(xs); + } else { +#ifdef SCCLUN + reqp->req_scclun = XS_LUN(xs); +#else + reqp->req_lun_trn = XS_LUN(xs); +#endif + } bcopy((void *)XS_CDBP(xs), reqp->req_cdb, XS_CDBLEN(xs)); @@ -1122,7 +1153,18 @@ isp_control(isp, ctl, arg) break; } mbs.param[0] = MBOX_ABORT; - mbs.param[1] = XS_TGT(xs) | XS_LUN(xs); +#ifdef SCCLUN + if (isp->isp_type & ISP_HA_FC) { + mbs.param[1] = XS_TGT(xs) << 8; + mbs.param[4] = 0; + mbs.param[5] = 0; + mbs.param[6] = XS_LUN(xs); + } else { + mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs); + } +#else + mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs); +#endif mbs.param[2] = (i+1) >> 16; mbs.param[3] = (i+1) & 0xffff; isp_mboxcmd(isp, &mbs); @@ -1180,7 +1222,7 @@ isp_intr(arg) if (ISP_READ(isp, BIU_SEMA) & 1) { u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - if (isp_parse_async(isp, mbox)) + if (isp_parse_async(isp, (int) mbox)) return (1); ISP_WRITE(isp, BIU_SEMA, 0); } @@ -1320,7 +1362,8 @@ isp_intr(arg) */ if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) { if (XS_NOERR(xs)) { - PRINTF("%s: ARQ Failure\n", isp->isp_name); + PRINTF("%s: ARQ failure for target %d lun %d\n", + isp->isp_name, XS_TGT(xs), XS_LUN(xs)); XS_SETERR(xs, HBA_ARQFAIL); } } @@ -1340,9 +1383,8 @@ isp_intr(arg) } ISP_WRITE(isp, INMAILBOX5, optr); - isp->isp_nactive--; - if (isp->isp_nactive < 0) - isp->isp_nactive = 0; + if (isp->isp_nactive > 0) + isp->isp_nactive--; complist[ndone++] = xs; /* defer completion call until later */ } /* @@ -1369,12 +1411,15 @@ isp_intr(arg) static int isp_parse_async(isp, mbox) struct ispsoftc *isp; - u_int16_t mbox; + int mbox; { switch (mbox) { case ASYNC_BUS_RESET: PRINTF("%s: SCSI bus reset detected\n", isp->isp_name); isp->isp_sendmarker = 1; +#ifdef ISP_TARGET_MODE + isp_notify_ack(isp, NULL); +#endif break; case ASYNC_SYSTEM_ERROR: @@ -1401,10 +1446,16 @@ isp_parse_async(isp, mbox) case ASYNC_TIMEOUT_RESET: PRINTF("%s: timeout initiated SCSI bus reset\n", isp->isp_name); isp->isp_sendmarker = 1; +#ifdef ISP_TARGET_MODE + isp_notify_ack(isp, NULL); +#endif break; - case ASYNC_UNSPEC_TMODE: - PRINTF("%s: mystery async target completion\n", isp->isp_name); + case ASYNC_DEVICE_RESET: + PRINTF("%s: device reset\n", isp->isp_name); +#ifdef ISP_TARGET_MODE + isp_notify_ack(isp, NULL); +#endif break; case ASYNC_EXTMSG_UNDERRUN: @@ -1440,6 +1491,7 @@ isp_parse_async(isp, mbox) break; case ASYNC_CTIO_DONE: + /* Should only occur when Fast Posting Set for 2100s */ PRINTF("%s: CTIO done\n", isp->isp_name); break; @@ -1457,6 +1509,9 @@ isp_parse_async(isp, mbox) case ASYNC_LOOP_RESET: PRINTF("%s: Loop RESET\n", isp->isp_name); +#ifdef ISP_TARGET_MODE + isp_notify_ack(isp, NULL); +#endif break; case ASYNC_PDB_CHANGED: @@ -1483,62 +1538,122 @@ isp_handle_other_response(isp, sp, optrp) u_int8_t iptr, optr; int reqsize = 0; void *ireqp = NULL; +#ifdef ISP_TARGET_MODE + union { + at_entry_t *atio; + at2_entry_t *at2io; + ct_entry_t *ctio; + ct2_entry_t *ct2io; + lun_entry_t *lunen; + in_entry_t *inot; + in_fcentry_t *inot_fc; + na_entry_t *nack; + na_fcentry_t *nack_fc; + void *voidp; +#define atio un.atio +#define at2io un.at2io +#define ctio un.ctio +#define ct2io un.ct2io +#define lunen un.lunen +#define inot un.inot +#define inot_fc un.inot_fc +#define nack un.nack +#define nack_fc un.nack_fc + } un; + + un.voidp = sp; +#endif + switch (sp->req_header.rqs_entry_type) { case RQSTYPE_REQUEST: return (-1); -#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) +#ifdef ISP_TARGET_MODE case RQSTYPE_NOTIFY_ACK: { - ispnotify_t *spx = (ispnotify_t *) sp; - PRINTF("%s: Immediate Notify Ack %d.%d Status 0x%x Sequence " - "0x%x\n", isp->isp_name, spx->req_initiator, spx->req_lun, - spx->req_status, spx->req_sequence); + static const char *f = + "%s: Notify Ack Status 0x%x Sequence Id 0x%x\n" + /* + * The ISP is acknowleding our ack of an Immediate Notify. + */ + if (isp->isp_type & ISP_HA_FC) { + PRINTF(f, isp->isp_name, + nack_fc->na-status, nack_fc->na_seqid); + } else { + PRINTF(f, isp->isp_name, + nack->na_status, nack->na_seqid); + } break; } case RQSTYPE_NOTIFY: { - ispnotify_t *spx = (ispnotify_t *) sp; - - PRINTF("%s: Notify loopid %d to lun %d req_status 0x%x " - "req_task_flags 0x%x seq 0x%x\n", isp->isp_name, spx->req_initiator, spx->req_lun, spx->req_status, - spx->req_task_flags, spx->req_sequence); - reqsize = sizeof (*spx); - spx->req_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; - spx->req_header.rqs_entry_count = 1; - spx->req_header.rqs_flags = 0; - spx->req_header.rqs_seqno = isp->isp_seqno++; - spx->req_handle = (spx->req_initiator<<16) | RQSTYPE_NOTIFY_ACK; - if (spx->req_status == IN_RSRC_UNAVAIL) - spx->req_flags = LUN_INCR_CMD; - else if (spx->req_status == IN_NOCAP) - spx->req_flags = LUN_INCR_IMMED; - else { - reqsize = 0; - } - ireqp = spx; + u_int16_t seqid, status; + + /* + * Either the ISP received a SCSI message it cannot handle + * or some other out of band condition (e.g., Port Logout) + * or it is returning an Immediate Notify entry we sent. + */ + if (isp->isp_type & ISP_HA_FC) { + status = inot_fc->status; + seqid = inot_fc->in_seqid; + } else { + status = inot->status; + seqid = inot->seqid & 0xff; + } + PRINTF("%s: Immediate Notify Status 0x%x Sequence Id 0x%x\n", + isp->isp_name, status, seqid); + + switch (status) { + case IN_MSG_RECEIVED: + case IN_IDE_RECEIVED: + ptisp_got_msg(ptp, &inot); + break; + case IN_RSRC_UNAVAIL: + PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name); + break; + case IN_ABORT_TASK: + PRINTF("%s: Abort Task iid %d rx_id 0x%x\n", + inot_fc->in_iid, seqid); + break; + case IN_PORT_LOGOUT: + PRINTF("%s: Port Logout for Initiator %d\n", + isp->isp_name, inot_fc->in_iid); + break; + default: + PRINTF("%s: bad status (0x%x) in Immediate Notify\n", + isp->isp_name, status); + break; + + } + isp_notify_ack(isp, un.voidp); + reqsize = 0; break; } case RQSTYPE_ENABLE_LUN: - { - isplun_t *ip = (isplun_t *) sp; - if (ip->req_status != 1) { - PRINTF("%s: ENABLE LUN returned status 0x%x\n", - isp->isp_name, ip->req_status); + case RQSTYPE_MODIFY_LUN: + if (lunen->req_status != 1) { + PRINTF("%s: ENABLE/MODIFY LUN returned status 0x%x\n", + isp->isp_name, lunen->req_status); } break; - } case RQSTYPE_ATIO2: { fcparam *fcp = isp->isp_param; ispctiot2_t local, *ct2 = NULL; ispatiot2_t *at2 = (ispatiot2_t *) sp; - int s; + int s, lun; - PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags 0x%x " - "task flags 0x%x exec codes 0x%x\n", isp->isp_name, - at2->req_initiator, at2->req_lun, at2->req_rxid, - at2->req_flags, at2->req_taskflags, at2->req_execodes); +#ifdef SCCLUN + lun = at2->req_scclun; +#else + lun = at2->req_lun; +#endif + PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags0x%x " + "tflags0x%x ecodes0x%x rqstatus0x%x\n", isp->isp_name, + at2->req_initiator, lun, at2->req_rxid, + at2->req_flags, at2->req_taskflags, at2->req_execodes, + at2->req_status); switch (at2->req_status & ~ATIO_SENSEVALID) { case ATIO_PATH_INVALID: @@ -1576,8 +1691,10 @@ isp_handle_other_response(isp, sp, optrp) ct2->req_header.rqs_entry_count = 1; ct2->req_header.rqs_flags = 0; ct2->req_header.rqs_seqno = isp->isp_seqno++; - ct2->req_handle = (at2->req_initiator << 16) | at2->req_lun; - ct2->req_lun = at2->req_lun; + ct2->req_handle = (at2->req_initiator << 16) | lun; +#ifndef SCCLUN + ct2->req_lun = lun; +#endif ct2->req_initiator = at2->req_initiator; ct2->req_rxid = at2->req_rxid; @@ -1604,7 +1721,7 @@ isp_handle_other_response(isp, sp, optrp) fcp->isp_scdma; ct2->req_m.mode0.req_dataseg[0].ds_count = s; ct2->req_m.mode0.req_datalen = s; -#if 0 +#if 1 if (at2->req_datalen < s) { ct2->req_m.mode1.req_scsi_status |= CTIO2_RESP_VALID|CTIO2_RSPOVERUN; @@ -1618,7 +1735,7 @@ isp_handle_other_response(isp, sp, optrp) default: /* ALL OTHERS */ ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE1; ct2->req_m.mode1.req_scsi_status = 0; -#if 0 +#if 1 if (at2->req_datalen) { ct2->req_m.mode1.req_scsi_status |= CTIO2_RSPUNDERUN; @@ -1679,6 +1796,15 @@ isp_handle_other_response(isp, sp, optrp) ireqp = at2; break; } +#undef atio +#undef at2io +#undef ctio +#undef ct2io +#undef lunen +#undef inot +#undef inot_fc +#undef nack +#undef nack_fc #endif default: PRINTF("%s: other response type %x\n", isp->isp_name, @@ -1703,7 +1829,37 @@ isp_handle_other_response(isp, sp, optrp) return (0); } -#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) +#ifdef ISP_TARGET_MODE + +static void isp_tmd_newcmd_dflt __P((void *, tmd_cmd_t *)); +static void isp_tmd_event_dflt __P((void *, int)); +static void isp_tmd_notify_dflt __P((void *, tmd_notify_t *)); + +static void isp_tgt_data_xfer __P ((tmd_cmd_t *)); +static void isp_tgt_endcmd __P ((tmd_cmd_t *, u_int8_t)); +static void isp_tgt_done __P ((tmd_cmd_t *)); + +static void +isp_tmd_newcmd_dflt(arg0, cmdp) + void *arg0; + tmd_cmd_t *cmdp; +{ +} + +static void +isp_tmd_event_dflt(arg0, event) + void *arg0; + int event; +{ +} + +static void +isp_tmd_notify_dflt(arg0, npt) + void *arg0; + tmd_notify_t *npt; +{ +} + /* * Locks held, and ints disabled (if FC). * @@ -1732,10 +1888,11 @@ isp_modify_lun(isp, lun, icnt, ccnt) bzero((void *) ip, sizeof (*ip)); ip->req_header.rqs_entry_type = RQSTYPE_ENABLE_LUN; ip->req_header.rqs_entry_count = 1; - ip->req_header.rqs_flags = 0; ip->req_header.rqs_seqno = isp->isp_seqno++; ip->req_handle = RQSTYPE_ENABLE_LUN; - ip->req_lun = lun; + if (isp->isp_type & ISP_HA_SCSI) { + ip->req_lun = lun; + } ip->req_cmdcount = ccnt; ip->req_imcount = icnt; ip->req_timeout = 0; /* default 30 seconds */ @@ -1743,6 +1900,264 @@ isp_modify_lun(isp, lun, icnt, ccnt) isp->isp_reqidx = iptr; return (0); } + +static void +isp_notify_ack(isp, ptrp) + struct ispsoftc *isp; + void *ptrp; +{ + void *reqp; + u_int8_t iptr, optr; + union { + na_fcentry_t _naf; + na_entry_t _nas; + } un; + + bzero((caddr_t)&un, sizeof (un)); + un._nas.na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; + un._nas.na_header.rqs_entry_count = 1; + + if (isp->isp_type & ISP_HA_FC) { + na_fcentry_t *na = &un._nas; + if (ptrp) { + in_fcentry_t *inp = ptrp; + na->na_iid = inp->in_iid; + na->na_lun = inp->in_lun; + na->na_task_flags = inp->in_task_flags; + na->na_seqid = inp->in_seqid; + na->na_status = inp->in_status; + } else { + na->na_flags = NAFC_RST_CLRD; + } + } else { + na_entry_t *na = &un._nas; + if (ptrp) { + in_entry_t *inp = ptrp; + na->na_iid = inp->in_iid; + na->na_lun = inp->in_lun; + na->na_tgt = inp->in_tgt; + na->na_seqid = inp->in_seqid; + } else { + na->na_flags = NA_RST_CLRD; + } + } + optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); + iptr = isp->isp_reqidx; + reqp = (void *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); + iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN); + if (iptr == optr) { + PRINTF("%s: Request Queue Overflow For isp_notify_ack\n", + isp->isp_name); + } else { + bcopy(ireqp, reqp, sizeof (un)); + ISP_WRITE(isp, INMAILBOX4, iptr); + isp->isp_reqidx = iptr; + } +} + +/* + * These are dummy stubs for now until the outside framework is plugged in. + */ + +static void +isp_handle_atio (isp, aep) + struct ispsoftc *isp; + at_entry_t *aep; +{ + int status, connected; + tmd_cmd_t local, *cdp = &local; + + /* + * Get the ATIO status and see if we're still connected. + */ + status = aep->at_status; + connected = ((aep->at_flags & AT_NODISC) != 0); + + PRINTF("%s: ATIO status=0x%x, connected=%d\n", isp->isp_name, + status, connected); + + /* + * The firmware status (except for the SenseValid bit) indicates + * why this ATIO was sent to us. + * If SenseValid is set, the firware has recommended Sense Data. + * If the Disconnects Disabled bit is set in the flags field, + * we're still connected on the SCSI bus - i.e. the initiator + * did not set DiscPriv in the identify message. We don't care + * about this so it's ignored. + */ + switch(status & ~TGTSVALID) { + case AT_PATH_INVALID: + /* + * ATIO rejected by the firmware due to disabled lun. + */ + PRINTF("%s: Firmware rejected ATIO for disabled lun %d\n", + isp->isp_name, aep->at_lun); + break; + + case AT_PHASE_ERROR: + /* + * Bus Pase Sequence error. + * + * The firmware should have filled in the correct + * sense data. + */ + + + if (status & TGTSVALID) { + bcopy((caddr_t) aep->at_sense, + (caddr_t) &cdp->cd_sensedata, + sizeof (cdp->cd_sensedata)); + PRINTF("%s: Bus Phase Sequence error key 0x%x\n", + isp->isp_name, cdp->cd_sensedata[2] & 0xf); + } else { + PRINTF("%s: Bus Phase Sequence With No Sense\n", + isp->isp_name); + } + (*isp->isp_tmd_newcmd)(isp, cdp); + break; + + case AT_NOCAP: + /* + * Requested Capability not available + * We sent an ATIO that overflowed the firmware's + * command resource count. + */ + PRINTF("%s: Firmware rejected ATIO, command count overflow\n", + isp->isp_name); + break; + + case AT_BDR_MSG: + /* + * If we send an ATIO to the firmware to increment + * its command resource count, and the firmware is + * recovering from a Bus Device Reset, it returns + * the ATIO with this status. + */ + PRINTF("%s: ATIO returned with BDR received\n", isp->isp_name); + break; + + case AT_CDB: + /* + * New CDB + */ + cdp->cd_hba = isp; + cdp->cd_iid = aep->at_iid; + cdp->cd_tgt = aep->at_tgt; + 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); + 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); + break; + + default: + PRINTF("%s: Unknown status (0x%x) in ATIO\n", + isp->isp_name, status); + cdp->cd_hba = isp; + cdp->cd_iid = aep->at_iid; + cdp->cd_tgt = aep->at_tgt; + cdp->cd_lun = aep->at_lun; + cdp->cd_tagtype = aep->at_tag_type; + cdp->cd_tagval = aep->at_tag_val; + isp_tgtcmd_done(cdp); + break; + } +} + +static void +isp_handle_atio2(isp, aep) + struct ispsoftc *isp; + at2_entry_t *aep; +{ + int status; + tmd_cmd_t local, *cdp = &local; + + /* + * Get the ATIO2 status. + */ + status = aep->at_status; + PRINTD("%s: ATIO2 status=0x%x\n", status); + + /* + * The firmware status (except for the SenseValid bit) indicates + * why this ATIO was sent to us. + * If SenseValid is set, the firware has recommended Sense Data. + */ + switch(status & ~TGTSVALID) { + case AT_PATH_INVALID: + /* + * ATIO rejected by the firmware due to disabled lun. + */ + PRINTF("%s: Firmware rejected ATIO2 for disabled lun %d\n", + isp->isp_name, aep->at_lun); + break; + + case AT_NOCAP: + /* + * Requested Capability not available + * We sent an ATIO that overflowed the firmware's + * command resource count. + */ + PRINTF("%s: Firmware rejected ATIO2, command count overflow\n", + isp->isp_name); + break; + + case AT_BDR_MSG: + /* + * If we send an ATIO to the firmware to increment + * its command resource count, and the firmware is + * recovering from a Bus Device Reset, it returns + * the ATIO with this status. + */ + PRINTF("%s: ATIO2 returned with BDR rcvd\n", isp->isp_name); + break; + + case AT_CDB: + /* + * New CDB + */ + cdp->cd_hba = isp; + cdp->cd_iid = aep->at_iid; + cdp->cd_tgt = 0; + cdp->cd_lun = aep->at_lun; + bcopy(aep->at_cdb, cdp->cd_cdb, 16); + cdp->cd_rxid = aep->at_rxid; + cdp->cp_origdlen = aep->at_datalen; + cdp->cp_totbytes = 0; + PRINTF("%s: CDB 0x%x rx_id 0x%x itl %d/%d/%d dlen %d\n", + isp->isp_name, cdp->cd_cdb[0], cdp->cd_tagval, cdp->cd_iid, + cdp->cd_tgt, cdp->cd_lun, aep->at_datalen); + (*isp->isp_tmd_newcmd)(isp, cdp); + break; + + default: + PRINTF("%s: Unknown status (0x%x) in ATIO2\n", + isp->isp_name, status); + cdp->cd_hba = isp; + cdp->cd_iid = aep->at_iid; + cdp->cd_tgt = aep->at_tgt; + cdp->cd_lun = aep->at_lun; + cdp->cp_rxid = aep->at_rxid; + isp_tgtcmd_done(cdp); + break; + } +} + +static void +isp_handle_ctio(isp, cep) + struct ispsoftc *isp; + ct_entry_t *aep; +{ +} + +static void +isp_handle_ctio2(isp, cep) + struct ispsoftc *isp; + at2_entry_t *aep; +{ +} #endif static void @@ -1869,7 +2284,7 @@ isp_parse_status(isp, sp, xs) break; case RQCS_UNEXP_BUS_FREE: - PRINTF("%s: target %d lun %d had unexeptected bus free\n", + PRINTF("%s: target %d lun %d had an unexpected bus free\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs)); break; @@ -2128,6 +2543,29 @@ isp_mboxcmd(isp, mbp) } + /* + * Check for variants + */ +#ifdef SCCLUN + if (isp->isp_type & ISP_HA_FC) { + switch (mbp->param[0]) { + case MBOX_ABORT: + inparam = 7; + break; + case MBOX_ABORT_DEVICE: + case MBOX_START_QUEUE: + case MBOX_STOP_QUEUE: + case MBOX_SINGLE_STEP_QUEUE: + case MBOX_ABORT_QUEUE: + case MBOX_GET_DEV_QUEUE_STATUS: + inparam = 3; + break; + default: + break; + } + } +#endif + command_known: /* @@ -2146,7 +2584,7 @@ command_known: isp->isp_name, ISP_READ(isp, BIU_ISR)); if (ISP_READ(isp, BIU_SEMA) & 1) { u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - if (isp_parse_async(isp, mbox)) + if (isp_parse_async(isp, (int) mbox)) return; ISP_WRITE(isp, BIU_SEMA, 0); } @@ -2275,8 +2713,13 @@ command_known: isp->isp_name, opcode); break; + /* + * Be silent about these... + */ + case ASYNC_LOOP_UP: case ASYNC_LIP_OCCURRED: + case ASYNC_PDB_CHANGED: break; default: @@ -2394,6 +2837,7 @@ again: isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { if (mbs.param[0] == ASYNC_LIP_OCCURRED || + mbs.param[0] == ASYNC_PDB_CHANGED || mbs.param[0] == ASYNC_LOOP_UP) { if (once++ < 2) { goto again; @@ -2649,10 +3093,8 @@ isp_restart(isp) if (XS_NULL(xs)) { continue; } - isp->isp_nactive--; - if (isp->isp_nactive < 0) { - isp->isp_nactive = 0; - } + if (isp->isp_nactive > 0) + isp->isp_nactive--; XS_RESID(xs) = XS_XFRLEN(xs); XS_SETERR(xs, HBA_BUSRESET); XS_CMD_DONE(xs); @@ -2747,7 +3189,7 @@ isp_prtstst(sp) static char * isp2100_fw_statename(state) - u_int8_t state; + int state; { switch(state) { case FW_CONFIG_WAIT: return "Config Wait"; @@ -2948,8 +3390,9 @@ isp_read_nvram(isp) fcp->isp_wwn = wwnstore.full64; wwnstore.full64 = ISP2100_NVRAM_BOOT_NODE_NAME(nvram_data); if (wwnstore.full64 != 0) { - PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n", isp->isp_name, - wwnstore.wds.hi32, wwnstore.wds.lo32); + PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n", + isp->isp_name, wwnstore.wds.hi32, + wwnstore.wds.lo32); } fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); |