📄 isp.c
字号:
((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; isp->isp_sendmarker = 1; isp_mark_getpdb_all(isp); isp_async(isp, ISPASYNC_LOOP_DOWN, NULL); break; case ASYNC_LOOP_RESET: ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; isp->isp_sendmarker = 1; isp_mark_getpdb_all(isp); PRINTF("%s: Loop RESET\n", isp->isp_name);#ifdef ISP_TARGET_MODE isp_notify_ack(isp, NULL);#endif break; case ASYNC_PDB_CHANGED: isp->isp_sendmarker = 1; isp_mark_getpdb_all(isp); PRINTF("%s: Port Database Changed\n", isp->isp_name); break; case ASYNC_CHANGE_NOTIFY: break; default: PRINTF("%s: unknown async code 0x%x\n", isp->isp_name, mbox); break; } return (fast_post_handle);}static intisp_handle_other_response(isp, sp, optrp) struct ispsoftc *isp; ispstatusreq_t *sp; u_int8_t *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);#ifdef ISP_TARGET_MODE case RQSTYPE_NOTIFY_ACK: { 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: { 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: 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, lun;#ifdef ISP2100_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: PRINTF("%s: ATIO2 Path Invalid\n", isp->isp_name); break; case ATIO_NOCAP: PRINTF("%s: ATIO2 No Cap\n", isp->isp_name); break; case ATIO_BDR_MSG: PRINTF("%s: ATIO2 BDR Received\n", isp->isp_name); break; case ATIO_CDB_RECEIVED: ct2 = &local; break; default: PRINTF("%s: unknown req_status 0x%x\n", isp->isp_name, at2->req_status); break; } if (ct2 == NULL) { /* * Just do an ACCEPT on this fellow. */ at2->req_header.rqs_entry_type = RQSTYPE_ATIO2; at2->req_header.rqs_flags = 0; at2->req_flags = 1; ireqp = at2; reqsize = sizeof (*at2); break; } PRINTF("%s: datalen %d cdb0=0x%x\n", isp->isp_name, at2->req_datalen, at2->req_cdb[0]); 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; ct2->req_header.rqs_seqno = isp->isp_seqno++; ct2->req_handle = (at2->req_initiator << 16) | lun;#ifndef ISP2100_SCCLUN ct2->req_lun = lun;#endif ct2->req_initiator = at2->req_initiator; ct2->req_rxid = at2->req_rxid; ct2->req_flags = CTIO_SEND_STATUS; switch (at2->req_cdb[0]) { case 0x0: /* TUR */ ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE0; ct2->req_m.mode0.req_scsi_status = CTIO2_STATUS_VALID; break; case 0x3: /* REQUEST SENSE */ case 0x12: /* INQUIRE */ ct2->req_flags |= CTIO_SEND_DATA | CTIO2_SMODE0; ct2->req_m.mode0.req_scsi_status = CTIO2_STATUS_VALID; ct2->req_seg_count = 1; if (at2->req_cdb[0] == 0x12) { s = sizeof (tgtiqd); MEMCPY(fcp->isp_scratch, tgtiqd, s); } else { s = at2->req_datalen; MEMZERO(fcp->isp_scratch, s); } ct2->req_m.mode0.req_dataseg[0].ds_base = fcp->isp_scdma; ct2->req_m.mode0.req_dataseg[0].ds_count = s; ct2->req_m.mode0.req_datalen = s;#if 1 if (at2->req_datalen < s) { ct2->req_m.mode1.req_scsi_status |= CTIO2_RESP_VALID|CTIO2_RSPOVERUN; } else if (at2->req_datalen > s) { ct2->req_m.mode1.req_scsi_status |= CTIO2_RESP_VALID|CTIO2_RSPUNDERUN; }#endif break; default: /* ALL OTHERS */ ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE1; ct2->req_m.mode1.req_scsi_status = 0;#if 1 if (at2->req_datalen) { ct2->req_m.mode1.req_scsi_status |= CTIO2_RSPUNDERUN; ct2->req_resid[0] = at2->req_datalen & 0xff; ct2->req_resid[1] = (at2->req_datalen >> 8) & 0xff; ct2->req_resid[2] = (at2->req_datalen >> 16) & 0xff; ct2->req_resid[3] = (at2->req_datalen >> 24) & 0xff; }#endif if ((at2->req_status & ATIO_SENSEVALID) == 0) { ct2->req_m.mode1.req_sense_len = 18; ct2->req_m.mode1.req_scsi_status |= 2; ct2->req_m.mode1.req_response[0] = 0x70; ct2->req_m.mode1.req_response[2] = 0x2; } else { ct2->req_m.mode1.req_sense_len = 18; ct2->req_m.mode1.req_scsi_status |= at2->req_scsi_status; MEMCPY(ct2->req_m.mode1.req_response, at2->req_sense, sizeof (at2->req_sense)); } break; } reqsize = sizeof (*ct2); ireqp = ct2; break; } case RQSTYPE_CTIO2: { ispatiot2_t *at2; ispctiot2_t *ct2 = (ispctiot2_t *) sp; PRINTF("%s: CTIO2 returned status 0x%x\n", isp->isp_name, ct2->req_status); /* * Return the ATIO to the board. */ at2 = (ispatiot2_t *) sp; at2->req_header.rqs_entry_type = RQSTYPE_ATIO2; at2->req_header.rqs_entry_count = 1; at2->req_header.rqs_flags = 0; at2->req_header.rqs_seqno = isp->isp_seqno++; at2->req_status = 1; reqsize = sizeof (*at2); 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, sp->req_header.rqs_entry_type); break; } if (reqsize) { void *reqp; 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 other response\n", isp->isp_name); } else { MEMCPY(reqp, ireqp, reqsize); ISP_WRITE(isp, INMAILBOX4, iptr); isp->isp_reqidx = iptr; } } return (0);}#ifdef ISP_TARGET_MODEstatic 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 voidisp_tmd_newcmd_dflt(arg0, cmdp) void *arg0; tmd_cmd_t *cmdp;{}static voidisp_tmd_event_dflt(arg0, event) void *arg0; int event;{}static voidisp_tmd_notify_dflt(arg0, npt) void *arg0; tmd_notify_t *npt;{}/* * Locks held, and ints disabled (if FC). * * XXX: SETUP ONLY FOR INITIAL ENABLING RIGHT NOW */static intisp_modify_lun(isp, lun, icnt, ccnt) struct ispsoftc *isp; int lun; /* logical unit to enable, modify, or disable */ int icnt; /* immediate notify count */ int ccnt; /* command count */{ isplun_t *ip = NULL; u_int8_t iptr, optr; optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); iptr = isp->isp_reqidx; ip = (isplun_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN); if (iptr == optr) { PRINTF("%s: Request Queue Overflow in isp_modify_lun\n", isp->isp_name); return (-1); } 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++; ip->req_handle = RQSTYPE_ENABLE_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 */ ISP_WRITE(isp, INMAILBOX4, iptr); isp->isp_reqidx = iptr; return (0);}static voidisp_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; MEMZERO((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 { MEMCPY(reqp, ireqp, 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 voidisp_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) { 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); } else { PRINTF("%s: Bus Phase Sequence With No Sense\n", isp->isp_name); } (*isp->isp_tm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -