diff options
| -rw-r--r-- | sys/dev/isp/isp.c | 183 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.c | 58 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.h | 4 | ||||
| -rw-r--r-- | sys/dev/isp/isp_inline.h | 299 | ||||
| -rw-r--r-- | sys/dev/isp/isp_ioctl.h | 41 | ||||
| -rw-r--r-- | sys/dev/isp/isp_pci.c | 28 | ||||
| -rw-r--r-- | sys/dev/isp/isp_sbus.c | 3 | ||||
| -rw-r--r-- | sys/dev/isp/isp_target.c | 341 | ||||
| -rw-r--r-- | sys/dev/isp/isp_target.h | 134 | ||||
| -rw-r--r-- | sys/dev/isp/isp_tpublic.h | 237 | ||||
| -rw-r--r-- | sys/dev/isp/ispmbox.h | 41 | ||||
| -rw-r--r-- | sys/dev/isp/ispreg.h | 21 | ||||
| -rw-r--r-- | sys/dev/isp/ispvar.h | 42 |
13 files changed, 1016 insertions, 416 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index cc0c3c1ddca5..a9666e9e51ea 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -1,10 +1,8 @@ -/* $FreeBSD$ */ /*- * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. * - * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob - * Feral Software + * Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,6 +41,8 @@ #include <dev/ic/isp_netbsd.h> #endif #ifdef __FreeBSD__ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include <dev/isp/isp_freebsd.h> #endif #ifdef __OpenBSD__ @@ -95,7 +95,7 @@ static const char xact3[] = static const char pskip[] = "SCSI phase skipped for target %d.%d.%d"; static const char topology[] = - "Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'"; + "Loop ID %d, Port ID 0x%x, Loop State 0x%x, Topology '%s'"; static const char swrej[] = "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x"; static const char finmsg[] = @@ -165,6 +165,7 @@ isp_reset(struct ispsoftc *isp) char *btype = "????"; isp->isp_state = ISP_NILSTATE; + MEMZERO(&mbs, sizeof (mbs)); /* * Basic types (SCSI, FibreChannel and PCI or SBus) @@ -252,6 +253,12 @@ isp_reset(struct ispsoftc *isp) case ISP_HA_FC_2312: btype = "2312"; break; + case ISP_HA_FC_2322: + btype = "2322"; + break; + case ISP_HA_FC_2422: + btype = "2422"; + break; default: break; } @@ -677,6 +684,15 @@ again: mbs.param[0] = MBOX_EXEC_FIRMWARE; mbs.param[1] = code_org; + if (IS_2322(isp) || IS_24XX(isp)) { + if (isp->isp_loaded_fw) { + mbs.param[2] = 1; + } else { + mbs.param[2] = 0; + } + mbs.obits |= 2; + } + isp_mboxcmd(isp, &mbs, MBLOGNONE); /* * Give it a chance to start. @@ -746,9 +762,8 @@ again: isp_prt(isp, ISP_LOGDEBUG0, "Firmware Attributes = 0x%x", mbs.param[6]); } - if (ISP_READ(isp, BIU2100_CSR) & BIU2100_PCI64) { - isp_prt(isp, ISP_LOGCONFIG, - "Installed in 64-Bit PCI slot"); + if (IS_2KLOGIN(isp)) { + isp_prt(isp, ISP_LOGCONFIG, "2K Logins Supported"); } } @@ -869,6 +884,7 @@ isp_scsi_init(struct ispsoftc *isp) * Set Retry Delay and Count. * You set both channels at the same time. */ + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SET_RETRY_COUNT; mbs.param[1] = sdp_chan0->isp_retry_count; mbs.param[2] = sdp_chan0->isp_retry_delay; @@ -1048,6 +1064,7 @@ isp_scsi_channel_init(struct ispsoftc *isp, int channel) /* * Set (possibly new) Initiator ID. */ + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SET_INIT_SCSI_ID; mbs.param[1] = (channel << 7) | sdp->isp_initiator_id; isp_mboxcmd(isp, &mbs, MBLOGALL); @@ -1257,9 +1274,9 @@ isp_fibre_init(struct ispsoftc *isp) icbp->icb_hardaddr = loopid; if (icbp->icb_hardaddr >= 125) { /* - * We end up with a Loop ID of 255 for F-Port topologies + * We end up with these Loop IDs for F-Port topologies */ - if (icbp->icb_hardaddr != 255) { + if (icbp->icb_hardaddr != 0xff || icbp->icb_hardaddr != 0x800) { isp_prt(isp, ISP_LOGERR, "bad hard address %u- resetting to zero", icbp->icb_hardaddr); @@ -1354,8 +1371,10 @@ isp_fibre_init(struct ispsoftc *isp) #endif #endif + MEMZERO(&mbs, sizeof (mbs)); + /* - * For 22XX > 2.1.26 && 23XX, set someoptions. + * For 22XX > 2.1.26 && 23XX, set some options. * XXX: Probably okay for newer 2100 f/w too. */ if (ISP_FW_NEWER_THAN(isp, 2, 26, 0)) { @@ -1457,6 +1476,7 @@ isp_getmap(struct ispsoftc *isp, fcpos_map_t *map) fcparam *fcp = (fcparam *) isp->isp_param; mbreg_t mbs; + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP; mbs.param[1] = 0; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -1498,8 +1518,14 @@ isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp) fcparam *fcp = (fcparam *) isp->isp_param; mbreg_t mbs; + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_PORT_DB; - mbs.param[1] = id << 8; + if (IS_2KLOGIN(isp)) { + mbs.param[1] = id; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = id << 8; + } mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); /* @@ -1528,10 +1554,18 @@ isp_get_portname(struct ispsoftc *isp, int loopid, int nodename) u_int64_t wwn = 0; mbreg_t mbs; + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_PORT_NAME; - mbs.param[1] = loopid << 8; - if (nodename) - mbs.param[1] |= 1; + if (IS_2KLOGIN(isp)) { + mbs.param[1] = loopid; + if (nodename) + mbs.param[10] = 1; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = loopid << 8; + if (nodename) + mbs.param[1] |= 1; + } isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { wwn = @@ -1647,6 +1681,7 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) /* * Get our Loop ID (if possible). We really need to have it. */ + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_LOOP_ID; isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { @@ -1661,7 +1696,11 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) } else { fcp->isp_topo = TOPO_NL_PORT; } - fcp->isp_portid = fcp->isp_alpa = mbs.param[2] & 0xff; + /* + * XXX: We can get the AL_PA (low 8 bits) from here. + * XXX: Where do we get the upper 16 bits? + */ + fcp->isp_portid = mbs.param[2] & 0xff; /* * Check to see if we're on a fabric by trying to see if we @@ -1752,7 +1791,7 @@ not_on_fabric: } } - isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, fcp->isp_alpa, + isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]); /* @@ -1966,8 +2005,14 @@ isp_pdb_sync(struct ispsoftc *isp) if (lp->loggedin) { if (lp->force_logout || isp_getpdb(isp, lp->loopid, &pdb) == 0) { + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_FABRIC_LOGOUT; - mbs.param[1] = lp->loopid << 8; + if (IS_2KLOGIN(isp)) { + mbs.param[1] = lp->loopid; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = lp->loopid << 8; + } mbs.param[2] = 0; mbs.param[3] = 0; isp_mboxcmd(isp, &mbs, MBLOGNONE); @@ -1988,8 +2033,14 @@ isp_pdb_sync(struct ispsoftc *isp) loopid = lp - fcp->portdb; lp->loopid = FL_PORT_ID; do { + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_FABRIC_LOGIN; - mbs.param[1] = loopid << 8; + if (IS_2KLOGIN(isp)) { + mbs.param[1] = loopid; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = loopid << 8; + } mbs.param[2] = portid >> 16; mbs.param[3] = portid & 0xffff; isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED | @@ -2104,10 +2155,14 @@ dump_em: lp->valid = 0; isp_prt(isp, ISP_LOGINFO, ldumped, loopid, lp->loopid, lp->portid); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_FABRIC_LOGOUT; - mbs.param[1] = lp->loopid << 8; - mbs.param[2] = 0; - mbs.param[3] = 0; + if (IS_2KLOGIN(isp)) { + mbs.param[1] = lp->loopid; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = lp->loopid << 8; + } isp_mboxcmd(isp, &mbs, MBLOGNONE); if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_SYNCING_PDB) { @@ -2488,6 +2543,7 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) rq->snscb_data[5] = (portid >> 16) & 0xff; isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch); MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -2638,6 +2694,7 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) rq->snscb_fc4_type = ftype; isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch); MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -2715,6 +2772,7 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) isp_put_gxn_id_request(isp, gq, (sns_gxn_id_req_t *) fcp->isp_scratch); MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -2770,6 +2828,7 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) isp_put_gxn_id_request(isp, gq, (sns_gxn_id_req_t *) fcp->isp_scratch); MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -2833,6 +2892,7 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) isp_put_gxn_id_request(isp, gq, (sns_gxn_id_req_t *) fcp->isp_scratch); MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -2934,6 +2994,7 @@ isp_register_fc4_type(struct ispsoftc *isp) #endif FC_SCRATCH_ACQUIRE(isp); isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch); + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); @@ -3273,15 +3334,19 @@ isp_start(XS_T *xs) reqp->req_flags = XS_TAG_TYPE(xs); } } - reqp->req_target = target | (XS_CHANNEL(xs) << 7); if (IS_SCSI(isp)) { + reqp->req_target = target | (XS_CHANNEL(xs) << 7); reqp->req_lun_trn = XS_LUN(xs); reqp->req_cdblen = XS_CDBLEN(xs); + } else if (IS_2KLOGIN(isp)) { + ((ispreqt2e_t *)reqp)->req_target = target; + ((ispreqt2e_t *)reqp)->req_scclun = XS_LUN(xs); + } else if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + ((ispreqt2_t *)reqp)->req_target = target; + ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs); } else { - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) - ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs); - else - ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs); + ((ispreqt2_t *)reqp)->req_target = target; + ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs); } MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); @@ -3333,6 +3398,8 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) int bus, tgt; u_int16_t handle; + MEMZERO(&mbs, sizeof (mbs)); + switch (ctl) { default: isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl); @@ -3369,7 +3436,16 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) tgt = (*((int *) arg)) & 0xffff; bus = (*((int *) arg)) >> 16; mbs.param[0] = MBOX_ABORT_TARGET; - mbs.param[1] = (tgt << 8) | (bus << 15); + if (IS_SCSI(isp)) { + mbs.param[1] = (tgt << 8) | (bus << 15); + } else { + if (IS_2KLOGIN(isp)) { + mbs.param[1] = tgt; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = (tgt << 8); + } + } mbs.param[2] = 3; /* 'delay', in seconds */ isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { @@ -3393,7 +3469,11 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) mbs.param[0] = MBOX_ABORT; if (IS_FC(isp)) { if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - mbs.param[1] = tgt << 8; + if (IS_2KLOGIN(isp)) { + mbs.param[1] = tgt; + } else { + mbs.param[1] = tgt << 8; + } mbs.param[4] = 0; mbs.param[5] = 0; mbs.param[6] = XS_LUN(xs); @@ -3541,7 +3621,7 @@ again: if (isp->isp_mboxbsy) { int i = 0, obits = isp->isp_obits; isp->isp_mboxtmp[i++] = mbox; - for (i = 1; i < MAX_MAILBOX; i++) { + for (i = 1; i < MAX_MAILBOX(isp); i++) { if ((obits & (1 << i)) == 0) { continue; } @@ -4145,8 +4225,6 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) } case ASYNC_LIP_F8: case ASYNC_LIP_OCCURRED: - FCPARAM(isp)->isp_lipseq = - ISP_READ(isp, OUTMAILBOX1); FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp->isp_sendmarker = 1; @@ -4300,7 +4378,7 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) int i, nh; u_int16_t handles[16]; - for (nh = 0, i = 1; i < MAX_MAILBOX; i++) { + for (nh = 0, i = 1; i < MAX_MAILBOX(isp); i++) { if ((bus & (1 << i)) == 0) { continue; } @@ -4716,6 +4794,7 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT || FCPARAM(isp)->isp_topo == TOPO_FL_PORT) { mbreg_t mbs; + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_INIT_LIP; isp_mboxcmd_qnw(isp, &mbs, 1); } @@ -4810,7 +4889,6 @@ isp_mbox_continue(struct ispsoftc *isp) return (-1); } - /* * Clear the previous interrupt. */ @@ -4820,6 +4898,7 @@ isp_mbox_continue(struct ispsoftc *isp) /* * Continue with next word. */ + MEMZERO(&mbs, sizeof (mbs)); ptr = isp->isp_mbxworkp; switch (isp->isp_lastmbxcmd) { case MBOX_WRITE_RAM_WORD: @@ -4840,10 +4919,10 @@ isp_mbox_continue(struct ispsoftc *isp) } -#define HIBYT(x) ((x) >> 0x8) -#define LOBYT(x) ((x) & 0xff) -#define ISPOPMAP(a, b) (((a) << 8) | (b)) -static const u_int16_t mbpscsi[] = { +#define HIWRD(x) ((x) >> 16) +#define LOWRD(x) ((x) & 0xffff) +#define ISPOPMAP(a, b) (((a) << 16) | (b)) +static const u_int32_t mbpscsi[] = { ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ @@ -5039,7 +5118,7 @@ static char *scsi_mbcmd_names[] = { }; #endif -static const u_int16_t mbpfc[] = { +static const u_int32_t mbpfc[] = { ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ @@ -5312,7 +5391,7 @@ static void isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay) { unsigned int ibits, obits, box, opcode; - const u_int16_t *mcp; + const u_int32_t *mcp; if (IS_FC(isp)) { mcp = mbpfc; @@ -5320,9 +5399,11 @@ isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay) mcp = mbpscsi; } opcode = mbp->param[0]; - ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp); - obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp); - for (box = 0; box < MAX_MAILBOX; box++) { + ibits = HIWRD(mcp[opcode]) & NMBOX_BMASK(isp); + obits = LOWRD(mcp[opcode]) & NMBOX_BMASK(isp); + ibits |= mbp->ibits; + obits |= mbp->obits; + for (box = 0; box < MAX_MAILBOX(isp); box++) { if (ibits & (1 << box)) { ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } @@ -5351,7 +5432,7 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) { char *cname, *xname, tname[16], mname[16]; unsigned int lim, ibits, obits, box, opcode; - const u_int16_t *mcp; + const u_int32_t *mcp; if (IS_FC(isp)) { mcp = mbpfc; @@ -5367,8 +5448,11 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) return; } - ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp); - obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp); + ibits = HIWRD(mcp[opcode]) & NMBOX_BMASK(isp); + obits = LOWRD(mcp[opcode]) & NMBOX_BMASK(isp); + + ibits |= mbp->ibits; + obits |= mbp->obits; if (ibits == 0 && obits == 0) { mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; @@ -5381,7 +5465,7 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) */ MBOX_ACQUIRE(isp); - for (box = 0; box < MAX_MAILBOX; box++) { + for (box = 0; box < MAX_MAILBOX(isp); box++) { if (ibits & (1 << box)) { ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } @@ -5418,7 +5502,7 @@ isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask) /* * Copy back output registers. */ - for (box = 0; box < MAX_MAILBOX; box++) { + for (box = 0; box < MAX_MAILBOX(isp); box++) { if (obits & (1 << box)) { mbp->param[box] = isp->isp_mboxtmp[box]; } @@ -5498,6 +5582,7 @@ isp_fw_state(struct ispsoftc *isp) mbreg_t mbs; fcparam *fcp = isp->isp_param; + MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_FW_STATE; isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { @@ -5535,6 +5620,7 @@ isp_update_bus(struct ispsoftc *isp, int bus) } sdp = isp->isp_param; sdp += bus; + MEMZERO(&mbs, sizeof (mbs)); for (tgt = 0; tgt < MAX_TARGETS; tgt++) { u_int16_t flags, period, offset; @@ -5650,6 +5736,7 @@ isp_setdfltparm(struct ispsoftc *isp, int channel) mbreg_t mbs; sdparam *sdp; + MEMZERO(&mbs, sizeof (mbs)); if (IS_FC(isp)) { fcparam *fcp = (fcparam *) isp->isp_param; int nvfail; @@ -6467,6 +6554,7 @@ isp2200_fw_dump(struct ispsoftc *isp) mbreg_t mbs; u_int16_t *ptr; + MEMZERO(&mbs, sizeof (mbs)); ptr = FCPARAM(isp)->isp_dump_data; if (ptr == NULL) { isp_prt(isp, ISP_LOGERR, @@ -6611,6 +6699,7 @@ isp2300_fw_dump(struct ispsoftc *isp) mbreg_t mbs; u_int16_t *ptr; + MEMZERO(&mbs, sizeof (mbs)); ptr = FCPARAM(isp)->isp_dump_data; if (ptr == NULL) { isp_prt(isp, ISP_LOGERR, diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index de468f5f33fb..2268092de2c3 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -1,7 +1,8 @@ /*- * Platform (FreeBSD) dependent common attachment code for Qlogic adapters. * - * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob + * Copyright (c) 1997-2006 by Matthew Jacob + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -507,6 +508,7 @@ ispioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *t { int needmarker; struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr; + u_int16_t loopid; mbreg_t mbs; if (IS_SCSI(isp)) { @@ -516,33 +518,36 @@ ispioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *t memset(&mbs, 0, sizeof (mbs)); needmarker = retval = 0; - + loopid = fct->loopid; + if (IS_2KLOGIN(isp) == 0) { + loopid <<= 8; + } switch (fct->action) { case CLEAR_ACA: mbs.param[0] = MBOX_CLEAR_ACA; - mbs.param[1] = fct->loopid << 8; + mbs.param[1] = loopid; mbs.param[2] = fct->lun; break; case TARGET_RESET: mbs.param[0] = MBOX_TARGET_RESET; - mbs.param[1] = fct->loopid << 8; + mbs.param[1] = loopid; needmarker = 1; break; case LUN_RESET: mbs.param[0] = MBOX_LUN_RESET; - mbs.param[1] = fct->loopid << 8; + mbs.param[1] = loopid; mbs.param[2] = fct->lun; needmarker = 1; break; case CLEAR_TASK_SET: mbs.param[0] = MBOX_CLEAR_TASK_SET; - mbs.param[1] = fct->loopid << 8; + mbs.param[1] = loopid; mbs.param[2] = fct->lun; needmarker = 1; break; case ABORT_TASK_SET: mbs.param[0] = MBOX_ABORT_TASK_SET; - mbs.param[1] = fct->loopid << 8; + mbs.param[1] = loopid; mbs.param[2] = fct->lun; needmarker = 1; break; @@ -606,7 +611,6 @@ static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *); static int isp_handle_platform_atio(struct ispsoftc *, at_entry_t *); static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *); static int isp_handle_platform_ctio(struct ispsoftc *, void *); -static void isp_handle_platform_ctio_fastpost(struct ispsoftc *, u_int32_t); static int isp_handle_platform_notify_scsi(struct ispsoftc *, in_entry_t *); static int isp_handle_platform_notify_fc(struct ispsoftc *, in_fcentry_t *); @@ -1796,19 +1800,6 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) return (0); } -static void -isp_handle_platform_ctio_fastpost(struct ispsoftc *isp, u_int32_t token) -{ - union ccb *ccb; - ccb = isp_find_xs_tgt(isp, token & 0xffff); - KASSERT((ccb != NULL), - ("null ccb in isp_handle_platform_ctio_fastpost")); - isp_destroy_tgt_handle(isp, token & 0xffff); - isp_prt(isp, ISP_LOGTDEBUG1, "CTIOx[%x] fastpost complete", - token & 0xffff); - isp_complete_ctio(ccb); -} - static int isp_handle_platform_notify_scsi(struct ispsoftc *isp, in_entry_t *inp) { @@ -3081,30 +3072,11 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) break; } #ifdef ISP_TARGET_MODE - case ISPASYNC_TARGET_MESSAGE: + case ISPASYNC_TARGET_NOTIFY: { - tmd_msg_t *mp = arg; - isp_prt(isp, ISP_LOGALL, - "bus %d iid %d tgt %d lun %d ttype %x tval %x msg[0]=%x", - mp->nt_bus, (int) mp->nt_iid, (int) mp->nt_tgt, - (int) mp->nt_lun, mp->nt_tagtype, mp->nt_tagval, - mp->nt_msg[0]); - break; - } - case ISPASYNC_TARGET_EVENT: - { - tmd_event_t *ep = arg; - if (ep->ev_event == ASYNC_CTIO_DONE) { - /* - * ACK the interrupt first - */ - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - isp_handle_platform_ctio_fastpost(isp, ep->ev_bus); - break; - } + tmd_notify_t *nt = arg; isp_prt(isp, ISP_LOGALL, - "bus %d event code 0x%x", ep->ev_bus, ep->ev_event); + "target notify code 0x%x", nt->nt_ncode); break; } case ISPASYNC_TARGET_ACTION: diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index 4b3a4d3f95f7..50b46bbab4df 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -1,7 +1,9 @@ /* $FreeBSD$ */ /*- * Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions - * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by Matthew Jacob + * + * Copyright (c) 1997-2006 by Matthew Jacob + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/dev/isp/isp_inline.h b/sys/dev/isp/isp_inline.h index c09ec9cd25dd..e6649b821323 100644 --- a/sys/dev/isp/isp_inline.h +++ b/sys/dev/isp/isp_inline.h @@ -2,10 +2,8 @@ /*- * Qlogic Host Adapter Inline Functions * - * Copyright (c) 1999, 2000, 2001 by Matthew Jacob - * Feral Software + * Copyright (c) 1999-2006 by Matthew Jacob * All rights reserved. - * mjacob@feral.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -314,8 +312,12 @@ isp_put_request(struct ispsoftc *, ispreq_t *, ispreq_t *); static INLINE void isp_put_request_t2(struct ispsoftc *, ispreqt2_t *, ispreqt2_t *); static INLINE void +isp_put_request_t2e(struct ispsoftc *, ispreqt2e_t *, ispreqt2e_t *); +static INLINE void isp_put_request_t3(struct ispsoftc *, ispreqt3_t *, ispreqt3_t *); static INLINE void +isp_put_request_t3e(struct ispsoftc *, ispreqt3e_t *, ispreqt3e_t *); +static INLINE void isp_put_extended_request(struct ispsoftc *, ispextreq_t *, ispextreq_t *); static INLINE void isp_put_cont_req(struct ispsoftc *, ispcontreq_t *, ispcontreq_t *); @@ -366,16 +368,24 @@ isp_get_atio(struct ispsoftc *, at_entry_t *, at_entry_t *); static INLINE void isp_put_atio2(struct ispsoftc *, at2_entry_t *, at2_entry_t *); static INLINE void +isp_put_atio2e(struct ispsoftc *, at2e_entry_t *, at2e_entry_t *); +static INLINE void isp_get_atio2(struct ispsoftc *, at2_entry_t *, at2_entry_t *); static INLINE void +isp_get_atio2e(struct ispsoftc *, at2e_entry_t *, at2e_entry_t *); +static INLINE void isp_put_ctio(struct ispsoftc *, ct_entry_t *, ct_entry_t *); static INLINE void isp_get_ctio(struct ispsoftc *, ct_entry_t *, ct_entry_t *); static INLINE void isp_put_ctio2(struct ispsoftc *, ct2_entry_t *, ct2_entry_t *); static INLINE void +isp_put_ctio2e(struct ispsoftc *, ct2e_entry_t *, ct2e_entry_t *); +static INLINE void isp_get_ctio2(struct ispsoftc *, ct2_entry_t *, ct2_entry_t *); static INLINE void +isp_get_ctio2e(struct ispsoftc *, ct2e_entry_t *, ct2e_entry_t *); +static INLINE void isp_put_enable_lun(struct ispsoftc *, lun_entry_t *, lun_entry_t *); static INLINE void isp_get_enable_lun(struct ispsoftc *, lun_entry_t *, lun_entry_t *); @@ -386,15 +396,23 @@ isp_get_notify(struct ispsoftc *, in_entry_t *, in_entry_t *); static INLINE void isp_put_notify_fc(struct ispsoftc *, in_fcentry_t *, in_fcentry_t *); static INLINE void +isp_put_notify_fc_e(struct ispsoftc *, in_fcentry_e_t *, in_fcentry_e_t *); +static INLINE void isp_get_notify_fc(struct ispsoftc *, in_fcentry_t *, in_fcentry_t *); static INLINE void +isp_get_notify_fc_e(struct ispsoftc *, in_fcentry_e_t *, in_fcentry_e_t *); +static INLINE void isp_put_notify_ack(struct ispsoftc *, na_entry_t *, na_entry_t *); static INLINE void isp_get_notify_ack(struct ispsoftc *, na_entry_t *, na_entry_t *); static INLINE void isp_put_notify_ack_fc(struct ispsoftc *, na_fcentry_t *, na_fcentry_t *); static INLINE void +isp_put_notify_ack_fc_e(struct ispsoftc *, na_fcentry_e_t *, na_fcentry_e_t *); +static INLINE void isp_get_notify_ack_fc(struct ispsoftc *, na_fcentry_t *, na_fcentry_t *); +static INLINE void +isp_get_notify_ack_fc_e(struct ispsoftc *, na_fcentry_e_t *, na_fcentry_e_t *); #endif #define ISP_IS_SBUS(isp) \ @@ -517,6 +535,30 @@ isp_put_request_t2(struct ispsoftc *isp, ispreqt2_t *tqsrc, ispreqt2_t *tqdst) } static INLINE void +isp_put_request_t2e(struct ispsoftc *isp, ispreqt2e_t *tqsrc, ispreqt2e_t *tqdst) +{ + int i; + isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); + ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); + ISP_IOXPUT_16(isp, tqsrc->req_target, &tqdst->req_target); + ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); + ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); + ISP_IOXPUT_16(isp, tqsrc->_res2, &tqdst->_res2); + ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); + ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); + for (i = 0; i < 16; i++) { + ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, + &tqdst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, + &tqdst->req_dataseg[i].ds_count); + } +} + +static INLINE void isp_put_request_t3(struct ispsoftc *isp, ispreqt3_t *tqsrc, ispreqt3_t *tqdst) { int i; @@ -544,6 +586,32 @@ isp_put_request_t3(struct ispsoftc *isp, ispreqt3_t *tqsrc, ispreqt3_t *tqdst) } static INLINE void +isp_put_request_t3e(struct ispsoftc *isp, ispreqt3e_t *tqsrc, ispreqt3e_t *tqdst) +{ + int i; + isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); + ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); + ISP_IOXPUT_16(isp, tqsrc->req_target, &tqdst->req_target); + ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); + ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); + ISP_IOXPUT_16(isp, tqsrc->_res2, &tqdst->_res2); + ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); + ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); + for (i = 0; i < 16; i++) { + ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, + &tqdst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_basehi, + &tqdst->req_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, + &tqdst->req_dataseg[i].ds_count); + } +} + +static INLINE void isp_put_extended_request(struct ispsoftc *isp, ispextreq_t *xqsrc, ispextreq_t *xqdst) { @@ -1072,6 +1140,35 @@ isp_put_atio2(struct ispsoftc *isp, at2_entry_t *atsrc, at2_entry_t *atdst) } static INLINE void +isp_put_atio2e(struct ispsoftc *isp, at2e_entry_t *atsrc, at2e_entry_t *atdst) +{ + int i; + isp_copy_out_hdr(isp, &atsrc->at_header, &atdst->at_header); + ISP_IOXPUT_32(isp, atsrc->at_reserved, &atdst->at_reserved); + ISP_IOXPUT_16(isp, atsrc->at_iid, &atdst->at_iid); + ISP_IOXPUT_16(isp, atsrc->at_rxid, &atdst->at_rxid); + ISP_IOXPUT_16(isp, atsrc->at_flags, &atdst->at_flags); + ISP_IOXPUT_16(isp, atsrc->at_status, &atdst->at_status); + ISP_IOXPUT_8(isp, atsrc->at_crn, &atdst->at_crn); + ISP_IOXPUT_8(isp, atsrc->at_taskcodes, &atdst->at_taskcodes); + ISP_IOXPUT_8(isp, atsrc->at_taskflags, &atdst->at_taskflags); + ISP_IOXPUT_8(isp, atsrc->at_execodes, &atdst->at_execodes); + for (i = 0; i < ATIO2_CDBLEN; i++) { + ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]); + } + ISP_IOXPUT_32(isp, atsrc->at_datalen, &atdst->at_datalen); + ISP_IOXPUT_16(isp, atsrc->at_scclun, &atdst->at_scclun); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, atsrc->at_wwpn[i], &atdst->at_wwpn[i]); + } + for (i = 0; i < 6; i++) { + ISP_IOXPUT_16(isp, atsrc->at_reserved2[i], + &atdst->at_reserved2[i]); + } + ISP_IOXPUT_16(isp, atsrc->at_oxid, &atdst->at_oxid); +} + +static INLINE void isp_get_atio2(struct ispsoftc *isp, at2_entry_t *atsrc, at2_entry_t *atdst) { int i; @@ -1102,6 +1199,35 @@ isp_get_atio2(struct ispsoftc *isp, at2_entry_t *atsrc, at2_entry_t *atdst) } static INLINE void +isp_get_atio2e(struct ispsoftc *isp, at2e_entry_t *atsrc, at2e_entry_t *atdst) +{ + int i; + isp_copy_in_hdr(isp, &atsrc->at_header, &atdst->at_header); + ISP_IOXGET_32(isp, &atsrc->at_reserved, atdst->at_reserved); + ISP_IOXGET_16(isp, &atsrc->at_iid, atdst->at_iid); + ISP_IOXGET_16(isp, &atsrc->at_rxid, atdst->at_rxid); + ISP_IOXGET_16(isp, &atsrc->at_flags, atdst->at_flags); + ISP_IOXGET_16(isp, &atsrc->at_status, atdst->at_status); + ISP_IOXGET_8(isp, &atsrc->at_crn, atdst->at_crn); + ISP_IOXGET_8(isp, &atsrc->at_taskcodes, atdst->at_taskcodes); + ISP_IOXGET_8(isp, &atsrc->at_taskflags, atdst->at_taskflags); + ISP_IOXGET_8(isp, &atsrc->at_execodes, atdst->at_execodes); + for (i = 0; i < ATIO2_CDBLEN; i++) { + ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]); + } + ISP_IOXGET_32(isp, &atsrc->at_datalen, atdst->at_datalen); + ISP_IOXGET_16(isp, &atsrc->at_scclun, atdst->at_scclun); + for (i = 0; i < 4; i++) { + ISP_IOXGET_16(isp, &atsrc->at_wwpn[i], atdst->at_wwpn[i]); + } + for (i = 0; i < 6; i++) { + ISP_IOXGET_16(isp, &atsrc->at_reserved2[i], + atdst->at_reserved2[i]); + } + ISP_IOXGET_16(isp, &atsrc->at_oxid, atdst->at_oxid); +} + +static INLINE void isp_put_ctio(struct ispsoftc *isp, ct_entry_t *ctsrc, ct_entry_t *ctdst) { int i; @@ -1268,6 +1394,89 @@ isp_put_ctio2(struct ispsoftc *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst) } static INLINE void +isp_put_ctio2e(struct ispsoftc *isp, ct2e_entry_t *ctsrc, ct2e_entry_t *ctdst) +{ + int i; + isp_copy_out_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); + ISP_IOXPUT_16(isp, ctsrc->ct_reserved, &ctdst->ct_reserved); + ISP_IOXPUT_16(isp, ctsrc->ct_fwhandle, &ctdst->ct_fwhandle); + ISP_IOXPUT_16(isp, ctsrc->ct_iid, &ctdst->ct_iid); + ISP_IOXPUT_16(isp, ctsrc->ct_rxid, &ctdst->ct_rxid); + ISP_IOXPUT_16(isp, ctsrc->ct_flags, &ctdst->ct_flags); + ISP_IOXPUT_16(isp, ctsrc->ct_timeout, &ctdst->ct_timeout); + ISP_IOXPUT_16(isp, ctsrc->ct_seg_count, &ctdst->ct_seg_count); + ISP_IOXPUT_32(isp, ctsrc->ct_resid, &ctdst->ct_resid); + ISP_IOXPUT_32(isp, ctsrc->ct_reloff, &ctdst->ct_reloff); + if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXPUT_32(isp, ctsrc->rsp.m0._reserved, + &ctdst->rsp.m0._reserved); + ISP_IOXPUT_16(isp, ctsrc->rsp.m0._reserved2, + &ctdst->rsp.m0._reserved2); + ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_scsi_status, + &ctdst->rsp.m0.ct_scsi_status); + ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_xfrlen, + &ctdst->rsp.m0.ct_xfrlen); + if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXPUT_32(isp, + ctsrc->rsp.m0.ct_dataseg[i].ds_base, + &ctdst->rsp.m0.ct_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, + ctsrc->rsp.m0.ct_dataseg[i].ds_count, + &ctdst->rsp.m0.ct_dataseg[i].ds_count); + } + } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXPUT_32(isp, + ctsrc->rsp.m0.ct_dataseg64[i].ds_base, + &ctdst->rsp.m0.ct_dataseg64[i].ds_base); + ISP_IOXPUT_32(isp, + ctsrc->rsp.m0.ct_dataseg64[i].ds_basehi, + &ctdst->rsp.m0.ct_dataseg64[i].ds_basehi); + ISP_IOXPUT_32(isp, + ctsrc->rsp.m0.ct_dataseg64[i].ds_count, + &ctdst->rsp.m0.ct_dataseg64[i].ds_count); + } + } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_dslist.ds_type, + &ctdst->rsp.m0.ct_dslist.ds_type); + ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_segment, + &ctdst->rsp.m0.ct_dslist.ds_segment); + ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_base, + &ctdst->rsp.m0.ct_dslist.ds_base); + } + } else if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved, + &ctdst->rsp.m1._reserved); + ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved2, + &ctdst->rsp.m1._reserved2); + ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_senselen, + &ctdst->rsp.m1.ct_senselen); + ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_scsi_status, + &ctdst->rsp.m1.ct_scsi_status); + ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_resplen, + &ctdst->rsp.m1.ct_resplen); + for (i = 0; i < MAXRESPLEN; i++) { + ISP_IOXPUT_8(isp, ctsrc->rsp.m1.ct_resp[i], + &ctdst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXPUT_32(isp, ctsrc->rsp.m2._reserved, + &ctdst->rsp.m2._reserved); + ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved2, + &ctdst->rsp.m2._reserved2); + ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved3, + &ctdst->rsp.m2._reserved3); + ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_datalen, + &ctdst->rsp.m2.ct_datalen); + ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_base, + &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_count, + &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + +static INLINE void isp_get_ctio2(struct ispsoftc *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst) { isp_copy_in_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); @@ -1285,6 +1494,22 @@ isp_get_ctio2(struct ispsoftc *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst) } static INLINE void +isp_get_ctio2e(struct ispsoftc *isp, ct2e_entry_t *ctsrc, ct2e_entry_t *ctdst) +{ + isp_copy_in_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); + ISP_IOXGET_16(isp, &ctsrc->ct_reserved, ctdst->ct_reserved); + ISP_IOXGET_16(isp, &ctsrc->ct_fwhandle, ctdst->ct_fwhandle); + ISP_IOXGET_16(isp, &ctsrc->ct_iid, ctdst->ct_iid); + ISP_IOXGET_16(isp, &ctsrc->ct_rxid, ctdst->ct_rxid); + ISP_IOXGET_16(isp, &ctsrc->ct_flags, ctdst->ct_flags); + ISP_IOXGET_16(isp, &ctsrc->ct_status, ctdst->ct_status); + ISP_IOXGET_16(isp, &ctsrc->ct_timeout, ctdst->ct_timeout); + ISP_IOXGET_16(isp, &ctsrc->ct_seg_count, ctdst->ct_seg_count); + ISP_IOXGET_32(isp, &ctsrc->ct_reloff, ctdst->ct_reloff); + ISP_IOXGET_32(isp, &ctsrc->ct_resid, ctdst->ct_resid); +} + +static INLINE void isp_put_enable_lun(struct ispsoftc *isp, lun_entry_t *lesrc, lun_entry_t *ledst) { int i; @@ -1454,6 +1679,20 @@ isp_put_notify_fc(struct ispsoftc *isp, in_fcentry_t *insrc, } static INLINE void +isp_put_notify_fc_e(struct ispsoftc *isp, in_fcentry_e_t *insrc, + in_fcentry_e_t *indst) +{ + isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header); + ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved); + ISP_IOXPUT_16(isp, insrc->in_iid, &indst->in_iid); + ISP_IOXPUT_16(isp, insrc->in_scclun, &indst->in_scclun); + ISP_IOXPUT_32(isp, insrc->in_reserved2, &indst->in_reserved2); + ISP_IOXPUT_16(isp, insrc->in_status, &indst->in_status); + ISP_IOXPUT_16(isp, insrc->in_task_flags, &indst->in_task_flags); + ISP_IOXPUT_16(isp, insrc->in_seqid, &indst->in_seqid); +} + +static INLINE void isp_get_notify_fc(struct ispsoftc *isp, in_fcentry_t *insrc, in_fcentry_t *indst) { @@ -1469,6 +1708,20 @@ isp_get_notify_fc(struct ispsoftc *isp, in_fcentry_t *insrc, } static INLINE void +isp_get_notify_fc_e(struct ispsoftc *isp, in_fcentry_e_t *insrc, + in_fcentry_e_t *indst) +{ + isp_copy_in_hdr(isp, &insrc->in_header, &indst->in_header); + ISP_IOXGET_32(isp, &insrc->in_reserved, indst->in_reserved); + ISP_IOXGET_16(isp, &insrc->in_iid, indst->in_iid); + ISP_IOXGET_16(isp, &insrc->in_scclun, indst->in_scclun); + ISP_IOXGET_32(isp, &insrc->in_reserved2, indst->in_reserved2); + ISP_IOXGET_16(isp, &insrc->in_status, indst->in_status); + ISP_IOXGET_16(isp, &insrc->in_task_flags, indst->in_task_flags); + ISP_IOXGET_16(isp, &insrc->in_seqid, indst->in_seqid); +} + +static INLINE void isp_put_notify_ack(struct ispsoftc *isp, na_entry_t *nasrc, na_entry_t *nadst) { int i; @@ -1538,6 +1791,26 @@ isp_put_notify_ack_fc(struct ispsoftc *isp, na_fcentry_t *nasrc, } static INLINE void +isp_put_notify_ack_fc_e(struct ispsoftc *isp, na_fcentry_e_t *nasrc, + na_fcentry_e_t *nadst) +{ + int i; + isp_copy_out_hdr(isp, &nasrc->na_header, &nadst->na_header); + ISP_IOXPUT_32(isp, nasrc->na_reserved, &nadst->na_reserved); + ISP_IOXPUT_16(isp, nasrc->na_iid, &nadst->na_iid); + ISP_IOXPUT_16(isp, nasrc->na_scclun, &nadst->na_scclun); + ISP_IOXPUT_16(isp, nasrc->na_flags, &nadst->na_flags); + ISP_IOXPUT_16(isp, nasrc->na_reserved2, &nadst->na_reserved2); + ISP_IOXPUT_16(isp, nasrc->na_status, &nadst->na_status); + ISP_IOXPUT_16(isp, nasrc->na_task_flags, &nadst->na_task_flags); + ISP_IOXPUT_16(isp, nasrc->na_seqid, &nadst->na_seqid); + for (i = 0; i < NA2_RSVDLEN; i++) { + ISP_IOXPUT_16(isp, nasrc->na_reserved3[i], + &nadst->na_reserved3[i]); + } +} + +static INLINE void isp_get_notify_ack_fc(struct ispsoftc *isp, na_fcentry_t *nasrc, na_fcentry_t *nadst) { @@ -1557,5 +1830,25 @@ isp_get_notify_ack_fc(struct ispsoftc *isp, na_fcentry_t *nasrc, nadst->na_reserved3[i]); } } + +static INLINE void +isp_get_notify_ack_fc_e(struct ispsoftc *isp, na_fcentry_e_t *nasrc, + na_fcentry_e_t *nadst) +{ + int i; + isp_copy_in_hdr(isp, &nasrc->na_header, &nadst->na_header); + ISP_IOXGET_32(isp, &nasrc->na_reserved, nadst->na_reserved); + ISP_IOXGET_16(isp, &nasrc->na_iid, nadst->na_iid); + ISP_IOXGET_16(isp, &nasrc->na_scclun, nadst->na_scclun); + ISP_IOXGET_16(isp, &nasrc->na_flags, nadst->na_flags); + ISP_IOXGET_16(isp, &nasrc->na_reserved2, nadst->na_reserved2); + ISP_IOXGET_16(isp, &nasrc->na_status, nadst->na_status); + ISP_IOXGET_16(isp, &nasrc->na_task_flags, nadst->na_task_flags); + ISP_IOXGET_16(isp, &nasrc->na_seqid, nadst->na_seqid); + for (i = 0; i < NA2_RSVDLEN; i++) { + ISP_IOXGET_16(isp, &nasrc->na_reserved3[i], + nadst->na_reserved3[i]); + } +} #endif #endif /* _ISP_INLINE_H */ diff --git a/sys/dev/isp/isp_ioctl.h b/sys/dev/isp/isp_ioctl.h index 099b10478771..7cf61495bb2a 100644 --- a/sys/dev/isp/isp_ioctl.h +++ b/sys/dev/isp/isp_ioctl.h @@ -1,34 +1,29 @@ /* $FreeBSD$ */ /*- - * Copyright (c) 2001 by Matthew Jacob + * + * Copyright (c) 1997-2006 by Matthew Jacob + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Alternatively, this software may be distributed under the terms of the - * the GNU Public License ("GPL", Library, Version 2). - * - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Matthew Jacob <mjacob@feral.com) + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ /* * ioctl definitions for Qlogic FC/SCSI HBA driver diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index b75867c8bb12..4d2810e6f0bf 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -2,7 +2,8 @@ * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. * FreeBSD Version. * - * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob + * Copyright (c) 1997-2006 by Matthew Jacob + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,6 +25,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * */ #include <sys/cdefs.h> @@ -220,6 +222,10 @@ static struct ispmdvec mdvec_2300 = { #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 #endif +#ifndef PCI_PRODUCT_QLOGIC_ISP2322 +#define PCI_PRODUCT_QLOGIC_ISP2322 0x2322 +#endif + #ifndef PCI_PRODUCT_QLOGIC_ISP6312 #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312 #endif @@ -254,6 +260,9 @@ static struct ispmdvec mdvec_2300 = { #define PCI_QLOGIC_ISP2312 \ ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) +#define PCI_QLOGIC_ISP2322 \ + ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) + #define PCI_QLOGIC_ISP6312 \ ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) @@ -336,6 +345,9 @@ isp_pci_probe(device_t dev) case PCI_QLOGIC_ISP2312: device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); break; + case PCI_QLOGIC_ISP2322: + device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); + break; case PCI_QLOGIC_ISP6312: device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); break; @@ -534,6 +546,13 @@ isp_pci_attach(device_t dev) pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; } + if (pci_get_devid(dev) == PCI_QLOGIC_ISP2322) { + mdvp = &mdvec_2300; + basetype = ISP_HA_FC_2322; + psize = sizeof (fcparam); + pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = + PCI_MBOX_REGS2300_OFF; + } isp = &pcs->pci_isp; isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); if (isp->isp_param == NULL) { @@ -550,7 +569,10 @@ isp_pci_attach(device_t dev) * Try and find firmware for this device. */ - if (isp_get_firmware_p) { + /* + * Don't even attempt to get firmware for the 2322/2422 (yet) + */ + if (IS_2322(isp) == 0 && IS_24XX(isp) == 0 && isp_get_firmware_p) { int device = (int) pci_get_device(dev); #ifdef ISP_TARGET_MODE (*isp_get_firmware_p)(0, 1, device, &mdvp->dv_ispfw); @@ -744,7 +766,7 @@ isp_pci_attach(device_t dev) /* * Last minute checks... */ - if (IS_2312(isp)) { + if (IS_23XX(isp)) { isp->isp_port = pci_get_function(dev); } diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index 5f87f3dbb08e..8914d9aba64c 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -2,7 +2,8 @@ * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. * FreeBSD Version. * - * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob + * Copyright (c) 1997-2006 by Matthew Jacob + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index 1d4b397bbad5..f561cd90b75e 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -1,10 +1,8 @@ -/* $FreeBSD$ */ /*- * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters. * - * Copyright (c) 1999, 2000, 2001 by Matthew Jacob + * Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. - * mjacob@feral.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,6 +38,9 @@ #include <dev/ic/isp_netbsd.h> #endif #ifdef __FreeBSD__ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include <dev/isp/isp_freebsd.h> #endif #ifdef __OpenBSD__ @@ -57,9 +58,8 @@ static const char atior[] = "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred " "on bus %d"; -static void isp_got_msg(struct ispsoftc *, int, in_entry_t *); -static void isp_got_msg_fc(struct ispsoftc *, int, in_fcentry_t *); -static void isp_notify_ack(struct ispsoftc *, void *); +static void isp_got_msg(struct ispsoftc *, in_entry_t *); +static void isp_got_msg_fc(struct ispsoftc *, in_fcentry_t *); static void isp_handle_atio(struct ispsoftc *, at_entry_t *); static void isp_handle_atio2(struct ispsoftc *, at2_entry_t *); static void isp_handle_ctio(struct ispsoftc *, ct_entry_t *); @@ -118,24 +118,32 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) union { at_entry_t *atiop; at2_entry_t *at2iop; + at2e_entry_t *at2eiop; ct_entry_t *ctiop; ct2_entry_t *ct2iop; + ct2e_entry_t *ct2eiop; lun_entry_t *lunenp; in_entry_t *inotp; in_fcentry_t *inot_fcp; + in_fcentry_e_t *inote_fcp; na_entry_t *nackp; na_fcentry_t *nack_fcp; + na_fcentry_e_t *nacke_fcp; isphdr_t *hp; void * *vp; #define atiop unp.atiop #define at2iop unp.at2iop +#define at2eiop unp.at2eiop #define ctiop unp.ctiop #define ct2iop unp.ct2iop +#define ct2eiop unp.ct2eiop #define lunenp unp.lunenp #define inotp unp.inotp #define inot_fcp unp.inot_fcp +#define inote_fcp unp.inote_fcp #define nackp unp.nackp #define nack_fcp unp.nack_fcp +#define nacke_fcp unp.nacke_fcp #define hdrp unp.hp } unp; u_int8_t local[QENTRY_LEN]; @@ -156,12 +164,18 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) isp_handle_ctio(isp, (ct_entry_t *) local); break; case RQSTYPE_ATIO2: - isp_get_atio2(isp, at2iop, (at2_entry_t *) local); + if (IS_2KLOGIN(isp)) + isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); + else + isp_get_atio2(isp, at2iop, (at2_entry_t *) local); isp_handle_atio2(isp, (at2_entry_t *) local); break; case RQSTYPE_CTIO3: case RQSTYPE_CTIO2: - isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); + if (IS_2KLOGIN(isp)) + isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); + else + isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); isp_handle_ctio2(isp, (ct2_entry_t *) local); break; case RQSTYPE_ENABLE_LUN: @@ -180,7 +194,9 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) */ bus = 0; if (IS_FC(isp)) { - isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local); + if (IS_2KLOGIN(isp)) + isp_get_notify_fc_e(isp, inote_fcp, (in_fcentry_e_t *)local); + isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local); inot_fcp = (in_fcentry_t *) local; status = inot_fcp->in_status; seqid = inot_fcp->in_seqid; @@ -198,24 +214,21 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", bus, status, seqid); - /* - * ACK it right away. - */ - isp_notify_ack(isp, (status == IN_RESET)? NULL : local); switch (status) { - case IN_RESET: - (void) isp_async(isp, ISPASYNC_BUS_RESET, &bus); - break; case IN_MSG_RECEIVED: case IN_IDE_RECEIVED: if (IS_FC(isp)) { - isp_got_msg_fc(isp, bus, (in_fcentry_t *)local); + isp_got_msg_fc(isp, (in_fcentry_t *)local); } else { - isp_got_msg(isp, bus, (in_entry_t *)local); + isp_got_msg(isp, (in_entry_t *)local); } break; case IN_RSRC_UNAVAIL: isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs"); + isp_notify_ack(isp, local); + break; + case IN_RESET: + isp_target_async(isp, 0, ASYNC_BUS_RESET); break; case IN_PORT_LOGOUT: case IN_ABORT_TASK: @@ -226,6 +239,7 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) default: isp_prt(isp, ISP_LOGERR, "bad status (0x%x) in isp_target_notify", status); + isp_notify_ack(isp, local); break; } break; @@ -236,8 +250,12 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) * Immediate Notify entry for some asynchronous event. */ if (IS_FC(isp)) { - isp_get_notify_ack_fc(isp, nack_fcp, - (na_fcentry_t *)local); + if (IS_2KLOGIN(isp)) + isp_get_notify_ack_fc_e(isp, nacke_fcp, + (na_fcentry_e_t *)local); + else + isp_get_notify_ack_fc(isp, nack_fcp, + (na_fcentry_t *)local); nack_fcp = (na_fcentry_t *)local; isp_prt(isp, ISP_LOGTDEBUG1, "Notify Ack status=0x%x seqid 0x%x", @@ -258,13 +276,17 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) } #undef atiop #undef at2iop +#undef at2eiop #undef ctiop #undef ct2iop +#undef ct2eiop #undef lunenp #undef inotp #undef inot_fcp +#undef inote_fcp #undef nackp #undef nack_fcp +#undef nacke_fcp #undef hdrp return (rval); } @@ -375,6 +397,7 @@ isp_target_put_atio(struct ispsoftc *isp, void *arg) union { at_entry_t _atio; at2_entry_t _atio2; + at2e_entry_t _atio2e; } atun; MEMZERO(&atun, sizeof atun); @@ -387,7 +410,11 @@ isp_target_put_atio(struct ispsoftc *isp, void *arg) } else { atun._atio2.at_lun = (u_int8_t) aep->at_lun; } - atun._atio2.at_iid = aep->at_iid; + if (IS_2KLOGIN(isp)) { + atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; + } else { + atun._atio2.at_iid = aep->at_iid; + } atun._atio2.at_rxid = aep->at_rxid; atun._atio2.at_status = CT_OK; } else { @@ -431,6 +458,7 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) union { ct_entry_t _ctio; ct2_entry_t _ctio2; + ct2e_entry_t _ctio2e; } un; MEMZERO(&un, sizeof un); @@ -442,10 +470,14 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; cto->ct_header.rqs_entry_count = 1; - cto->ct_iid = aep->at_iid; if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { cto->ct_lun = aep->at_lun; } + if (IS_2KLOGIN(isp)) { + un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; + } else { + cto->ct_iid = aep->at_iid; + } cto->ct_rxid = aep->at_rxid; cto->rsp.m1.ct_scsi_status = sts; cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1; @@ -494,65 +526,74 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) int isp_target_async(struct ispsoftc *isp, int bus, int event) { - tmd_event_t evt; - tmd_msg_t msg; + tmd_notify_t notify; + + MEMZERO(¬ify, sizeof (tmd_notify_t)); + notify.nt_hba = isp; + /* nt_str set in outer layers */ + notify.nt_iid = INI_ANY; + /* nt_tgt set in outer layers */ + notify.nt_lun = LUN_ANY; + notify.nt_tagval = TAG_ANY; + + if (IS_SCSI(isp)) { + TAG_INSERT_BUS(notify.nt_tagval, bus); + } switch (event) { - /* - * These three we handle here to propagate an effective bus reset - * upstream, but these do not require any immediate notify actions - * so we return when done. - */ - case ASYNC_LIP_F8: - case ASYNC_LIP_OCCURRED: case ASYNC_LOOP_UP: + case ASYNC_PTPMODE: + notify.nt_ncode = NT_LINK_UP; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; case ASYNC_LOOP_DOWN: + notify.nt_ncode = NT_LINK_DOWN; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; + case ASYNC_LIP_F8: + case ASYNC_LIP_OCCURRED: case ASYNC_LOOP_RESET: - case ASYNC_PTPMODE: - /* - * These don't require any immediate notify actions. We used - * treat them like SCSI Bus Resets, but that was just plain - * wrong. Let the normal CTIO completion report what occurred. - */ - return (0); - + notify.nt_ncode = NT_LIP_RESET; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; case ASYNC_BUS_RESET: - case ASYNC_TIMEOUT_RESET: - if (IS_FC(isp)) { - return (0); /* we'll be getting an inotify instead */ - } - evt.ev_bus = bus; - evt.ev_event = event; - (void) isp_async(isp, ISPASYNC_TARGET_EVENT, &evt); + case ASYNC_TIMEOUT_RESET: /* XXX: where does this come from ? */ + notify.nt_ncode = NT_BUS_RESET; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); break; case ASYNC_DEVICE_RESET: - /* - * Bus Device Reset resets a specific target, so - * we pass this as a synthesized message. - */ - MEMZERO(&msg, sizeof msg); + notify.nt_ncode = NT_TARGET_RESET; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); + break; + case ASYNC_CTIO_DONE: + { + uint8_t storage[QENTRY_LEN]; + memset(storage, 0, QENTRY_LEN); if (IS_FC(isp)) { - msg.nt_iid = FCPARAM(isp)->isp_loopid; + ct2_entry_t *ct = (ct2_entry_t *) storage; + ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; + ct->ct_status = CT_OK; + ct->ct_syshandle = bus; + ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST; } else { - msg.nt_iid = SDPARAM(isp)->isp_initiator_id; + ct_entry_t *ct = (ct_entry_t *) storage; + ct->ct_header.rqs_entry_type = RQSTYPE_CTIO; + ct->ct_status = CT_OK; + ct->ct_fwhandle = bus; + ct->ct_flags = CT_SENDSTATUS; } - msg.nt_bus = bus; - msg.nt_msg[0] = MSG_BUS_DEV_RESET; - (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); - break; - case ASYNC_CTIO_DONE: - evt.ev_bus = bus; - evt.ev_event = event; - (void) isp_async(isp, ISPASYNC_TARGET_EVENT, &evt); + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage); return (0); + } default: isp_prt(isp, ISP_LOGERR, "isp_target_async: unknown event 0x%x", event); + if (isp->isp_state == ISP_RUNSTATE) { + isp_notify_ack(isp, NULL); + } break; } - if (isp->isp_state == ISP_RUNSTATE) - isp_notify_ack(isp, NULL); - return(0); + return (0); } @@ -565,25 +606,54 @@ isp_target_async(struct ispsoftc *isp, int bus, int event) */ static void -isp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp) +isp_got_msg(struct ispsoftc *isp, in_entry_t *inp) { + tmd_notify_t nt; u_int8_t status = inp->in_status & ~QLTM_SVALID; + MEMZERO(&nt, sizeof (nt)); + nt.nt_hba = isp; + /* nt_str set in outer layers */ + nt.nt_iid = GET_IID_VAL(inp->in_iid); + nt.nt_tgt = inp->in_tgt; + nt.nt_lun = inp->in_lun; + IN_MAKE_TAGID(nt.nt_tagval, 0, inp); + nt.nt_lreserved = inp; + if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) { - tmd_msg_t msg; - - MEMZERO(&msg, sizeof (msg)); - msg.nt_bus = bus; - msg.nt_iid = inp->in_iid; - msg.nt_tgt = inp->in_tgt; - msg.nt_lun = inp->in_lun; - msg.nt_tagtype = inp->in_tag_type; - IN_MAKE_TAGID(msg.nt_tagval, 0, inp); - MEMCPY(msg.nt_msg, inp->in_msg, IN_MSGLEN); - (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); + switch (inp->in_msg[0]) { + case MSG_ABORT: + nt.nt_ncode = NT_ABORT_TASK_SET; + break; + case MSG_BUS_DEV_RESET: + nt.nt_ncode = NT_TARGET_RESET; + break; + case MSG_ABORT_TAG: + nt.nt_ncode = NT_ABORT_TASK; + break; + case MSG_CLEAR_QUEUE: + nt.nt_ncode = NT_CLEAR_TASK_SET; + break; + case MSG_REL_RECOVERY: + nt.nt_ncode = NT_CLEAR_ACA; + break; + case MSG_TERM_IO_PROC: + nt.nt_ncode = NT_ABORT_TASK; + break; + case MSG_LUN_RESET: + nt.nt_ncode = NT_LUN_RESET; + break; + default: + isp_prt(isp, ISP_LOGERR, + "unhandled message 0x%x", inp->in_msg[0]); + isp_notify_ack(isp, inp); + return; + } + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); } else { isp_prt(isp, ISP_LOGERR, "unknown immediate notify status 0x%x", inp->in_status); + isp_notify_ack(isp, inp); } } @@ -591,64 +661,71 @@ isp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp) * Synthesize a message from the task management flags in a FCP_CMND_IU. */ static void -isp_got_msg_fc(struct ispsoftc *isp, int bus, in_fcentry_t *inp) +isp_got_msg_fc(struct ispsoftc *isp, in_fcentry_t *inp) { - int lun; - static const char f1[] = "%s from iid %d lun %d seq 0x%x"; + tmd_notify_t nt; + static const char f1[] = "%s from iid 0x%08x%08x lun %d seq 0x%x"; static const char f2[] = - "unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n"; + "unknown %s 0x%x lun %d iid 0x%08x%08x task flags 0x%x seq 0x%x\n"; + MEMZERO(&nt, sizeof (tmd_notify_t)); + nt.nt_hba = isp; + /* + * XXX: LOOK UP TRANSLATION IN CURRENT LPORTDB + */ + if (IS_2KLOGIN(isp)) { + nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid; + } else { + nt.nt_iid = inp->in_iid; /* possibly reset in outer layer */ + } + /* nt_tgt set in outer layers */ if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - lun = inp->in_scclun; + nt.nt_lun = inp->in_scclun; } else { - lun = inp->in_lun; + nt.nt_lun = inp->in_lun; } + IN_FC_MAKE_TAGID(nt.nt_tagval, 0, inp); + nt.nt_lreserved = inp; if (inp->in_status != IN_MSG_RECEIVED) { isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", - inp->in_status, lun, inp->in_iid, + inp->in_status, nt.nt_lun, (u_int32_t) (nt.nt_iid >> 32), (u_int32_t) nt.nt_iid, inp->in_task_flags, inp->in_seqid); + isp_notify_ack(isp, inp); + return; + } + + if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", + (u_int32_t) (nt.nt_iid >> 32), (u_int32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_ABORT_TASK_SET; + } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", + (u_int32_t) (nt.nt_iid >> 32), (u_int32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_CLEAR_TASK_SET; + } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", + (u_int32_t) (nt.nt_iid >> 32), (u_int32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_LUN_RESET; + } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", + (u_int32_t) (nt.nt_iid >> 32), (u_int32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_TARGET_RESET; + } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", + (u_int32_t) (nt.nt_iid >> 32), (u_int32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); + nt.nt_ncode = NT_CLEAR_ACA; } else { - tmd_msg_t msg; - - MEMZERO(&msg, sizeof (msg)); - msg.nt_bus = bus; - msg.nt_iid = inp->in_iid; - IN_FC_MAKE_TAGID(msg.nt_tagval, 0, inp); - msg.nt_lun = lun; - - if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) { - isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_ABORT; - } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { - isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_CLEAR_QUEUE; - } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) { - isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_LUN_RESET; - } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { - isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_BUS_DEV_RESET; - } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { - isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", - inp->in_iid, lun, inp->in_seqid); - msg.nt_msg[0] = MSG_REL_RECOVERY; - } else { - isp_prt(isp, ISP_LOGWARN, f2, "task flag", - inp->in_status, lun, inp->in_iid, - inp->in_task_flags, inp->in_seqid); - } - if (msg.nt_msg[0]) { - (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg); - } + isp_prt(isp, ISP_LOGWARN, f2, "task flag", + inp->in_status, nt.nt_lun, (u_int32_t) (nt.nt_iid >> 32), (u_int32_t) nt.nt_iid, + inp->in_task_flags, inp->in_seqid); + isp_notify_ack(isp, inp); + return; } + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); } -static void +void isp_notify_ack(struct ispsoftc *isp, void *arg) { char storage[QENTRY_LEN]; @@ -668,7 +745,11 @@ isp_notify_ack(struct ispsoftc *isp, void *arg) if (arg) { in_fcentry_t *inp = arg; MEMCPY(storage, arg, sizeof (isphdr_t)); - na->na_iid = inp->in_iid; + if (IS_2KLOGIN(isp)) { + ((na_fcentry_e_t *)na)->na_iid = ((in_fcentry_e_t *)inp)->in_iid; + } else { + na->na_iid = inp->in_iid; + } if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { na->na_lun = inp->in_scclun; } else { @@ -686,7 +767,11 @@ isp_notify_ack(struct ispsoftc *isp, void *arg) } na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; na->na_header.rqs_entry_count = 1; - isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); + if (IS_2KLOGIN(isp)) { + isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, (na_fcentry_e_t *)outp); + } else { + isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); + } } else { na_entry_t *na = (na_entry_t *) storage; if (arg) { @@ -794,7 +879,7 @@ isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep) static void isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep) { - int lun; + int lun, iid; if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { lun = aep->at_scclun; @@ -802,6 +887,12 @@ isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep) lun = aep->at_lun; } + if (IS_2KLOGIN(isp)) { + iid = ((at2e_entry_t *)aep)->at_iid; + } else { + iid = aep->at_iid; + } + /* * The firmware status (except for the QLTM_SVALID bit) indicates * why this ATIO was sent to us. @@ -861,14 +952,14 @@ isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep) * Ignore it because the async event will clear things * up for us. */ - isp_prt(isp, ISP_LOGERR, atior, lun, aep->at_iid, 0); + isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0); break; default: isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from initiator %d for lun %d", - aep->at_status, aep->at_iid, lun); + aep->at_status, iid, lun); (void) isp_target_put_atio(isp, aep); break; } diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h index dff513dd5a1c..0386fcb96281 100644 --- a/sys/dev/isp/isp_target.h +++ b/sys/dev/isp/isp_target.h @@ -7,12 +7,9 @@ * pms@psconsult.com * All rights reserved. * - * Additional Copyright (c) 1999, 2000, 2001 - * Matthew Jacob - * mjacob@feral.com + * Additonal Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. * - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,6 +25,8 @@ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. @@ -120,6 +119,17 @@ typedef struct { u_int16_t in_seqid; /* sequence id */ } in_fcentry_t; +typedef struct { + isphdr_t in_header; + u_int32_t in_reserved; + u_int16_t in_iid; /* initiator */ + u_int16_t in_scclun; + u_int32_t in_reserved2; + u_int16_t in_status; + u_int16_t in_task_flags; + u_int16_t in_seqid; /* sequence id */ +} in_fcentry_e_t; + /* * Values for the in_status field */ @@ -205,6 +215,20 @@ typedef struct { u_int16_t na_seqid; /* sequence id */ u_int16_t na_reserved3[NA2_RSVDLEN]; } na_fcentry_t; + +typedef struct { + isphdr_t na_header; + u_int32_t na_reserved; + u_int16_t na_iid; /* initiator */ + u_int16_t na_scclun; + u_int16_t na_flags; + u_int16_t na_reserved2; + u_int16_t na_status; + u_int16_t na_task_flags; + u_int16_t na_seqid; /* sequence id */ + u_int16_t na_reserved3[NA2_RSVDLEN]; +} na_fcentry_e_t; + #define NAFC_RCOUNT 0x80 /* increment resource count */ #define NAFC_RST_CLRD 0x20 /* Clear LIP Reset */ /* @@ -254,30 +278,38 @@ typedef struct { tid |= (aep->at_tag_val << 16); \ tid |= (1 << 24); \ } \ - tid |= (inst << 25) + tid |= (GET_BUS_VAL(aep->at_iid) << 25); \ + tid |= (inst << 26) -#define CT_MAKE_TAGID(tid, inst, ct) \ +#define CT_MAKE_TAGID(tid, bus, inst, ct) \ tid = ct->ct_fwhandle; \ if (ct->ct_flags & CT_TQAE) { \ tid |= (ct->ct_tag_val << 16); \ tid |= (1 << 24); \ } \ - tid |= (inst << 25) + tid |= ((bus & 0x1) << 25); \ + tid |= (inst << 26) #define AT_HAS_TAG(val) ((val) & (1 << 24)) #define AT_GET_TAG(val) (((val) >> 16) & 0xff) -#define AT_GET_INST(val) (((val) >> 25) & 0x7f) +#define AT_GET_INST(val) (((val) >> 26) & 0x3f) +#define AT_GET_BUS(val) (((val) >> 25) & 0x1) #define AT_GET_HANDLE(val) ((val) & 0xffff) #define IN_MAKE_TAGID(tid, inst, inp) \ tid = inp->in_seqid; \ tid |= (inp->in_tag_val << 16); \ tid |= (1 << 24); \ - tid |= (inst << 25) + tid |= (GET_BUS_VAL(inp->in_iid) << 25); \ + tid |= (inst << 26) #define TAG_INSERT_INST(tid, inst) \ - tid &= ~(0x1ffffff); \ - tid |= (inst << 25) + tid &= ~(0x3ffffff); \ + tid |= (inst << 26) + +#define TAG_INSERT_BUS(tid, bus) \ + tid &= ~(1 << 25); \ + tid |= (bus << 25) /* * Accept Target I/O Entry structure, Type 2 @@ -304,6 +336,25 @@ typedef struct { u_int16_t at_oxid; } at2_entry_t; +typedef struct { + isphdr_t at_header; + u_int32_t at_reserved; + u_int16_t at_iid; /* initiator */ + u_int16_t at_rxid; /* response ID */ + u_int16_t at_flags; + u_int16_t at_status; /* firmware status */ + u_int8_t at_crn; /* command reference number */ + u_int8_t at_taskcodes; + u_int8_t at_taskflags; + u_int8_t at_execodes; + u_int8_t at_cdb[ATIO2_CDBLEN]; /* received CDB */ + u_int32_t at_datalen; /* allocated data len */ + u_int16_t at_scclun; /* SCC Lun or reserved */ + u_int16_t at_wwpn[4]; /* WWPN of initiator */ + u_int16_t at_reserved2[6]; + u_int16_t at_oxid; +} at2e_entry_t; + #define ATIO2_WWPN_OFFSET 0x2A #define ATIO2_OXID_OFFSET 0x3E @@ -332,6 +383,11 @@ typedef struct { #define AT2_GET_INST(val) ((val) >> 16) #define AT2_GET_HANDLE AT2_GET_TAG +#define FC_HAS_TAG AT2_HAS_TAG +#define FC_GET_TAG AT2_GET_TAG +#define FC_GET_INST AT2_GET_INST +#define FC_GET_HANDLE AT2_GET_HANDLE + #define IN_FC_MAKE_TAGID(tid, inst, inp) \ tid = inp->in_seqid; \ tid |= (inst << 16) @@ -381,8 +437,8 @@ typedef struct { * in the MSbit of ct_iid. Bit fields are a bit too awkward here. * * Note that this does not apply to FC adapters at all which can and - * do report IIDs between 129 && 255 (these represent devices that have - * logged in across a SCSI fabric). + * do report IIDs between 0x81 && 0xfe (or 0x7ff) which represent devices + * that have logged in across a SCSI fabric. */ #define GET_IID_VAL(x) (x & 0x3f) #define GET_BUS_VAL(x) ((x >> 7) & 0x1) @@ -430,6 +486,8 @@ typedef struct { #define CT_PORTCHANGED 0x2A /* port changed */ #define CT_IDE 0x33 /* Initiator Detected Error */ #define CT_NOACK 0x35 /* Outstanding Immed. Notify. entry */ +#define CT_SRR 0x45 /* SRR Received */ +#define CT_LUN_RESET 0x48 /* Lun Reset Received */ /* * When the firmware returns a CTIO entry, it may overwrite the last @@ -509,6 +567,48 @@ typedef struct { } rsp; } ct2_entry_t; +typedef struct { + isphdr_t ct_header; + u_int16_t ct_reserved; + u_int16_t ct_fwhandle; /* just to match CTIO */ + u_int16_t ct_iid; /* initiator id */ + u_int16_t ct_rxid; /* response ID */ + u_int16_t ct_flags; + u_int16_t ct_status; /* isp status */ + u_int16_t ct_timeout; + u_int16_t ct_seg_count; + u_int32_t ct_reloff; /* relative offset */ + int32_t ct_resid; /* residual length */ + union { + struct { + u_int32_t _reserved; + u_int16_t _reserved2; + u_int16_t ct_scsi_status; + u_int32_t ct_xfrlen; + union { + ispds_t ct_a[ISP_RQDSEG_T2]; /* CTIO2 */ + ispds64_t ct_b[ISP_RQDSEG_T3]; /* CTIO3 */ + ispdslist_t ct_c; /* CTIO4 */ + } _u; + } m0; + struct { + u_int16_t _reserved; + u_int16_t _reserved2; + u_int16_t ct_senselen; + u_int16_t ct_scsi_status; + u_int16_t ct_resplen; + u_int8_t ct_resp[MAXRESPLEN]; + } m1; + struct { + u_int32_t _reserved; + u_int16_t _reserved2; + u_int16_t _reserved3; + u_int32_t ct_datalen; + ispds_t ct_fcp_rsp_iudata; + } m2; + } rsp; +} ct2e_entry_t; + /* * ct_flags values for CTIO2 */ @@ -557,6 +657,12 @@ typedef struct { int isp_target_notify(struct ispsoftc *, void *, u_int16_t *); /* + * This function externalizes the ability to acknowledge an Immediate Notify + * request. + */ +void isp_notify_ack(struct ispsoftc *, void *); + +/* * Enable/Disable/Modify a logical unit. * (softc, cmd, bus, tgt, lun, cmd_cnt, inotify_cnt, opaque) */ @@ -589,6 +695,6 @@ int isp_endcmd(struct ispsoftc *, void *, u_int32_t, u_int16_t); * * Return nonzero if the interrupt that generated this event has been dismissed. */ - int isp_target_async(struct ispsoftc *, int, int); + #endif /* _ISP_TARGET_H */ diff --git a/sys/dev/isp/isp_tpublic.h b/sys/dev/isp/isp_tpublic.h index a2773323d68e..fdaaf16b5aff 100644 --- a/sys/dev/isp/isp_tpublic.h +++ b/sys/dev/isp/isp_tpublic.h @@ -1,16 +1,16 @@ /* $FreeBSD$ */ /*- * Qlogic ISP Host Adapter Public Target Interface Structures && Routines - *--------------------------------------- - * Copyright (c) 2000 by Matthew Jacob + * + * Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * @@ -25,38 +25,120 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * Matthew Jacob - * Feral Software - * mjacob@feral.com + */ +/* + * Qlogic ISP Host Adapter Public Target Interface Structures && Routines */ +#ifndef _ISP_TPUBLIC_H +#define _ISP_TPUBLIC_H 1 + /* - * Required software target mode message and event handling structures. - * - * The message and event structures are used by the MI layer - * to propagate messages and events upstream. + * Action codes set by the Qlogic MD target driver for + * the external layer to figure out what to do with. */ +typedef enum { + QOUT_HBA_REG=0, /* the argument is a pointer to a hba_register_t */ + QOUT_ENABLE, /* the argument is a pointer to a enadis_t */ + QOUT_DISABLE, /* the argument is a pointer to a enadis_t */ + QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */ + QOUT_TMD_DONE, /* the argument is a pointer to a tmd_cmd_t */ + QOUT_NOTIFY, /* the argument is a pointer to a tmd_notify_t */ + QOUT_HBA_UNREG /* the argument is a pointer to a hba_register_t */ +} tact_e; -#ifndef IN_MSGLEN -#define IN_MSGLEN 8 -#endif +/* + * Action codes set by the external layer for the + * MD Qlogic driver to figure out what to do with. + */ +typedef enum { + QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */ + QIN_ENABLE, /* the argument is a pointer to a enadis_t */ + QIN_DISABLE, /* the argument is a pointer to a enadis_t */ + QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */ + QIN_TMD_FIN, /* the argument is a pointer to a tmd_cmd_t */ + QIN_NOTIFY_ACK, /* the argument is a pointer to a tmd_notify_t */ + QIN_HBA_UNREG, /* the argument is a pointer to a hba_register_t */ +} qact_e; + +/* + * This structure is used to register to other software modules the + * binding of an HBA identifier, driver name and instance and the + * lun width capapbilities of this target driver. It's up to each + * platform to figure out how it wants to do this, but a typical + * sequence would be for the MD layer to find some external module's + * entry point and start by sending a QOUT_HBA_REG with info filled + * in, and the external module to call back with a QIN_HBA_REG that + * passes back the corresponding information. + */ +#define QR_VERSION 2 typedef struct { - void * nt_hba; /* HBA tag */ - u_int64_t nt_iid; /* inititator id */ - u_int64_t nt_tgt; /* target id */ - u_int64_t nt_lun; /* logical unit */ - u_int32_t nt_tagval; /* tag value */ - u_int8_t nt_bus; /* bus */ - u_int8_t nt_tagtype; /* tag type */ - u_int8_t nt_msg[IN_MSGLEN]; /* message content */ -} tmd_msg_t; + void * r_identity; + void (*r_action)(qact_e, void *); + char r_name[8]; + int r_inst; + int r_version; + enum { R_FC, R_SCSI } r_type; +} hba_register_t; +/* + * Notify structure + */ +typedef enum { + NT_ABORT_TASK=0x1000, + NT_ABORT_TASK_SET, + NT_CLEAR_ACA, + NT_CLEAR_TASK_SET, + NT_LUN_RESET, + NT_TARGET_RESET, + NT_BUS_RESET, + NT_LIP_RESET, + NT_LINK_UP, + NT_LINK_DOWN, + NT_LOGOUT, + NT_HBA_RESET +} tmd_ncode_t; + +typedef struct tmd_notify { + void * nt_hba; /* HBA tag */ + uint64_t nt_iid; /* inititator id */ + uint64_t nt_tgt; /* target id */ + uint16_t nt_lun; /* logical unit */ + uint16_t nt_padding; /* padding */ + uint32_t nt_tagval; /* tag value */ + tmd_ncode_t nt_ncode; /* action */ + void * nt_lreserved; + void * nt_hreserved; +} tmd_notify_t; +#define LUN_ANY 0xffff +#define INI_ANY ((uint64_t) -1) +#define TAG_ANY 0 +#define MATCH_TMD(tmd, iid, lun, tag) \ + ( \ + (tmd) && \ + (iid == INI_ANY || iid == tmd->cd_iid) && \ + (lun == LUN_ANY || lun == tmd->cd_lun) && \ + (tag == TAG_ANY || tag == tmd->cd_tagval) \ + ) + +/* + * A word about ENABLE/DISABLE: the argument is a pointer to a enadis_t + * with cd_hba, cd_iid, cd_chan, cd_tgt and cd_lun filled out. + * + * If an error occurs in either enabling or disabling the described lun + * cd_error is set with an appropriate non-zero value. + * + * Logical unit zero must be the first enabled and the last disabled. + */ typedef struct { - void * ev_hba; /* HBA tag */ - u_int32_t ev_bus; /* bus */ - u_int32_t ev_event; /* type of async event */ -} tmd_event_t; + void * en_private; /* for outer layer usage */ + void * en_hba; /* HBA tag */ + u_int64_t en_iid; /* initiator ID */ + u_int64_t en_tgt; /* target id */ + u_int64_t en_lun; /* logical unit */ + u_int8_t en_chan; /* channel on card */ + int32_t en_error; +} enadis_t; /* * Suggested Software Target Mode Command Handling structure. @@ -262,37 +344,6 @@ typedef struct tmd_cmd { /* - * Action codes set by the Qlogic MD target driver for - * the external layer to figure out what to do with. - */ -typedef enum { - QOUT_HBA_REG=0, /* the argument is a pointer to a hba_register_t */ - QOUT_ENABLE, /* the argument is a pointer to a enadis_t */ - QOUT_DISABLE, /* the argument is a pointer to a enadis_t */ - QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */ - QOUT_TMD_DONE, /* the argument is a pointer to a tmd_cmd_t */ - QOUT_TEVENT, /* the argument is a pointer to a tmd_event_t */ - QOUT_TMSG, /* the argument is a pointer to a tmd_msg_t */ - QOUT_IOCTL, /* the argument is a pointer to a ioctl_cmd_t */ - QOUT_HBA_UNREG /* the argument is a pointer to a hba_register_t */ -} tact_e; - -/* - * Action codes set by the external layer for the - * MD Qlogic driver to figure out what to do with. - */ -typedef enum { - QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */ - QIN_ENABLE, /* the argument is a pointer to a enadis_t */ - QIN_DISABLE, /* the argument is a pointer to a enadis_t */ - QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */ - QIN_TMD_FIN, /* the argument is a pointer to a tmd_cmd_t */ - QIN_IOCTL, /* the argument is a pointer to a ioctl_cmd_t */ - QIN_HBA_UNREG, /* the argument is a pointer to a hba_register_t */ -} qact_e; - - -/* * A word about the START/CONT/DONE/FIN dance: * * When the HBA is enabled for receiving commands, one may show up @@ -320,72 +371,6 @@ typedef enum { */ /* - * A word about ENABLE/DISABLE: the argument is a pointer to a enadis_t - * with cd_hba, cd_iid, cd_chan, cd_tgt and cd_lun filled out. - * - * If an error occurs in either enabling or disabling the described lun - * cd_error is set with an appropriate non-zero value. - * - * Logical unit zero must be the first enabled and the last disabled. - */ -typedef struct { - void * cd_private; /* for outer layer usage */ - void * cd_hba; /* HBA tag */ - u_int64_t cd_iid; /* initiator ID */ - u_int64_t cd_tgt; /* target id */ - u_int64_t cd_lun; /* logical unit */ - u_int8_t cd_chan; /* channel on card */ - int32_t cd_error; -} enadis_t; - -/* - * This structure is used to register to other software modules the - * binding of an HBA identifier, driver name and instance and the - * lun width capapbilities of this target driver. It's up to each - * platform to figure out how it wants to do this, but a typical - * sequence would be for the MD layer to find some external module's - * entry point and start by sending a QOUT_HBA_REG with info filled - * in, and the external module to call back with a QIN_HBA_REG that - * passes back the corresponding information. - */ -#define QR_VERSION 1 -typedef struct { - void * r_identity; - void (*r_action)(qact_e, void *); - char r_name[8]; - int r_inst; - int r_version; - enum { R_FC, R_SCSI } r_type; -} hba_register_t; - -/* - * This structure is used to pass an encapsulated ioctl through to the - * MD layer. In many implementations it's often convenient to open just - * one device, but actions you want to take need to be taken on the - * underlying HBA. Rather than invent a separate protocol for each action, - * an ioctl passthrough seems simpler. - * - * In order to avoid cross domain copy problems, though, the caller will - * be responsible for allocating and providing a staging area for all ioctl - * related data. This, unavoidably, requires some ioctl decode capability - * in the outer layer code.` - * - * And also, albeit being cheesy, we'll define a few internal ioctls here. - */ -typedef struct { - void * i_identity; /* HBA tag */ - void * i_syncptr; /* synchronization pointer */ - int i_cmd; /* ioctl command */ - void * i_arg; /* ioctl argument area */ - int i_errno; /* ioctl error return */ -} ioctl_cmd_t; - -#define QI_IOC ('Q' << 8) -#define QI_SCSI_TINI QI_IOC|0 -#define QI_SCSI_CMD QI_IOC|1 -#define QI_WWPN_XLT QI_IOC|2 - -/* * Target handler functions. * * The MD target handler function (the outer layer calls this) @@ -398,4 +383,4 @@ typedef struct { * * void system_target_handler(tact_e, void *arg) */ - +#endif /* _ISP_TPUBLIC_H */ diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index b810faaa6344..a7f5b90d91c1 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -2,7 +2,7 @@ /*- * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. * - * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob + * Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -160,10 +160,6 @@ #define MBOX_BUSY 0x04 -typedef struct { - u_int16_t param[8]; -} mbreg_t; - /* * Mailbox Command Complete Status Codes */ @@ -351,6 +347,7 @@ typedef struct { #define SYNC_DEVICE 0 #define SYNC_TARGET 1 #define SYNC_ALL 2 +#define SYNC_LIP 3 #define ISP_RQDSEG_T2 3 typedef struct { @@ -368,6 +365,20 @@ typedef struct { ispds_t req_dataseg[ISP_RQDSEG_T2]; } ispreqt2_t; +typedef struct { + isphdr_t req_header; + u_int32_t req_handle; + u_int16_t req_target; + u_int16_t req_scclun; + u_int16_t req_flags; + u_int16_t _res2; + u_int16_t req_time; + u_int16_t req_seg_count; + u_int8_t req_cdb[16]; + u_int32_t req_totalcnt; + ispds_t req_dataseg[ISP_RQDSEG_T2]; +} ispreqt2e_t; + #define ISP_RQDSEG_T3 2 typedef struct { isphdr_t req_header; @@ -384,6 +395,20 @@ typedef struct { ispds64_t req_dataseg[ISP_RQDSEG_T3]; } ispreqt3_t; +typedef struct { + isphdr_t req_header; + u_int32_t req_handle; + u_int16_t req_target; + u_int16_t req_scclun; + u_int16_t req_flags; + u_int16_t _res2; + u_int16_t req_time; + u_int16_t req_seg_count; + u_int8_t req_cdb[16]; + u_int32_t req_totalcnt; + ispds64_t req_dataseg[ISP_RQDSEG_T3]; +} ispreqt3e_t; + /* req_flag values */ #define REQFLAG_NODISCON 0x0001 #define REQFLAG_HTAG 0x0002 @@ -569,6 +594,12 @@ typedef struct { #define ISP_FW_ATTR_CLASS2 0x08 #define ISP_FW_ATTR_FCTAPE 0x10 #define ISP_FW_ATTR_IP 0x20 +#define ISP_FW_ATTR_VI 0x40 +#define ISP_FW_ATTR_VI_SOLARIS 0x80 +#define ISP_FW_ATTR_2KLOGINS 0x100 /* XXX: just a guess */ + +#define IS_2KLOGIN(isp) \ + (IS_FC(isp) && (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_2KLOGINS)) /* * Reduced Interrupt Operation Response Queue Entreis diff --git a/sys/dev/isp/ispreg.h b/sys/dev/isp/ispreg.h index 163ac9894d90..21d75ca7d4ec 100644 --- a/sys/dev/isp/ispreg.h +++ b/sys/dev/isp/ispreg.h @@ -3,7 +3,7 @@ * Machine Independent (well, as best as possible) register * definitions for Qlogic ISP SCSI adapters. * - * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob + * Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -371,15 +371,26 @@ #define OUTMAILBOX6 (MBOX_BLOCK+0xC) #define OUTMAILBOX7 (MBOX_BLOCK+0xE) +/* + * Strictly speaking, it's + * SCSI && 2100 : 8 MBOX registers + * 2200: 24 MBOX registers + * 2300: 32 MBOX registers + */ #define MBOX_OFF(n) (MBOX_BLOCK + ((n) << 1)) #define NMBOX(isp) \ (((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \ - ((isp)->isp_type & ISP_HA_FC))? 8 : 6) + ((isp)->isp_type & ISP_HA_FC))? 12 : 6) #define NMBOX_BMASK(isp) \ (((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \ - ((isp)->isp_type & ISP_HA_FC))? 0xff : 0x3f) - -#define MAX_MAILBOX 8 + ((isp)->isp_type & ISP_HA_FC))? 0xfff : 0x3f) + +#define MAX_MAILBOX(isp) ((IS_FC(isp))? 12 : 8) +#define MAILBOX_STORAGE 12 +typedef struct { + u_int16_t param[MAILBOX_STORAGE]; + u_int16_t ibits, obits; +} mbreg_t; /* * Fibre Protocol Module and Frame Buffer Register Offsets/Definitions (2X00). diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index e71a952cf8fd..ead95a9b62cc 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -2,7 +2,7 @@ /*- * Soft Definitions for for Qlogic ISP SCSI adapters. * - * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob + * Copyright (c) 1997-2006 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,7 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ #ifndef _ISPVAR_H @@ -174,7 +173,6 @@ typedef u_int32_t isp_dma_addr_t; /* * SCSI Specific Host Adapter Parameters- per bus, per target */ - typedef struct { u_int isp_gotdparms : 1, isp_req_ack_active_neg : 1, @@ -230,7 +228,6 @@ typedef struct { #define DPARM_DEFAULT (0xFF00 & ~DPARM_QFRZ) #define DPARM_SAFE_DFLT (DPARM_DEFAULT & ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING)) - /* technically, not really correct, as they need to be rated based upon clock */ #define ISP_80M_SYNCPARMS 0x0c09 #define ISP_40M_SYNCPARMS 0x0c0a @@ -254,8 +251,9 @@ typedef struct { #endif typedef struct { - u_int32_t isp_fwoptions : 16, - isp_gbspeed : 2, + u_int32_t : 13, + isp_gbspeed : 3, + : 2, isp_iid_set : 1, loop_seen_once : 1, isp_loopstate : 4, /* Current Loop State */ @@ -263,11 +261,11 @@ typedef struct { isp_gotdparms : 1, isp_topo : 3, isp_onfabric : 1; - u_int8_t isp_iid; /* 'initiator' id */ - u_int8_t isp_loopid; /* hard loop id */ - u_int8_t isp_alpa; /* ALPA */ - u_int32_t isp_portid; - volatile u_int16_t isp_lipseq; /* LIP sequence # */ + u_int32_t : 8, + isp_portid : 24; /* S_ID */ + u_int16_t isp_fwoptions; + u_int16_t isp_iid; /* 'initiator' id */ + u_int16_t isp_loopid; /* hard loop id */ u_int16_t isp_fwattr; /* firmware attributes */ u_int8_t isp_execthrottle; u_int8_t isp_retry_delay; @@ -287,20 +285,20 @@ typedef struct { * to move around. */ struct lportdb { - u_int32_t - port_type : 8, - loopid : 8, + u_int32_t loopid : 16, + : 2, fc4_type : 4, last_fabric_dev : 1, - : 2, relogin : 1, force_logout : 1, was_fabric_dev : 1, fabric_dev : 1, loggedin : 1, roles : 2, + tvalid : 1, valid : 1; - u_int32_t portid; + u_int32_t port_type : 8, + portid : 24; u_int64_t node_wwn; u_int64_t port_wwn; } portdb[MAX_FC_TARG], tport[FC_PORT_ID]; @@ -414,7 +412,7 @@ typedef struct ispsoftc { volatile u_int16_t isp_resodx; /* index of next result */ volatile u_int16_t isp_rspbsy; volatile u_int16_t isp_lasthdls; /* last handle seed */ - volatile u_int16_t isp_mboxtmp[MAX_MAILBOX]; + volatile u_int16_t isp_mboxtmp[MAILBOX_STORAGE]; volatile u_int16_t isp_lastmbxcmd; /* last mbox command sent */ volatile u_int16_t isp_mbxwrk0; volatile u_int16_t isp_mbxwrk1; @@ -554,6 +552,9 @@ typedef struct ispsoftc { #define ISP_HA_FC_2200 0x20 #define ISP_HA_FC_2300 0x30 #define ISP_HA_FC_2312 0x40 +#define ISP_HA_FC_2322 0x50 +#define ISP_HA_FC_2400 0x60 +#define ISP_HA_FC_2422 0x61 #define IS_SCSI(isp) (isp->isp_type & ISP_HA_SCSI) #define IS_1240(isp) (isp->isp_type == ISP_HA_SCSI_1240) @@ -574,6 +575,8 @@ typedef struct ispsoftc { #define IS_23XX(isp) ((isp)->isp_type >= ISP_HA_FC_2300) #define IS_2300(isp) ((isp)->isp_type == ISP_HA_FC_2300) #define IS_2312(isp) ((isp)->isp_type == ISP_HA_FC_2312) +#define IS_2322(isp) ((isp)->isp_type == ISP_HA_FC_2322) +#define IS_24XX(isp) ((isp)->isp_type >= ISP_HA_FC_2400) /* * DMA cookie macros @@ -742,9 +745,8 @@ typedef enum { ISPASYNC_CHANGE_NOTIFY, /* FC Change Notification */ ISPASYNC_FABRIC_DEV, /* FC Fabric Device Arrival */ ISPASYNC_PROMENADE, /* FC Objects coming && going */ - ISPASYNC_TARGET_MESSAGE, /* target message */ - ISPASYNC_TARGET_EVENT, /* target asynchronous event */ - ISPASYNC_TARGET_ACTION, /* other target command action */ + ISPASYNC_TARGET_NOTIFY, /* target asynchronous notification event */ + ISPASYNC_TARGET_ACTION, /* target action requested */ ISPASYNC_CONF_CHANGE, /* Platform Configuration Change */ ISPASYNC_UNHANDLED_RESPONSE, /* Unhandled Response Entry */ ISPASYNC_FW_CRASH, /* Firmware has crashed */ |
