diff options
author | mjacob <mjacob@FreeBSD.org> | 2006-01-23 06:23:37 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2006-01-23 06:23:37 +0000 |
commit | 2ad9b36fa169019b73c876cc2ce2a2a683bbe6d3 (patch) | |
tree | c610435fa91dd49869b88e957e07d5db355f11a9 /sys | |
parent | 3172ccca0f55366494c853ef0b578fbb01ddf1f8 (diff) | |
download | FreeBSD-src-2ad9b36fa169019b73c876cc2ce2a2a683bbe6d3.zip FreeBSD-src-2ad9b36fa169019b73c876cc2ce2a2a683bbe6d3.tar.gz |
First of several commits as this driver is dusted off and maybe brought
up to date. Principle changes for this reelase is to support 2K Port Login
firmware. This allows us to support the 2322 (and 2422 4Gb) cards which only
come with the 2K Port Login firmware. The 2322 should now work- but we don't
have firmware sets for it in ispfw (as the change to load 2K Port Login f/w
hasn't been made- that f/w is so big it has to be loaded in more than one
chunk).
Other changes are the beginnings of cleaning up some long standing target
mode issues. The next changes here will incorporate a lot of bug fixes
from others.
Finally, some copyright cleanup and attempts to make the parts of the
driver that are FreeBSD specific start conforming more to FreeBSD style.
MFC after: 1 month
Diffstat (limited to 'sys')
-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 cc0c3c1..a9666e9 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 de468f5..2268092 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 4b3a4d3..50b46bb 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 c09ec9c..e6649b8 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 099b104..7cf6149 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 b75867c..4d2810e 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 5f87f3d..8914d9a 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 1d4b397..f561cd9 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 dff513d..0386fcb 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 a277332..fdaaf16 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 b810faa..a7f5b90 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 163ac98..21d75ca 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 e71a952..ead95a9 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 */ |