diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index b880a45dec30..4f5537f5072a 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -64,26 +64,9 @@ __FBSDID("$FreeBSD$");
 /*
  * Local static data
  */
-static const char portshift[] =
-    "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)";
-static const char portdup[] =
-    "Target %d duplicates Target %d- killing off both";
-static const char retained[] =
-    "Retaining Loop ID 0x%x for Target %d (Port 0x%x)";
-static const char lretained[] =
-    "Retained login of Target %d (Loop ID 0x%x) Port 0x%x";
-static const char plogout[] =
-    "Logging out Target %d at Loop ID 0x%x (Port 0x%x)";
-static const char plogierr[] =
-    "Command Error in PLOGI for Port 0x%x (0x%x)";
-static const char nopdb[] =
-    "Could not get PDB for Device @ Port 0x%x";
-static const char pdbmfail1[] =
-    "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)";
-static const char pdbmfail2[] =
-    "PDB Port info for Device @ Port 0x%x does not match up (0x%x)";
-static const char ldumped[] =
-    "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch";
+static const char fconf[] =
+    "PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n"
+    " database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)";
 static const char notresp[] =
   "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
 static const char xact1[] =
@@ -95,9 +78,9 @@ static const char xact3[] =
 static const char pskip[] =
     "SCSI phase skipped for target %d.%d.%d";
 static const char topology[] =
-    "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";
+    "HBA PortID 0x%06x N-Port Handle %d, Connection Topology '%s'";
+static const char ourwwn[] =
+    "HBA WWNN 0x%08x%08x HBA WWPN 0x%08x%08x";
 static const char finmsg[] =
     "%d.%d.%d: FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x";
 static const char sc0[] =
@@ -115,38 +98,52 @@ static const char bun[] =
  */
 static int isp_parse_async(ispsoftc_t *, uint16_t);
 static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *,
-    uint16_t *);
+    uint32_t *);
 static void
-isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *);
+isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *);
+static void
+isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *);
 static void isp_fastpost_complete(ispsoftc_t *, uint16_t);
 static int isp_mbox_continue(ispsoftc_t *);
 static void isp_scsi_init(ispsoftc_t *);
 static void isp_scsi_channel_init(ispsoftc_t *, int);
 static void isp_fibre_init(ispsoftc_t *);
-static void isp_mark_getpdb_all(ispsoftc_t *);
-static int isp_getmap(ispsoftc_t *, fcpos_map_t *);
-static int isp_getpdb(ispsoftc_t *, int, isp_pdb_t *);
+static void isp_fibre_init_2400(ispsoftc_t *);
+static void isp_dump_portdb(ispsoftc_t *);
+static void isp_mark_portdb(ispsoftc_t *, int);
+static void isp_plogx_24xx(ispsoftc_t *, uint16_t, uint32_t, int *);
+static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t);
+static void isp_port_logout(ispsoftc_t *, uint16_t, uint32_t);
+static int isp_getpdb(ispsoftc_t *, uint16_t, isp_pdb_t *, int);
 static uint64_t isp_get_portname(ispsoftc_t *, int, int);
 static int isp_fclink_test(ispsoftc_t *, int);
 static const char *isp2100_fw_statename(int);
 static int isp_pdb_sync(ispsoftc_t *);
 static int isp_scan_loop(ispsoftc_t *);
-static int isp_fabric_mbox_cmd(ispsoftc_t *, mbreg_t *);
-static int isp_scan_fabric(ispsoftc_t *, int);
-static void isp_register_fc4_type(ispsoftc_t *);
+static int isp_gid_ft_sns(ispsoftc_t *);
+static int isp_gid_ft_ct_passthru(ispsoftc_t *);
+static int isp_scan_fabric(ispsoftc_t *);
+static int isp_login_device(ispsoftc_t *, uint32_t, isp_pdb_t *, uint16_t *);
+static int isp_register_fc4_type(ispsoftc_t *);
+static int isp_register_fc4_type_24xx(ispsoftc_t *);
+static uint16_t isp_nxt_handle(ispsoftc_t *, uint16_t);
 static void isp_fw_state(ispsoftc_t *);
 static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int);
-static void isp_mboxcmd(ispsoftc_t *, mbreg_t *, int);
+static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
 
 static void isp_update(ispsoftc_t *);
 static void isp_update_bus(ispsoftc_t *, int);
 static void isp_setdfltparm(ispsoftc_t *, int);
 static int isp_read_nvram(ispsoftc_t *);
+static int isp_read_nvram_2400(ispsoftc_t *);
 static void isp_rdnvram_word(ispsoftc_t *, int, uint16_t *);
+static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *);
 static void isp_parse_nvram_1020(ispsoftc_t *, uint8_t *);
 static void isp_parse_nvram_1080(ispsoftc_t *, int, uint8_t *);
 static void isp_parse_nvram_12160(ispsoftc_t *, int, uint8_t *);
+static void isp_fix_nvram_wwns(ispsoftc_t *);
 static void isp_parse_nvram_2100(ispsoftc_t *, uint8_t *);
+static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
 
 /*
  * Reset Hardware.
@@ -160,9 +157,10 @@ void
 isp_reset(ispsoftc_t *isp)
 {
 	mbreg_t mbs;
-	uint32_t code_org;
+	uint32_t code_org, val;
 	int loops, i, dodnld = 1;
-	char *btype = "????";
+	static const char *btype = "????";
+	static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
 
 	isp->isp_state = ISP_NILSTATE;
 
@@ -202,10 +200,16 @@ isp_reset(ispsoftc_t *isp)
 			/*
 			 * Just in case it was paused...
 			 */
-			ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
+			if (IS_24XX(isp)) {
+				ISP_WRITE(isp, BIU2400_HCCR,
+				    HCCR_2400_CMD_RELEASE);
+			} else {
+				ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
+			}
 			MEMZERO(&mbs, sizeof (mbs));
 			mbs.param[0] = MBOX_ABOUT_FIRMWARE;
-			isp_mboxcmd(isp, &mbs, MBLOGNONE);
+			mbs.logval = MBLOGNONE;
+			isp_mboxcmd(isp, &mbs);
 			if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
 				isp->isp_romfw_rev[0] = mbs.param[1];
 				isp->isp_romfw_rev[1] = mbs.param[2];
@@ -215,21 +219,51 @@ isp_reset(ispsoftc_t *isp)
 		isp->isp_touched = 1;
 	}
 
-	DISABLE_INTS(isp);
+	ISP_DISABLE_INTS(isp);
+
+	/*
+	 * Pick an initial maxcmds value which will be used
+	 * to allocate xflist pointer space. It may be changed
+	 * later by the firmware.
+	 */
+	if (IS_24XX(isp)) {
+		isp->isp_maxcmds = 4096;
+	} else if (IS_2322(isp)) {
+		isp->isp_maxcmds = 2048;
+	} else if (IS_23XX(isp) || IS_2200(isp)) {
+		isp->isp_maxcmds = 1024;
+ 	} else {
+		isp->isp_maxcmds = 512;
+	}
+
+	/*
+	 * Set up DMA for the request and result queues.
+	 *
+	 * We do this now so we can use the request queue
+	 * for a dma
+	 */
+	if (ISP_MBOXDMASETUP(isp) != 0) {
+		isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
+		return;
+	}
+
 
 	/*
 	 * Set up default request/response queue in-pointer/out-pointer
 	 * register indices.
 	 */
-	if (IS_23XX(isp)) {
+	if (IS_24XX(isp)) {
+		isp->isp_rqstinrp = BIU2400_REQINP;
+		isp->isp_rqstoutrp = BIU2400_REQOUTP;
+		isp->isp_respinrp = BIU2400_RSPINP;
+		isp->isp_respoutrp = BIU2400_RSPOUTP;
+		isp->isp_atioinrp = BIU2400_ATIO_RSPINP;
+		isp->isp_atiooutrp = BIU2400_ATIO_REQINP;
+	} else if (IS_23XX(isp)) {
 		isp->isp_rqstinrp = BIU_REQINP;
 		isp->isp_rqstoutrp = BIU_REQOUTP;
 		isp->isp_respinrp = BIU_RSPINP;
 		isp->isp_respoutrp = BIU_RSPOUTP;
-		ISP_WRITE(isp, isp->isp_rqstinrp, 0);
-        	ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
-        	ISP_WRITE(isp, isp->isp_respinrp, 0);
-		ISP_WRITE(isp, isp->isp_respoutrp, 0);
 	} else {
 		isp->isp_rqstinrp = INMAILBOX4;
 		isp->isp_rqstoutrp = OUTMAILBOX4;
@@ -241,7 +275,13 @@ isp_reset(ispsoftc_t *isp)
 	 * Put the board into PAUSE mode (so we can read the SXP registers
 	 * or write FPM/FBM registers).
 	 */
-	ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+	if (IS_24XX(isp)) {
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT);
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
+	} else {
+		ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+	}
 
 	if (IS_FC(isp)) {
 		switch (isp->isp_type) {
@@ -260,20 +300,24 @@ isp_reset(ispsoftc_t *isp)
 		case ISP_HA_FC_2322:
 			btype = "2322";
 			break;
-		case ISP_HA_FC_2422:
+		case ISP_HA_FC_2400:
 			btype = "2422";
 			break;
 		default:
 			break;
 		}
-		/*
-		 * While we're paused, reset the FPM module and FBM fifos.
-		 */
-		ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
-		ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
-		ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
-		ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
-		ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
+
+		if (!IS_24XX(isp)) {
+			/*
+			 * While we're paused, reset the FPM module and FBM
+			 * fifos.
+			 */
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
+			ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
+			ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
+		}
 	} else if (IS_1240(isp)) {
 		sdparam *sdp = isp->isp_param;
 		btype = "1240";
@@ -443,8 +487,6 @@ isp_reset(ispsoftc_t *isp)
 	 */
 	ISP_RESET0(isp);
 
-again:
-
 	/*
 	 * Hit the chip over the head with hammer,
 	 * and give the ISP a chance to recover.
@@ -466,6 +508,42 @@ isp_reset(ispsoftc_t *isp)
 		    DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
 
 
+	} else if (IS_24XX(isp)) {
+		/*
+		 * Stop DMA and wait for it to stop.
+		 */
+		ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
+		for (val = loops = 0; loops < 30000; loops++) {
+			USEC_DELAY(10);
+			val = ISP_READ(isp, BIU2400_CSR);
+			if ((val & BIU2400_DMA_ACTIVE) == 0) {
+				break;
+			}
+		} 
+		if (val & BIU2400_DMA_ACTIVE) {
+			isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
+			return;
+		}
+		/*
+		 * Hold it in SOFT_RESET and STOP state for 100us.
+		 */
+		ISP_WRITE(isp, BIU2400_CSR,
+		    BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
+		USEC_DELAY(100);
+		for (loops = 0; loops < 10000; loops++) {
+			USEC_DELAY(5);
+			val = ISP_READ(isp, OUTMAILBOX0);
+		}
+		for (val = loops = 0; loops < 500000; loops ++) {
+			val = ISP_READ(isp, BIU2400_CSR);
+			if ((val & BIU2400_SOFT_RESET) == 0) {
+				break;
+			}
+		}
+		if (val & BIU2400_SOFT_RESET) {
+			isp_prt(isp, ISP_LOGERR, "Failed to come out of reset");
+			return;
+		}
 	} else {
 		ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
 		/*
@@ -490,8 +568,13 @@ isp_reset(ispsoftc_t *isp)
 	loops = MBOX_DELAY_COUNT;
 	for (;;) {
 		if (IS_SCSI(isp)) {
-			if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET))
+			if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET)) {
 				break;
+			}
+		} else if (IS_24XX(isp)) {
+			if (ISP_READ(isp, OUTMAILBOX0) == 0) {
+				break;
+			}
 		} else {
 			if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET))
 				break;
@@ -510,24 +593,40 @@ isp_reset(ispsoftc_t *isp)
 
 	if (IS_SCSI(isp)) {
 		ISP_WRITE(isp, BIU_CONF1, 0);
-	} else {
+	} else if (!IS_24XX(isp)) {
 		ISP_WRITE(isp, BIU2100_CSR, 0);
 	}
 
 	/*
 	 * Reset RISC Processor
 	 */
-	ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
-	USEC_DELAY(100);
-	/* Clear semaphore register (just to be sure) */
-	ISP_WRITE(isp, BIU_SEMA, 0);
+	if (IS_24XX(isp)) {
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE);
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
+	} else {
+		ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
+		USEC_DELAY(100);
+		ISP_WRITE(isp, BIU_SEMA, 0);
+	}
 
+	
 	/*
-	 * Establish some initial burst rate stuff.
-	 * (only for the 1XX0 boards). This really should
-	 * be done later after fetching from NVRAM.
+	 * Post-RISC Reset stuff.
 	 */
-	if (IS_SCSI(isp)) {
+	if (IS_24XX(isp)) {
+		for (val = loops = 0; loops < 5000000; loops++) {
+			USEC_DELAY(5);
+			val = ISP_READ(isp, OUTMAILBOX0);
+			if (val == 0) {
+				break;
+			}
+		}
+		if (val != 0) {
+			isp_prt(isp, ISP_LOGERR, "reset didn't clear");
+			return;
+		}
+	} else if (IS_SCSI(isp)) {
 		uint16_t tmp = isp->isp_mdvec->dv_conf1;
 		/*
 		 * Busted FIFO. Turn off all but burst enables.
@@ -540,15 +639,36 @@ isp_reset(ispsoftc_t *isp)
 			ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);
 			ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);
 		}
-		ISP_WRITE(isp, RISC_MTR, 0x1212);
+		if (SDPARAM(isp)->isp_ptisp) {
+			if (SDPARAM(isp)->isp_ultramode) {
+				while (ISP_READ(isp, RISC_MTR) != 0x1313) {
+					ISP_WRITE(isp, RISC_MTR, 0x1313);
+					ISP_WRITE(isp, HCCR, HCCR_CMD_STEP);
+				}
+			} else {
+				ISP_WRITE(isp, RISC_MTR, 0x1212);
+			}
+			/*
+			 * PTI specific register
+			 */
+			ISP_WRITE(isp, RISC_EMB, DUAL_BANK);
+		} else {
+			ISP_WRITE(isp, RISC_MTR, 0x1212);
+		}
+		ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
 	} else {
 		ISP_WRITE(isp, RISC_MTR2100, 0x1212);
 		if (IS_2200(isp) || IS_23XX(isp)) {
 			ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE);
 		}
+		ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
 	}
 
-	ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); /* release paused processor */
+	ISP_WRITE(isp, isp->isp_rqstinrp, 0);
+	ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
+	ISP_WRITE(isp, isp->isp_respinrp, 0);
+	ISP_WRITE(isp, isp->isp_respoutrp, 0);
+
 
 	/*
 	 * Do MD specific post initialization
@@ -561,8 +681,8 @@ isp_reset(ispsoftc_t *isp)
 	 * Avoid doing this on the 2312 because you can generate a PCI
 	 * parity error (chip breakage).
 	 */
-	if (IS_23XX(isp)) {
-		USEC_DELAY(5);
+	if (IS_2312(isp)) {
+		USEC_DELAY(100);
 	} else {
 		loops = MBOX_DELAY_COUNT;
 		while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
@@ -586,12 +706,13 @@ isp_reset(ispsoftc_t *isp)
 	 */
 	MEMZERO(&mbs, sizeof (mbs));
 	mbs.param[0] = MBOX_NO_OP;
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return;
 	}
 
-	if (IS_SCSI(isp)) {
+	if (IS_SCSI(isp) || IS_24XX(isp)) {
 		MEMZERO(&mbs, sizeof (mbs));
 		mbs.param[0] = MBOX_MAILBOX_REG_TEST;
 		mbs.param[1] = 0xdead;
@@ -599,7 +720,10 @@ isp_reset(ispsoftc_t *isp)
 		mbs.param[3] = 0xffff;
 		mbs.param[4] = 0x1111;
 		mbs.param[5] = 0xa5a5;
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.param[6] = 0x0000;
+		mbs.param[7] = 0x0000;
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			return;
 		}
@@ -629,12 +753,170 @@ isp_reset(ispsoftc_t *isp)
 		dodnld = 0;
 	}
 
-	if (IS_23XX(isp)) {
+	if (IS_24XX(isp)) {
+		code_org = ISP_CODE_ORG_2400;
+	} else if (IS_23XX(isp)) {
 		code_org = ISP_CODE_ORG_2300;
 	} else {
 		code_org = ISP_CODE_ORG;
 	}
-	if (dodnld) {
+
+	if (dodnld && IS_24XX(isp)) {
+		uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
+
+		/*
+		 * NB: Whatever you do do, do *not* issue the VERIFY FIRMWARE
+		 * NB: command to the 2400 while loading new firmware. This
+		 * NB: causes the new f/w to start and immediately crash back
+		 * NB: to the ROM.
+		 */
+
+		/*
+		 * Keep loading until we run out of f/w.
+		 */
+		code_org = ptr[2];	/* 1st load address is our start addr */
+
+		for (;;) {
+			uint32_t la, wi, wl;
+
+			isp_prt(isp, ISP_LOGDEBUG0,
+			    "load 0x%x words of code at load address 0x%x",
+			    ptr[3], ptr[2]);
+
+			wi = 0;
+			la = ptr[2];
+			wl = ptr[3];
+
+			while (wi < ptr[3]) {
+				uint32_t *cp;
+				uint32_t nw;
+
+				nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 2;
+				if (nw > wl) {
+					nw = wl;
+				}
+				cp = isp->isp_rquest;
+				for (i = 0; i < nw; i++) {
+					cp[i] = ptr[wi++];
+					wl--;
+				}
+				MEMORYBARRIER(isp, SYNC_REQUEST,
+				    0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
+				MEMZERO(&mbs, sizeof (mbs));
+				mbs.param[0] = MBOX_LOAD_RISC_RAM;
+				mbs.param[1] = la;
+				mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
+				mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
+				mbs.param[4] = nw >> 16;
+				mbs.param[5] = nw;
+				mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
+				mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
+				mbs.param[8] = la >> 16;
+				mbs.logval = MBLOGALL;
+				isp_mboxcmd(isp, &mbs);
+				if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+					isp_prt(isp, ISP_LOGERR,
+					    "F/W Risc Ram Load Failed");
+					return;
+				}
+				la += nw;
+			}
+
+			if (ptr[1] == 0) {
+				break;
+			}
+			ptr += ptr[3];
+		} 
+		isp->isp_loaded_fw = 1;
+	} else if (dodnld && IS_23XX(isp)) {
+		uint16_t *ptr = isp->isp_mdvec->dv_ispfw;
+		uint16_t wi, wl, segno;
+		uint32_t la;
+
+		la = code_org;
+		segno = 0;
+
+		for (;;) {
+			uint32_t nxtaddr;
+
+			isp_prt(isp, ISP_LOGDEBUG0,
+			    "load 0x%x words of code at load address 0x%x",
+			    ptr[3], la);
+
+			wi = 0;
+			wl = ptr[3];
+
+			while (wi < ptr[3]) {
+				uint16_t *cp;
+				uint32_t nw;
+				
+				nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 1;
+				if (nw > wl) {
+					nw = wl;
+				}
+				if (nw > (1 << 15)) {
+					nw = 1 << 15;
+				}
+				cp = isp->isp_rquest;
+				for (i = 0; i < nw; i++) {
+					cp[i] = ptr[wi++];
+					wl--;
+				}
+				MEMORYBARRIER(isp, SYNC_REQUEST,
+				    0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
+				MEMZERO(&mbs, sizeof (mbs));
+				mbs.param[0] = MBOX_LOAD_RISC_RAM;
+				mbs.param[1] = la;
+				mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
+				mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
+				mbs.param[4] = nw;
+				mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
+				mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
+				mbs.param[8] = la >> 16;
+				mbs.logval = MBLOGALL;
+				isp_mboxcmd(isp, &mbs);
+				if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+					isp_prt(isp, ISP_LOGERR,
+					    "F/W Risc Ram Load Failed");
+					return;
+				}
+				la += nw;
+			}
+
+			if (!IS_2322(isp)) {
+				/*
+				 * Verify that it downloaded correctly.
+				 */
+				MEMZERO(&mbs, sizeof (mbs));
+				mbs.param[0] = MBOX_VERIFY_CHECKSUM;
+				mbs.param[1] = code_org;
+				mbs.logval = MBLOGNONE;
+				isp_mboxcmd(isp, &mbs);
+				if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+					isp_prt(isp, ISP_LOGERR, dcrc);
+					return;
+				}
+				break;
+			}
+
+			if (++segno == 3) {
+				break;
+			}
+
+			/*
+			 * If we're a 2322, the firmware actually comes in
+			 * three chunks. We loaded the first at the code_org
+			 * address. The other two chunks, which follow right
+			 * after each other in memory here, get loaded at
+			 * addresses specfied at offset 0x9..0xB.
+			 */
+
+			nxtaddr = ptr[3];
+			ptr = &ptr[nxtaddr];
+			la = ptr[5] | ((ptr[4] & 0x3f) << 16);
+		}
+		isp->isp_loaded_fw = 1;
+	} else if (dodnld) {
 		uint16_t *ptr = isp->isp_mdvec->dv_ispfw;
 
 		isp->isp_mbxworkp = &ptr[1];
@@ -644,76 +926,25 @@ isp_reset(ispsoftc_t *isp)
 		mbs.param[0] = MBOX_WRITE_RAM_WORD;
 		mbs.param[1] = code_org;
 		mbs.param[2] = ptr[0];
-		isp_mboxcmd(isp, &mbs, MBLOGNONE);
+		mbs.logval = MBLOGNONE;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			isp_prt(isp, ISP_LOGERR,
 			    "F/W download failed at word %d",
 			    isp->isp_mbxwrk1 - code_org);
-			dodnld = 0;
-			goto again;
+			return;
 		}
-
 		/*
-		 * If we're a 2322, the firmware actually comes in three chunks.
-		 * We loaded the first at the code_org address. The other two
-		 * chunks, which follow right after each other in memory here,
-		 * get loaded at addresses specfied at offset 0x9..0xB.
+		 * Verify that it downloaded correctly.
 		 */
-		if (IS_2322(isp)) {
-			uint32_t nxtaddr;
-			uint32_t offset;
-
-			nxtaddr = ptr[3];
-			ptr = &ptr[nxtaddr];
-			offset = ptr[5] | (((uint32_t)(ptr[4] & 0x3f)) << 16);
-			isp->isp_mbxworkp = &ptr[1];
-			isp->isp_mbxwrk0 = ptr[3] - 1;
-			isp->isp_mbxwrk1 = offset + 1;
-			isp->isp_mbxwrk8 = (offset + 1) >> 16;
-			MEMZERO(&mbs, sizeof (mbs));
-			mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED;
-			mbs.param[1] = offset;
-			mbs.param[2] = ptr[0];
-			mbs.param[8] = offset >> 16;
-			isp_mboxcmd(isp, &mbs, MBLOGNONE);
-			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-				isp_prt(isp, ISP_LOGERR,
-				    "Receive Sequencer F/W Load Failed");
-				return;
-			}
-
-			nxtaddr = ptr[3];
-			ptr = &ptr[nxtaddr];
-			offset = ptr[5] | (((uint32_t)(ptr[4] & 0x3f)) << 16);
-			isp->isp_mbxworkp = &ptr[1];
-			isp->isp_mbxwrk0 = ptr[3] - 1;
-			isp->isp_mbxwrk1 = (offset + 1);
-			isp->isp_mbxwrk8 = (offset + 1) >> 16;
-			MEMZERO(&mbs, sizeof (mbs));
-			mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED;
-			mbs.param[1] = offset;
-			mbs.param[2] = ptr[0];
-			mbs.param[8] = offset >> 16;
-			isp_mboxcmd(isp, &mbs, MBLOGNONE);
-			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-				isp_prt(isp, ISP_LOGERR,
-				    "Transmit Sequencer F/W Load Failed");
-				return;
-			}
-		} else {
-			/*
-			 * Verify that it downloaded correctly.
-			 */
-			MEMZERO(&mbs, sizeof (mbs));
-			mbs.param[0] = MBOX_VERIFY_CHECKSUM;
-			mbs.param[1] = code_org;
-			isp_mboxcmd(isp, &mbs, MBLOGNONE);
-			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-				isp_prt(isp, ISP_LOGERR,
-				    "Downloaded RISC Code Checksum Failure");
-				return;
-			}
-
+		MEMZERO(&mbs, sizeof (mbs));
+		mbs.param[0] = MBOX_VERIFY_CHECKSUM;
+		mbs.param[1] = code_org;
+		mbs.logval = MBLOGNONE;
+		isp_mboxcmd(isp, &mbs);
+		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+			isp_prt(isp, ISP_LOGERR, dcrc);
+			return;
 		}
 		isp->isp_loaded_fw = 1;
 	} else {
@@ -730,28 +961,39 @@ isp_reset(ispsoftc_t *isp)
 
 
 	MEMZERO(&mbs, sizeof (mbs));
+	mbs.timeout = 1000000;
 	mbs.param[0] = MBOX_EXEC_FIRMWARE;
-	mbs.param[1] = code_org;
-	if (IS_2322(isp) || IS_24XX(isp)) {
+	if (IS_24XX(isp)) {
+		mbs.param[1] = code_org >> 16;
+		mbs.param[2] = code_org;
+		if (isp->isp_loaded_fw) {
+			mbs.param[3] = 0;
+		} else {
+			mbs.param[3] = 1;
+		}
+	} else if (IS_2322(isp)) {
+		mbs.param[1] = code_org;
 		if (isp->isp_loaded_fw) {
 			mbs.param[2] = 0;
 		} else {
 			mbs.param[2] = 1;
 		}
+	} else {
+		mbs.param[1] = code_org;
 	}
-	isp_mboxcmd(isp, &mbs, MBLOGNONE);
+
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (IS_2322(isp) || IS_24XX(isp)) {
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-			isp_prt(isp, ISP_LOGERR, "EXEC F/W failed: 0x%x",
-			    mbs.param[0]);
 			return;
 		}
 	}
 
 	/*
-	 * Give it a chance to start.
+	 * Give it a chance to finish starting up.
 	 */
-	USEC_DELAY(500);
+	USEC_DELAY(250000);
 
 	if (IS_SCSI(isp)) {
 		/*
@@ -760,18 +1002,25 @@ isp_reset(ispsoftc_t *isp)
 		if (isp->isp_clock) {
 			mbs.param[0] = MBOX_SET_CLOCK_RATE;
 			mbs.param[1] = isp->isp_clock;
-			isp_mboxcmd(isp, &mbs, MBLOGALL);
+			mbs.logval = MBLOGNONE;
+			isp_mboxcmd(isp, &mbs);
 			/* we will try not to care if this fails */
 		}
 	}
 
 	MEMZERO(&mbs, sizeof (mbs));
 	mbs.param[0] = MBOX_ABOUT_FIRMWARE;
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return;
 	}
 
+	if (IS_24XX(isp) && mbs.param[1] == 0xdead) {
+		isp_prt(isp, ISP_LOGERR, "f/w didn't *really* start");
+		return;
+	}
+
 	/*
 	 * The SBus firmware that we are using apparently does not return
 	 * major, minor, micro revisions in the mailbox registers, which
@@ -794,7 +1043,7 @@ isp_reset(ispsoftc_t *isp)
 		isp->isp_fwrev[2] = mbs.param[3];
 	}
 
-	isp_prt(isp, ISP_LOGCONFIG,
+	isp_prt(isp, ISP_LOGALL,
 	    "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
 	    btype, isp->isp_revision, dodnld? "loaded" : "resident",
 	    isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
@@ -805,9 +1054,9 @@ isp_reset(ispsoftc_t *isp)
 		 * than 1.17.0, unless it's the firmware we specifically
 		 * are loading.
 		 *
-		 * Note that all 22XX and 23XX f/w is greater than 1.X.0.
+		 * Note that all 22XX and later f/w is greater than 1.X.0.
 		 */
-		if (!(ISP_FW_NEWER_THAN(isp, 1, 17, 0))) {
+		if ((ISP_FW_OLDER_THAN(isp, 1, 17, 1))) {
 #ifdef	USE_SMALLER_2100_FIRMWARE
 			FCPARAM(isp)->isp_fwattr = ISP_FW_ATTR_SCCLUN;
 #else
@@ -818,7 +1067,26 @@ isp_reset(ispsoftc_t *isp)
 			isp_prt(isp, ISP_LOGDEBUG0,
 			    "Firmware Attributes = 0x%x", mbs.param[6]);
 		}
-		if (IS_2KLOGIN(isp)) {
+		FCPARAM(isp)->isp_2klogin = 0;
+		FCPARAM(isp)->isp_sccfw = 0;
+		FCPARAM(isp)->isp_tmode = 0;
+		if (IS_24XX(isp)) {
+			FCPARAM(isp)->isp_2klogin = 1;
+			FCPARAM(isp)->isp_sccfw = 1;
+			FCPARAM(isp)->isp_tmode = 1;
+		} else {
+			if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
+				FCPARAM(isp)->isp_sccfw = 1;
+			}
+			if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_2KLOGINS) {
+				FCPARAM(isp)->isp_2klogin = 1;
+				FCPARAM(isp)->isp_sccfw = 1;
+			}
+			if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) {
+				FCPARAM(isp)->isp_tmode = 1;
+			}
+		}
+		if (FCPARAM(isp)->isp_2klogin) {
 			isp_prt(isp, ISP_LOGCONFIG, "2K Logins Supported");
 		}
 	}
@@ -830,24 +1098,22 @@ isp_reset(ispsoftc_t *isp)
 		    isp->isp_romfw_rev[2]);
 	}
 
-	MEMZERO(&mbs, sizeof (mbs));
-	mbs.param[0] = MBOX_GET_FIRMWARE_STATUS;
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
-	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-		return;
+	if (!IS_24XX(isp)) {
+		MEMZERO(&mbs, sizeof (mbs));
+		mbs.param[0] = MBOX_GET_FIRMWARE_STATUS;
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
+		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+			return;
+		}
+		if (isp->isp_maxcmds >= mbs.param[2]) {
+			isp->isp_maxcmds = mbs.param[2];
+		}
 	}
-	isp->isp_maxcmds = mbs.param[2];
-	isp_prt(isp, ISP_LOGINFO,
-	    "%d max I/O commands supported", mbs.param[2]);
+	isp_prt(isp, ISP_LOGCONFIG,
+	    "%d max I/O command limit set", isp->isp_maxcmds);
 	isp_fw_state(isp);
 
-	/*
-	 * Set up DMA for the request and result mailboxes.
-	 */
-	if (ISP_MBOXDMASETUP(isp) != 0) {
-		isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
-		return;
-	}
 	isp->isp_state = ISP_RESETSTATE;
 
 	/*
@@ -878,7 +1144,7 @@ isp_reset(ispsoftc_t *isp)
 			isp->isp_maxluns = 8;
 		}
 	} else {
-		if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
+		if (FCPARAM(isp)->isp_sccfw) {
 			isp->isp_maxluns = 16384;
 		} else {
 			isp->isp_maxluns = 16;
@@ -902,8 +1168,22 @@ isp_init(ispsoftc_t *isp)
 	if (IS_DUALBUS(isp)) {
 		isp_setdfltparm(isp, 1);
 	}
+
 	if (IS_FC(isp)) {
-		isp_fibre_init(isp);
+		/*
+		 * Do this *before* initializing the firmware.
+		 */
+		isp_mark_portdb(isp, 0);
+		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
+		FCPARAM(isp)->isp_loopstate = LOOP_NIL;
+
+		if (isp->isp_role != ISP_ROLE_NONE) {
+			if (IS_24XX(isp)) {
+				isp_fibre_init_2400(isp);
+			} else {
+				isp_fibre_init(isp);
+			}
+		}
 	} else {
 		isp_scsi_init(isp);
 	}
@@ -947,8 +1227,8 @@ isp_scsi_init(ispsoftc_t *isp)
 	mbs.param[2] = sdp_chan0->isp_retry_delay;
 	mbs.param[6] = sdp_chan1->isp_retry_count;
 	mbs.param[7] = sdp_chan1->isp_retry_delay;
-
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return;
 	}
@@ -960,7 +1240,8 @@ isp_scsi_init(ispsoftc_t *isp)
 	mbs.param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME;
 	mbs.param[1] = sdp_chan0->isp_async_data_setup;
 	mbs.param[2] = sdp_chan1->isp_async_data_setup;
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return;
 	}
@@ -976,9 +1257,8 @@ isp_scsi_init(ispsoftc_t *isp)
 	mbs.param[2] =
 	    (sdp_chan1->isp_req_ack_active_neg << 4) |
 	    (sdp_chan1->isp_data_line_active_neg << 5);
-
-	MEMZERO(&mbs, sizeof (mbs));
-	isp_mboxcmd(isp, &mbs, MBLOGNONE);
+	mbs.logval = MBLOGNONE;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		isp_prt(isp, ISP_LOGERR,
 		    "failed to set active negation state (%d,%d), (%d,%d)",
@@ -998,7 +1278,8 @@ isp_scsi_init(ispsoftc_t *isp)
 	mbs.param[0] = MBOX_SET_TAG_AGE_LIMIT;
 	mbs.param[1] = sdp_chan0->isp_tag_aging;
 	mbs.param[2] = sdp_chan1->isp_tag_aging;
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)",
 		    sdp_chan0->isp_tag_aging, sdp_chan1->isp_tag_aging);
@@ -1012,7 +1293,8 @@ isp_scsi_init(ispsoftc_t *isp)
 	mbs.param[0] = MBOX_SET_SELECT_TIMEOUT;
 	mbs.param[1] = sdp_chan0->isp_selection_timeout;
 	mbs.param[2] = sdp_chan1->isp_selection_timeout;
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return;
 	}
@@ -1035,7 +1317,8 @@ isp_scsi_init(ispsoftc_t *isp)
 		mbs.param[4] = 0;
 		mbs.param[6] = DMA_WD3(isp->isp_result_dma);
 		mbs.param[7] = DMA_WD2(isp->isp_result_dma);
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			return;
 		}
@@ -1049,7 +1332,8 @@ isp_scsi_init(ispsoftc_t *isp)
 		mbs.param[5] = 0;
 		mbs.param[6] = DMA_WD3(isp->isp_result_dma);
 		mbs.param[7] = DMA_WD2(isp->isp_result_dma);
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			return;
 		}
@@ -1061,7 +1345,8 @@ isp_scsi_init(ispsoftc_t *isp)
 		mbs.param[2] = DMA_WD1(isp->isp_result_dma);
 		mbs.param[3] = DMA_WD0(isp->isp_result_dma);
 		mbs.param[4] = 0;
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			return;
 		}
@@ -1073,7 +1358,8 @@ isp_scsi_init(ispsoftc_t *isp)
 		mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
 		mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
 		mbs.param[5] = 0;
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			return;
 		}
@@ -1103,7 +1389,8 @@ isp_scsi_init(ispsoftc_t *isp)
 #endif
 	if (mbs.param[1] != 0) {
 		uint16_t sfeat = mbs.param[1];
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
 			isp_prt(isp, ISP_LOGINFO,
 			    "Enabled FW features (0x%x)", sfeat);
@@ -1132,7 +1419,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
 	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);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return;
 	}
@@ -1188,7 +1476,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
 		    "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x",
 		    channel, tgt, mbs.param[2], mbs.param[3] >> 8,
 		    mbs.param[3] & 0xff);
-		isp_mboxcmd(isp, &mbs, MBLOGNONE);
+		mbs.logval = MBLOGNONE;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			sdf = DPARM_SAFE_DFLT;
 			MEMZERO(&mbs, sizeof (mbs));
@@ -1196,7 +1485,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
 			mbs.param[1] = (tgt << 8) | (channel << 15);
 			mbs.param[2] = sdf;
 			mbs.param[3] = 0;
-			isp_mboxcmd(isp, &mbs, MBLOGALL);
+			mbs.logval = MBLOGALL;
+			isp_mboxcmd(isp, &mbs);
 			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 				continue;
 			}
@@ -1220,7 +1510,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
 			mbs.param[1] = (channel << 15) | (tgt << 8) | lun;
 			mbs.param[2] = sdp->isp_max_queue_depth;
 			mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle;
-			isp_mboxcmd(isp, &mbs, MBLOGALL);
+			mbs.logval = MBLOGALL;
+			isp_mboxcmd(isp, &mbs);
 			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 				break;
 			}
@@ -1237,8 +1528,6 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
 
 /*
  * Fibre Channel specific initialization.
- *
- * Locks are held before coming here.
  */
 static void
 isp_fibre_init(ispsoftc_t *isp)
@@ -1246,28 +1535,13 @@ isp_fibre_init(ispsoftc_t *isp)
 	fcparam *fcp;
 	isp_icb_t local, *icbp = &local;
 	mbreg_t mbs;
-	int loopid;
 	uint64_t nwwn, pwwn;
 
 	fcp = isp->isp_param;
 
-	/*
-	 * Do this *before* initializing the firmware.
-	 */
-	isp_mark_getpdb_all(isp);
-	fcp->isp_fwstate = FW_CONFIG_WAIT;
-	fcp->isp_loopstate = LOOP_NIL;
-
-	/*
-	 * If we have no role (neither target nor initiator), return.
-	 */
-	if (isp->isp_role == ISP_ROLE_NONE) {
-		return;
-	}
-
-	loopid = fcp->isp_loopid;
 	MEMZERO(icbp, sizeof (*icbp));
 	icbp->icb_version = ICB_VERSION1;
+	icbp->icb_fwoptions = fcp->isp_fwoptions;
 
 	/*
 	 * Firmware Options are either retrieved from NVRAM or
@@ -1279,8 +1553,8 @@ isp_fibre_init(ispsoftc_t *isp)
 	/*
 	 * If this is a 2100 < revision 5, we have to turn off FAIRNESS.
 	 */
-	if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) {
-		fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS;
+	if (IS_2100(isp) && isp->isp_revision < 5) {
+		icbp->icb_fwoptions &= ~ICBOPT_FAIRNESS;
 	}
 
 	/*
@@ -1289,33 +1563,29 @@ isp_fibre_init(ispsoftc_t *isp)
 	 * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0.
 	 */
 	if (!ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
-		fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
+		icbp->icb_fwoptions |= ICBOPT_FULL_LOGIN;
 	}
 
 	/*
 	 * Insist on Port Database Update Async notifications
 	 */
-	fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
+	icbp->icb_fwoptions |= ICBOPT_PDBCHANGE_AE;
 
 	/*
 	 * Make sure that target role reflects into fwoptions.
 	 */
 	if (isp->isp_role & ISP_ROLE_TARGET) {
-		fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE;
+		icbp->icb_fwoptions |= ICBOPT_TGT_ENABLE;
 	} else {
-		fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE;
+		icbp->icb_fwoptions &= ~ICBOPT_TGT_ENABLE;
 	}
 
 	if (isp->isp_role & ISP_ROLE_INITIATOR) {
-		fcp->isp_fwoptions &= ~ICBOPT_INI_DISABLE;
+		icbp->icb_fwoptions &= ~ICBOPT_INI_DISABLE;
 	} else {
-		fcp->isp_fwoptions |= ICBOPT_INI_DISABLE;
+		icbp->icb_fwoptions |= ICBOPT_INI_DISABLE;
 	}
 
-	/*
-	 * Propagate all of this into the ICB structure.
-	 */
-	icbp->icb_fwoptions = fcp->isp_fwoptions;
 	icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;
 	if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN ||
 	    icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
@@ -1339,7 +1609,7 @@ isp_fibre_init(ispsoftc_t *isp)
 	}
 	icbp->icb_retry_delay = fcp->isp_retry_delay;
 	icbp->icb_retry_count = fcp->isp_retry_count;
-	icbp->icb_hardaddr = loopid;
+	icbp->icb_hardaddr = fcp->isp_loopid;
 	if (icbp->icb_hardaddr > 125) {
 		/*
 		 * We end up with these Loop IDs for F-Port topologies
@@ -1434,7 +1704,11 @@ isp_fibre_init(ispsoftc_t *isp)
 		mbs.param[1] = 0xb;
 		mbs.param[2] = 0;
 		mbs.param[3] = 0;
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
+		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+			return;
+		}
 	}
 	icbp->icb_logintime = ICB_LOGIN_TOV;
 	icbp->icb_lunetimeout = ICB_LUN_ENABLE_TOV;
@@ -1451,9 +1725,16 @@ isp_fibre_init(ispsoftc_t *isp)
 		    ((uint32_t) (nwwn & 0xffffffff)),
 		    ((uint32_t) (pwwn >> 32)),
 		    ((uint32_t) (pwwn & 0xffffffff)));
+	} else if (pwwn) {
+		icbp->icb_fwoptions &= ~ICBOPT_BOTH_WWNS;
+		MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
+		isp_prt(isp, ISP_LOGDEBUG1,
+		    "Setting ICB Port 0x%08x%08x",
+		    ((uint32_t) (pwwn >> 32)),
+		    ((uint32_t) (pwwn & 0xffffffff)));
 	} else {
-		isp_prt(isp, ISP_LOGDEBUG1, "Not using any WWNs");
-		icbp->icb_fwoptions &= ~(ICBOPT_BOTH_WWNS|ICBOPT_FULL_LOGIN);
+		isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
+		return;
 	}
 	icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
 	if (icbp->icb_rqstqlen < 1) {
@@ -1488,18 +1769,277 @@ isp_fibre_init(ispsoftc_t *isp)
 	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
 	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
 	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+	mbs.logval = MBLOGALL;
+	mbs.timeout = 30 * 1000000;
 	isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %p (%08x%08x)",
 	    fcp->isp_scratch, (uint32_t) ((uint64_t)fcp->isp_scdma >> 32),
 	    (uint32_t) fcp->isp_scdma);
 	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp));
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	isp_mboxcmd(isp, &mbs);
 	FC_SCRATCH_RELEASE(isp);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return;
 	}
-	isp->isp_reqidx = isp->isp_reqodx = 0;
+	isp->isp_reqidx = 0;
+	isp->isp_reqodx = 0;
+	isp->isp_residx = 0;
+
+	/*
+	 * Whatever happens, we're now committed to being here.
+	 */
+	isp->isp_state = ISP_INITSTATE;
+}
+
+static void
+isp_fibre_init_2400(ispsoftc_t *isp)
+{
+	fcparam *fcp;
+	isp_icb_2400_t local, *icbp = &local;
+	mbreg_t mbs;
+	uint64_t nwwn, pwwn;
+
+	fcp = isp->isp_param;
+
+	/*
+	 * Turn on LIP F8 async event (1)
+	 */
+	MEMZERO(&mbs, sizeof (mbs));
+	mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS;
+	mbs.param[1] = 1;
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		return;
+	}
+
+	/*
+	 * XXX: This should be applied to icb- not fwoptions
+	 */
+	if (isp->isp_role & ISP_ROLE_TARGET) {
+		fcp->isp_fwoptions |= ICB2400_OPT1_TGT_ENABLE;
+	} else {
+		fcp->isp_fwoptions &= ~ICB2400_OPT1_TGT_ENABLE;
+	}
+
+	if (isp->isp_role & ISP_ROLE_INITIATOR) {
+		fcp->isp_fwoptions &= ~ICB2400_OPT1_INI_DISABLE;
+	} else {
+		fcp->isp_fwoptions |= ICB2400_OPT1_INI_DISABLE;
+	}
+
+	MEMZERO(icbp, sizeof (*icbp));
+	icbp->icb_version = ICB_VERSION1;
+	icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;
+	if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN ||
+	    icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
+		isp_prt(isp, ISP_LOGERR,
+		    "bad frame length (%d) from NVRAM- using %d",
+		    fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN);
+		icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
+	}
+
+	icbp->icb_execthrottle = fcp->isp_execthrottle;
+	if (icbp->icb_execthrottle < 1) {
+		isp_prt(isp, ISP_LOGERR,
+		    "bad execution throttle of %d- using 16",
+		    fcp->isp_execthrottle);
+		icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
+	}
+
+	if (isp->isp_role & ISP_ROLE_TARGET) {
+		/*
+		 * Get current resource count
+		 */
+		MEMZERO(&mbs, sizeof (mbs));
+		mbs.param[0] = MBOX_GET_RESOURCE_COUNT;
+		mbs.obits = 0x4cf;
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
+		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+			return;
+		}
+		icbp->icb_xchgcnt = mbs.param[3];
+	}
+
+	icbp->icb_fwoptions1 = fcp->isp_fwoptions;
+
+	icbp->icb_hardaddr = fcp->isp_loopid;
+	if (icbp->icb_hardaddr > 125) {
+		/*
+		 * We end up with these Loop IDs for F-Port topologies
+		 */
+		if (icbp->icb_hardaddr != 0xff && icbp->icb_hardaddr != 0x800) {
+			isp_prt(isp, ISP_LOGERR,
+			    "bad hard address %u- resetting to zero",
+			    icbp->icb_hardaddr); 
+			icbp->icb_hardaddr = 0;
+		}
+	}
+
+	if (isp->isp_confopts & ISP_CFG_OWNLOOPID) {
+		icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
+	}
+
+	icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
+	switch(isp->isp_confopts & ISP_CFG_PORT_PREF) {
+	case ISP_CFG_NPORT:
+		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
+		icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_2_LOOP;
+		break;
+	case ISP_CFG_NPORT_ONLY:
+		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
+		icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
+		break;
+	case ISP_CFG_LPORT_ONLY:
+		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
+		icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
+		break;
+	default:
+		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
+		icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
+		break;
+	}
+
+	switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
+	case ICB2400_OPT2_ZIO:
+	case ICB2400_OPT2_ZIO1:
+		icbp->icb_idelaytimer = 0;
+		break;
+	case 0:
+		break;
+	default:
+		isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field",
+		    icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
+		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
+		break;
+	}
+
+	icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
+	icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_AUTO;
+	if (isp->isp_confopts & ISP_CFG_ONEGB) {
+		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_ONEGB;
+	} else if (isp->isp_confopts & ISP_CFG_TWOGB) {
+		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_TWOGB;
+	} else if (isp->isp_confopts & ISP_CFG_FOURGB) {
+		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_FOURGB;
+	} else {
+		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
+	}
+
+	if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
+		icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
+	}
+	icbp->icb_logintime = ICB_LOGIN_TOV;
+
+	nwwn = ISP_NODEWWN(isp);
+	pwwn = ISP_PORTWWN(isp);
+
+	if (nwwn && pwwn) {
+		icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
+		MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn);
+		MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
+		isp_prt(isp, ISP_LOGDEBUG1,
+		    "Setting ICB Node 0x%08x%08x Port 0x%08x%08x",
+		    ((uint32_t) (nwwn >> 32)),
+		    ((uint32_t) (nwwn & 0xffffffff)),
+		    ((uint32_t) (pwwn >> 32)),
+		    ((uint32_t) (pwwn & 0xffffffff)));
+	} else if (pwwn) {
+		icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
+		MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
+		isp_prt(isp, ISP_LOGDEBUG1,
+		    "Setting ICB Port 0x%08x%08x",
+		    ((uint32_t) (pwwn >> 32)),
+		    ((uint32_t) (pwwn & 0xffffffff)));
+	} else {
+		isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
+		return;
+	}
+	icbp->icb_retry_count = fcp->isp_retry_count;
+
+	icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
+	if (icbp->icb_rqstqlen < 8) {
+		isp_prt(isp, ISP_LOGERR, "bad request queue length %d",
+		    icbp->icb_rqstqlen);
+		return;
+	}
+	icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
+	if (icbp->icb_rsltqlen < 8) {
+		isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
+		    icbp->icb_rsltqlen);
+		return;
+	}
+	icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
+	icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
+	icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
+	icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
+
+	icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
+	icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
+	icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
+	icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
+
+#ifdef	ISP_TARGET_MODE
+	if (isp->isp_role & ISP_ROLE_TARGET) {
+		icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp);
+		if (icbp->icb_atioqlen < 8) {
+			isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d",
+			    icbp->icb_atioqlen);
+			return;
+		}
+		icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
+		icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
+		icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
+		icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
+		isp_prt(isp, ISP_LOGDEBUG0,
+		    "isp_fibre_init_2400: atioq %04x%04x%04x%04x",
+		    DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
+		    DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
+	}
+#endif
+
+	isp_prt(isp, ISP_LOGDEBUG0,
+	    "isp_fibre_init_2400: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
+	    icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3);
+
+	isp_prt(isp, ISP_LOGDEBUG0,
+	    "isp_fibre_init_2400: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x",
+	    DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma),
+	    DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma),
+	    DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
+	    DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
+
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "isp_fibre_init_2400", sizeof (*icbp),
+		    icbp);
+	}
+	FC_SCRATCH_ACQUIRE(isp);
+	isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
+
+
+	/*
+	 * Init the firmware
+	 */
+	MEMZERO(&mbs, sizeof (mbs));
+	mbs.param[0] = MBOX_INIT_FIRMWARE;
+	mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+	mbs.logval = MBLOGALL;
+	mbs.timeout = 30 * 1000000;
+	isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x",
+	    DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma),
+	    DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma));
+	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp));
+	isp_mboxcmd(isp, &mbs);
+	FC_SCRATCH_RELEASE(isp);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		return;
+	}
+	isp->isp_reqidx = 0;
+	isp->isp_reqodx = 0;
 	isp->isp_residx = 0;
-	isp->isp_sendmarker = 1;
 
 	/*
 	 * Whatever happens, we're now committed to being here.
@@ -1509,57 +2049,306 @@ isp_fibre_init(ispsoftc_t *isp)
 
 /*
  * Fibre Channel Support- get the port database for the id.
- *
- * Locks are held before coming here. Return 0 if success,
- * else failure.
  */
-
-static int
-isp_getmap(ispsoftc_t *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[2] = DMA_WD1(fcp->isp_scdma);
-	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-	FC_SCRATCH_ACQUIRE(isp);
-	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (fcpos_map_t));
-	isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
-	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
-		MEMCPY(map, fcp->isp_scratch, sizeof (fcpos_map_t));
-		map->fwmap = mbs.param[1] != 0;
-		FC_SCRATCH_RELEASE(isp);
-		return (0);
-	}
-	FC_SCRATCH_RELEASE(isp);
-	return (-1);
-}
-
 static void
-isp_mark_getpdb_all(ispsoftc_t *isp)
+isp_dump_portdb(ispsoftc_t *isp)
 {
 	fcparam *fcp = (fcparam *) isp->isp_param;
 	int i;
+
 	for (i = 0; i < MAX_FC_TARG; i++) {
-		fcp->portdb[i].valid = fcp->portdb[i].fabric_dev = 0;
+		char mb[4];
+		const char *dbs[8] = {
+			"NIL ",
+			"PROB",
+			"DEAD",
+			"CHGD",
+			"NEW ",
+			"PVLD",
+			"????",
+			"VLD "
+		};
+		const char *roles[4] = {
+			" UNK", " TGT", " INI", "TINI"
+		};
+		fcportdb_t *lp = &fcp->portdb[i];
+
+		if (lp->state == FC_PORTDB_STATE_NIL) {
+			continue;
+		}
+		if (lp->ini_map_idx) {
+			SNPRINTF(mb, sizeof (mb), "%3d",
+			    ((int) lp->ini_map_idx) - 1);
+		} else {
+			SNPRINTF(mb, sizeof (mb), "---");
+		}
+		isp_prt(isp, ISP_LOGALL, "%d: %s al%d tgt %s %s 0x%06x =>%s"
+		    " 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x", i,
+		    dbs[lp->state], lp->autologin, mb,
+		    roles[lp->roles], lp->portid,
+		    roles[lp->new_roles], lp->new_portid,
+		    (uint32_t) (lp->node_wwn >> 32),
+		    (uint32_t) (lp->node_wwn),
+		    (uint32_t) (lp->port_wwn >> 32),
+		    (uint32_t) (lp->port_wwn));
+	}
+}
+
+static void
+isp_mark_portdb(ispsoftc_t *isp, int onprobation)
+{
+	fcparam *fcp = (fcparam *) isp->isp_param;
+	int i;
+
+	for (i = 0; i < MAX_FC_TARG; i++) {
+		fcp->isp_ini_map[i] = 0;
+		if (onprobation == 0) {
+			MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
+		} else {
+			switch (fcp->portdb[i].state) {
+			case FC_PORTDB_STATE_CHANGED:
+			case FC_PORTDB_STATE_PENDING_VALID:
+			case FC_PORTDB_STATE_VALID:
+			case FC_PORTDB_STATE_PROBATIONAL:
+				fcp->portdb[i].state =
+					FC_PORTDB_STATE_PROBATIONAL;
+				break;
+			case FC_PORTDB_STATE_NIL:
+			default:
+				MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
+				fcp->portdb[i].state =
+					FC_PORTDB_STATE_NIL;
+				break;
+			}
+		}
+	}
+}
+
+/*
+ * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
+ */
+static void
+isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret)
+{
+	mbreg_t mbs;
+	uint8_t q[QENTRY_LEN];
+	isp_plogx_t *plp = (isp_plogx_t *) q;
+	uint8_t *scp = FCPARAM(isp)->isp_scratch;
+	uint32_t sst, parm1;
+	int junk;
+
+	MEMZERO(q, QENTRY_LEN);
+	plp->plogx_header.rqs_entry_count = 1;
+	plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
+	plp->plogx_handle = 0xffffffff;
+	plp->plogx_nphdl = handle;
+	plp->plogx_portlo = portid;
+	plp->plogx_rspsz_porthi = (portid >> 16) & 0xff;
+	if (log_ret) {
+		plp->plogx_flags = *log_ret;
+	} else {
+		log_ret = &junk;
+	}
+
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, plp);
+	}
+	/*
+	 * XXX: We're going to assume somebody has acquired SCRATCH for us
+	 */
+	isp_put_plogx(isp, plp, (isp_plogx_t *) scp);
+
+
+	MEMZERO(&mbs, sizeof (mbs));
+	mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64;
+	mbs.param[1] = QENTRY_LEN;
+	mbs.param[2] = DMA_WD1(FCPARAM(isp)->isp_scdma);
+	mbs.param[3] = DMA_WD0(FCPARAM(isp)->isp_scdma);
+	mbs.param[6] = DMA_WD3(FCPARAM(isp)->isp_scdma);
+	mbs.param[7] = DMA_WD2(FCPARAM(isp)->isp_scdma);
+	mbs.logval = MBLOGALL;
+	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN);
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		*log_ret = mbs.param[0];
+	}
+	MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN);
+	scp += QENTRY_LEN;
+	isp_get_plogx(isp, (isp_plogx_t *) scp, plp);
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, plp);
+	}
+
+	if (plp->plogx_status == PLOGX_STATUS_OK) {
+		*log_ret = 0;
+		return;
+	} else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) {
+		isp_prt(isp, ISP_LOGWARN, "status 0x%x on port login IOCB",
+		    plp->plogx_status);
+		*log_ret = -1;
+		return;
+	}
+
+	sst = plp->plogx_ioparm[0].lo16 | (plp->plogx_ioparm[0].hi16 << 16);
+	parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16);
+
+	*log_ret = -1;
+
+	switch (sst) {
+	case PLOGX_IOCBERR_NOLINK:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed- no link");
+		break;
+	case PLOGX_IOCBERR_NOIOCB:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed- no IOCB buffer");
+		break;
+	case PLOGX_IOCBERR_NOXGHG:
+		isp_prt(isp, ISP_LOGERR,
+		    "PLOGX failed- no Exchange Control Block");
+		break;
+	case PLOGX_IOCBERR_FAILED:
+		isp_prt(isp, ISP_LOGERR,
+		    "PLOGX(0x%x) of Port 0x%06x failed: reason 0x%x (last LOGIN"
+		    " state 0x%x)", *log_ret, portid,
+		    parm1 & 0xff, (parm1 >> 8) & 0xff);
+		break;
+	case PLOGX_IOCBERR_NOFABRIC:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed- no fabric");
+		break;
+	case PLOGX_IOCBERR_NOTREADY:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed- f/w not ready");
+		break;
+	case PLOGX_IOCBERR_NOLOGIN:
+		isp_prt(isp, ISP_LOGERR,
+		    "PLOGX failed- not logged in (last LOGIN state 0x%x)",
+		    parm1);
+		*log_ret = MBOX_NOT_LOGGED_IN;
+		break;
+	case PLOGX_IOCBERR_REJECT:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed: LS_RJT = 0x%x", parm1);
+		break;
+	case PLOGX_IOCBERR_NOPCB:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed- no PCB allocated");
+		break;
+	case PLOGX_IOCBERR_EINVAL:
+		isp_prt(isp, ISP_LOGERR,
+		    "PLOGX failed: invalid parameter at offset 0x%x", parm1);
+		break;
+	case PLOGX_IOCBERR_PORTUSED:
+		isp_prt(isp, ISP_LOGDEBUG0,
+		    "portid 0x%x already logged in with N-port handle 0x%x",
+		    portid, parm1);
+		*log_ret = MBOX_PORT_ID_USED | (handle << 16);
+		break;
+	case PLOGX_IOCBERR_HNDLUSED:
+		isp_prt(isp, ISP_LOGDEBUG0,
+		    "N-port handle 0x%x already used for portid 0x%x",
+		    handle, parm1);
+		*log_ret = MBOX_LOOP_ID_USED;
+		break;
+	case PLOGX_IOCBERR_NOHANDLE:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed- no handle allocated");
+		break;
+	case PLOGX_IOCBERR_NOFLOGI:
+		isp_prt(isp, ISP_LOGERR, "PLOGX failed- no FLOGI_ACC");
+		break;
+	default:
+		isp_prt(isp, ISP_LOGERR, "status %x from %s", plp->plogx_status,
+		    (*log_ret)? "PLOGI" : "LOGO");
+		*log_ret = -1;
+		break;
 	}
 }
 
 static int
-isp_getpdb(ispsoftc_t *isp, int id, isp_pdb_t *pdbp)
+isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
 {
-	fcparam *fcp = (fcparam *) isp->isp_param;
 	mbreg_t mbs;
 
+	MEMZERO(&mbs, sizeof (mbs));
+	mbs.param[0] = MBOX_FABRIC_LOGIN;
+	if (FCPARAM(isp)->isp_2klogin) {
+		mbs.param[1] = handle;
+		mbs.ibits = (1 << 10);
+	} else {
+		mbs.param[1] = handle << 8;
+	}
+	mbs.param[2] = portid >> 16;
+	mbs.param[3] = portid;
+
+	mbs.logval = MBLOGNONE;
+	isp_mboxcmd(isp, &mbs);
+
+	switch (mbs.param[0]) {
+	case MBOX_PORT_ID_USED:
+		isp_prt(isp, ISP_LOGDEBUG0,
+		    "isp_port_login: portid 0x%06x already logged in as %u",
+		    portid, mbs.param[1]);
+		return (MBOX_PORT_ID_USED | (mbs.param[1] << 16));
+		break;
+
+	case MBOX_LOOP_ID_USED:
+		isp_prt(isp, ISP_LOGDEBUG0,
+		    "isp_port_login: handle %u in use for port id 0x%02xXXXX",
+		    handle, mbs.param[1] & 0xff);
+		return (MBOX_LOOP_ID_USED);
+
+	case MBOX_COMMAND_COMPLETE:
+		return (0);
+
+	case MBOX_COMMAND_ERROR:
+		isp_prt(isp, ISP_LOGINFO,
+		    "isp_port_login: error 0x%x in PLOGI to port 0x%06x",
+		    mbs.param[1], portid);
+		return (MBOX_COMMAND_ERROR);
+
+	case MBOX_ALL_IDS_USED:
+		isp_prt(isp, ISP_LOGINFO,
+		    "isp_port_login: all IDs used for fabric login");
+		return (MBOX_ALL_IDS_USED);
+
+	default:
+		isp_prt(isp, ISP_LOGINFO,
+		    "isp_port_login: error 0x%x on port login of 0x%06x@0x%0x",
+		    mbs.param[0], portid, handle);
+		return (mbs.param[0]);
+	}
+}
+
+static void
+isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
+{
+	mbreg_t mbs;
+
+	MEMZERO(&mbs, sizeof (mbs));
+	mbs.param[0] = MBOX_FABRIC_LOGOUT;
+	if (FCPARAM(isp)->isp_2klogin) {
+		mbs.param[1] = handle;
+		mbs.ibits = (1 << 10);
+	} else {
+		mbs.param[1] = handle << 8;
+	}
+	mbs.logval = MBLOGNONE;
+	isp_mboxcmd(isp, &mbs);
+}
+
+static int
+isp_getpdb(ispsoftc_t *isp, uint16_t id, isp_pdb_t *pdb, int dolock)
+{
+	fcparam *fcp = (fcparam *) isp->isp_param;
+	mbreg_t mbs;
+	union {
+		isp_pdb_21xx_t fred;
+		isp_pdb_24xx_t bill;
+	} un;
+
 	MEMZERO(&mbs, sizeof (mbs));
 	mbs.param[0] = MBOX_GET_PORT_DB;
-	if (IS_2KLOGIN(isp)) {
+	if (IS_24XX(isp)) {
+		mbs.ibits = 0x3ff;
 		mbs.param[1] = id;
-		mbs.ibits |= (1 << 10);
+	} else if (FCPARAM(isp)->isp_2klogin) {
+		mbs.param[1] = id;
+		mbs.ibits = (1 << 10);
 	} else {
 		mbs.param[1] = id << 8;
 	}
@@ -1567,29 +2356,50 @@ isp_getpdb(ispsoftc_t *isp, int id, isp_pdb_t *pdbp)
 	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
 	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
 	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-	FC_SCRATCH_ACQUIRE(isp);
-	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (isp_pdb_t));
-	isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
-	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
-		isp_get_pdb(isp, (isp_pdb_t *)fcp->isp_scratch, pdbp);
-		FC_SCRATCH_RELEASE(isp);
-		return (0);
+	mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR;
+	if (dolock) {
+		FC_SCRATCH_ACQUIRE(isp);
 	}
-	FC_SCRATCH_RELEASE(isp);
-	return (-1);
+	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (un));
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		if (dolock) {
+			FC_SCRATCH_RELEASE(isp);
+		}
+		return (-1);
+	}
+	if (IS_24XX(isp)) {
+		isp_get_pdb_24xx(isp, fcp->isp_scratch, &un.bill);
+		pdb->handle = un.bill.pdb_handle;
+		pdb->s3_role = un.bill.pdb_prli_svc3;
+		pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
+		MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
+		MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
+	} else {
+		isp_get_pdb_21xx(isp, fcp->isp_scratch, &un.fred);
+		pdb->handle = un.fred.pdb_loopid;
+		pdb->s3_role = un.fred.pdb_prli_svc3;
+		pdb->portid = BITS2WORD(un.fred.pdb_portid_bits);
+		MEMCPY(pdb->portname, un.fred.pdb_portname, 8);
+		MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8);
+	}
+	if (dolock) {
+		FC_SCRATCH_RELEASE(isp);
+	}
+	return (0);
 }
 
 static uint64_t
 isp_get_portname(ispsoftc_t *isp, int loopid, int nodename)
 {
-	uint64_t wwn = 0;
+	uint64_t wwn = (uint64_t) -1;
 	mbreg_t mbs;
 
 	MEMZERO(&mbs, sizeof (mbs));
 	mbs.param[0] = MBOX_GET_PORT_NAME;
-	if (IS_2KLOGIN(isp)) {
+	if (FCPARAM(isp)->isp_2klogin || IS_24XX(isp)) {
 		mbs.param[1] = loopid;
-		mbs.ibits |= (1 << 10);
+		mbs.ibits = (1 << 10);
 		if (nodename) {
 			mbs.param[10] = 1;
 		}
@@ -1599,8 +2409,23 @@ isp_get_portname(ispsoftc_t *isp, int loopid, int nodename)
 			mbs.param[1] |= 1;
 		}
 	}
-	isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
-	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
+	mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR;
+	mbs.timeout = 30000;
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		return (wwn);
+	}
+	if (IS_24XX(isp)) {
+		wwn =
+		    (((uint64_t)(mbs.param[2] >> 8))  << 56) |
+		    (((uint64_t)(mbs.param[2] & 0xff))	<< 48) |
+		    (((uint64_t)(mbs.param[3] >> 8))	<< 40) |
+		    (((uint64_t)(mbs.param[3] & 0xff))	<< 32) |
+		    (((uint64_t)(mbs.param[6] >> 8))	<< 24) |
+		    (((uint64_t)(mbs.param[6] & 0xff))	<< 16) |
+		    (((uint64_t)(mbs.param[7] >> 8))	<<  8) |
+		    (((uint64_t)(mbs.param[7] & 0xff)));
+	} else {
 		wwn =
 		    (((uint64_t)(mbs.param[2] & 0xff))  << 56) |
 		    (((uint64_t)(mbs.param[2] >> 8))	<< 48) |
@@ -1615,13 +2440,13 @@ isp_get_portname(ispsoftc_t *isp, int loopid, int nodename)
 }
 
 /*
- * Make sure we have good FC link and know our Loop ID.
+ * Make sure we have good FC link.
  */
 
 static int
 isp_fclink_test(ispsoftc_t *isp, int usdelay)
 {
-	static char *toponames[] = {
+	static const char *toponames[] = {
 		"Private Loop",
 		"FL Port",
 		"N-Port to N-Port",
@@ -1631,17 +2456,15 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
 	mbreg_t mbs;
 	int count, check_for_fabric;
 	uint8_t lwfs;
+	int loopid;
 	fcparam *fcp;
-	struct lportdb *lp;
+	fcportdb_t *lp;
 	isp_pdb_t pdb;
 
 	fcp = isp->isp_param;
 
 	isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Entry");
-
-	/*
-	 * XXX: Here is where we would start a 'loop dead' timeout
-	 */
+	isp_mark_portdb(isp, 1);
 
 	/*
 	 * Wait up to N microseconds for F/W to go to a ready state.
@@ -1710,49 +2533,38 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
 	 * If we haven't gone to 'ready' state, return.
 	 */
 	if (fcp->isp_fwstate != FW_READY) {
+		isp_prt(isp, ISP_LOGDEBUG0,
+		    "isp_fclink_test: not at FW_READY state");
 		return (-1);
 	}
 
 	/*
-	 * Get our Loop ID (if possible). We really need to have it.
+	 * Get our Loop ID and Port ID.
 	 */
 	MEMZERO(&mbs, sizeof (mbs));
 	mbs.param[0] = MBOX_GET_LOOP_ID;
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	mbs.logval = MBLOGALL;
+	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return (-1);
 	}
-	if (IS_2KLOGIN(isp)) {
+
+	if (FCPARAM(isp)->isp_2klogin) {
 		fcp->isp_loopid = mbs.param[1];
 	} else {
 		fcp->isp_loopid = mbs.param[1] & 0xff;
 	}
-	if (fcp->isp_loopid == 0xffff) {	/* happens with 2k login f/w */
-		fcp->isp_loopid = MAX_FC_TARG-1;
-	} else if (fcp->isp_loopid >= MAX_FC_TARG) {
-		isp_prt(isp, ISP_LOGWARN, "bad initiator loopid (0x%x)", fcp->isp_loopid);
-		fcp->isp_loopid = MAX_FC_TARG-1;
-	}
-	if (IS_2200(isp) || IS_23XX(isp)) {
-		int topo = (int) mbs.param[6];
-		if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
-			topo = TOPO_PTP_STUB;
-		fcp->isp_topo = topo;
-	} else {
-		fcp->isp_topo = TOPO_NL_PORT;
-	}
-	/*
-	 * Get the port id.
-	 */
-	fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
 
-	/*
-	 * Check to see if we're on a fabric by trying to see if we
-	 * can talk to the fabric name server. This can be a bit
-	 * tricky because if we're a 2100, we should check always
-	 * (in case we're connected to a server doing aliasing).
-	 */
-	fcp->isp_onfabric = 0;
+	if (IS_2100(isp)) {
+		fcp->isp_topo = TOPO_NL_PORT;
+	} else {
+		int topo = (int) mbs.param[6];
+		if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) {
+			topo = TOPO_PTP_STUB;
+		}
+		fcp->isp_topo = topo;
+	}
+	fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
 
 	if (IS_2100(isp)) {
 		/*
@@ -1767,117 +2579,79 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
 	} else if (fcp->isp_topo == TOPO_FL_PORT ||
 	    fcp->isp_topo == TOPO_F_PORT) {
 		check_for_fabric = 1;
-	} else
+	} else {
 		check_for_fabric = 0;
+	}
 
-	if (check_for_fabric && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) {
-		int loopid = FL_PORT_ID;
+	if (IS_24XX(isp)) {
+		loopid = NPH_FL_ID;
+	} else {
+		loopid = FL_ID;
+	}
+
+	if (check_for_fabric && isp_getpdb(isp, loopid, &pdb, 1) == 0) {
 		if (IS_2100(isp)) {
 			fcp->isp_topo = TOPO_FL_PORT;
 		}
-
-		if (BITS2WORD(pdb.pdb_portid_bits) == 0) {
+		if (pdb.portid == 0) {
 			/*
 			 * Crock.
 			 */
 			fcp->isp_topo = TOPO_NL_PORT;
 			goto not_on_fabric;
 		}
-		fcp->isp_portid = mbs.param[2] | ((int) mbs.param[3] << 16);
 
 		/*
 		 * Save the Fabric controller's port database entry.
 		 */
-		lp = &fcp->portdb[loopid];
-		lp->node_wwn =
-		    (((uint64_t)pdb.pdb_nodename[0]) << 56) |
-		    (((uint64_t)pdb.pdb_nodename[1]) << 48) |
-		    (((uint64_t)pdb.pdb_nodename[2]) << 40) |
-		    (((uint64_t)pdb.pdb_nodename[3]) << 32) |
-		    (((uint64_t)pdb.pdb_nodename[4]) << 24) |
-		    (((uint64_t)pdb.pdb_nodename[5]) << 16) |
-		    (((uint64_t)pdb.pdb_nodename[6]) <<  8) |
-		    (((uint64_t)pdb.pdb_nodename[7]));
-		lp->port_wwn =
-		    (((uint64_t)pdb.pdb_portname[0]) << 56) |
-		    (((uint64_t)pdb.pdb_portname[1]) << 48) |
-		    (((uint64_t)pdb.pdb_portname[2]) << 40) |
-		    (((uint64_t)pdb.pdb_portname[3]) << 32) |
-		    (((uint64_t)pdb.pdb_portname[4]) << 24) |
-		    (((uint64_t)pdb.pdb_portname[5]) << 16) |
-		    (((uint64_t)pdb.pdb_portname[6]) <<  8) |
-		    (((uint64_t)pdb.pdb_portname[7]));
-		lp->roles =
-		    (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
-		lp->portid = BITS2WORD(pdb.pdb_portid_bits);
-		lp->loopid = pdb.pdb_loopid;
-		lp->loggedin = lp->valid = 1;
-		fcp->isp_onfabric = 1;
-		(void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
-		isp_register_fc4_type(isp);
+		lp = &fcp->portdb[FL_ID];
+		lp->state = FC_PORTDB_STATE_PENDING_VALID;
+		MAKE_WWN_FROM_NODE_NAME(lp->node_wwn, pdb.nodename);
+		MAKE_WWN_FROM_NODE_NAME(lp->port_wwn, pdb.portname);
+		lp->roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
+		lp->portid = pdb.portid;
+		lp->handle = pdb.handle;
+		lp->new_portid = lp->portid;
+		lp->new_roles = lp->roles;
+		if (IS_24XX(isp)) {
+			(void) isp_register_fc4_type_24xx(isp);
+		} else {
+			(void) isp_register_fc4_type(isp);
+		}
 	} else {
 not_on_fabric:
-		fcp->isp_onfabric = 0;
-		fcp->portdb[FL_PORT_ID].valid = 0;
+		fcp->portdb[FL_ID].state = FC_PORTDB_STATE_NIL;
 	}
 
 	fcp->isp_gbspeed = 1;
-	if (IS_23XX(isp)) {
+	if (IS_23XX(isp) || IS_24XX(isp)) {
 		MEMZERO(&mbs, sizeof (mbs));
 		mbs.param[0] = MBOX_GET_SET_DATA_RATE;
 		mbs.param[1] = MBGSD_GET_RATE;
 		/* mbs.param[2] undefined if we're just getting rate */
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
-			if (mbs.param[1] == MBGSD_TWOGB) {
+			if (mbs.param[1] == MBGSD_FOURGB) {
+				isp_prt(isp, ISP_LOGINFO, "4Gb link speed/s");
+				fcp->isp_gbspeed = 4;
+			} if (mbs.param[1] == MBGSD_TWOGB) {
 				isp_prt(isp, ISP_LOGINFO, "2Gb link speed/s");
 				fcp->isp_gbspeed = 2;
 			}
 		}
 	}
 
-	isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid,
-	    fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]);
-
 	/*
-	 * Announce ourselves, too. This involves synthesizing an entry.
+	 * Announce ourselves, too.
 	 */
-	if (fcp->isp_iid_set == 0) {
-		fcp->isp_iid_set = 1;
-		fcp->isp_iid = fcp->isp_loopid;
-		lp = &fcp->portdb[fcp->isp_iid];
-	} else {
-		lp = &fcp->portdb[fcp->isp_iid];
-		if (fcp->isp_portid != lp->portid ||
-		    fcp->isp_loopid != lp->loopid ||
-		    fcp->isp_nodewwn != ISP_NODEWWN(isp) ||
-		    fcp->isp_portwwn != ISP_PORTWWN(isp)) {
-			lp->valid = 0;
-			count = fcp->isp_iid;
-			(void) isp_async(isp, ISPASYNC_PROMENADE, &count);
-		}
-	}
-	lp->loopid = fcp->isp_loopid;
-	lp->portid = fcp->isp_portid;
-	lp->node_wwn = ISP_NODEWWN(isp);
-	lp->port_wwn = ISP_PORTWWN(isp);
-	switch (isp->isp_role) {
-	case ISP_ROLE_NONE:
-		lp->roles = 0;
-		break;
-	case ISP_ROLE_TARGET:
-		lp->roles = SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT;
-		break;
-	case ISP_ROLE_INITIATOR:
-		lp->roles = SVC3_INI_ROLE >> SVC3_ROLE_SHIFT;
-		break;
-	case ISP_ROLE_BOTH:
-		lp->roles = (SVC3_INI_ROLE|SVC3_TGT_ROLE) >> SVC3_ROLE_SHIFT;
-		break;
-	}
-	lp->loggedin = lp->valid = 1;
-	count = fcp->isp_iid;
-	(void) isp_async(isp, ISPASYNC_PROMENADE, &count);
+	isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_portid,
+	    fcp->isp_loopid, toponames[fcp->isp_topo]);
+	isp_prt(isp, ISP_LOGCONFIG, ourwwn,
+	    (uint32_t) (ISP_NODEWWN(isp) >> 32),
+	    (uint32_t) ISP_NODEWWN(isp),
+	    (uint32_t) (ISP_PORTWWN(isp) >> 32),
+	    (uint32_t) ISP_PORTWWN(isp));
 	isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Complete");
 	return (0);
 }
@@ -1899,17 +2673,35 @@ isp2100_fw_statename(int state)
 }
 
 /*
- * Synchronize our soft copy of the port database with what the f/w thinks
- * (with a view toward possibly for a specific target....)
+ * Complete the synchronization of our Port Database.
+ *
+ * At this point, we've scanned the local loop (if any) and the fabric
+ * and performed fabric logins on all new devices.
+ *
+ * Our task here is to go through our port database and remove any entities
+ * that are still marked probational (issuing PLOGO for ones which we had
+ * PLOGI'd into) or are dead.
+ *
+ * Our task here is to also check policy to decide whether devices which
+ * have *changed* in some way should still be kept active. For example,
+ * if a device has just changed PortID, we can either elect to treat it
+ * as an old device or as a newly arrived device (and notify the outer
+ * layer appropriately).
+ *
+ * We also do initiator map target id assignment here for new initiator
+ * devices and refresh old ones ot make sure that they point to the corret
+ * entities.
  */
-
 static int
 isp_pdb_sync(ispsoftc_t *isp)
 {
-	struct lportdb *lp;
 	fcparam *fcp = isp->isp_param;
-	isp_pdb_t pdb;
-	int loopid, base, lim;
+	fcportdb_t *lp;
+	uint16_t dbidx;
+
+	if (fcp->isp_loopstate == LOOP_READY) {
+		return (0);
+	}
 
 	/*
 	 * Make sure we're okay for doing this right now.
@@ -1917,306 +2709,146 @@ isp_pdb_sync(ispsoftc_t *isp)
 	if (fcp->isp_loopstate != LOOP_PDB_RCVD &&
 	    fcp->isp_loopstate != LOOP_FSCAN_DONE &&
 	    fcp->isp_loopstate != LOOP_LSCAN_DONE) {
+		isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d",
+		    fcp->isp_loopstate);
 		return (-1);
 	}
 
-	if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT ||
+	if (fcp->isp_topo == TOPO_FL_PORT ||
+	    fcp->isp_topo == TOPO_NL_PORT ||
 	    fcp->isp_topo == TOPO_N_PORT) {
 		if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
 			if (isp_scan_loop(isp) != 0) {
+				isp_prt(isp, ISP_LOGWARN,
+				    "isp_pdb_sync: isp_scan_loop failed");
 				return (-1);
 			}
 		}
 	}
+
+	if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
+		if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
+			if (isp_scan_fabric(isp) != 0) {
+				isp_prt(isp, ISP_LOGWARN,
+				    "isp_pdb_sync: isp_scan_fabric failed");
+				return (-1);
+			}
+		}
+	}
+
 	fcp->isp_loopstate = LOOP_SYNCING_PDB;
 
-	/*
-	 * If we get this far, we've settled our differences with the f/w
-	 * (for local loop device) and we can say that the loop state is ready.
-	 */
+	for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+		lp = &fcp->portdb[dbidx];
 
-	if (fcp->isp_topo == TOPO_NL_PORT) {
-		fcp->loop_seen_once = 1;
-		fcp->isp_loopstate = LOOP_READY;
-		return (0);
-	}
-
-	/*
-	 * Find all Fabric Entities that didn't make it from one scan to the
-	 * next and let the world know they went away. Scan the whole database.
-	 */
-	for (lp = &fcp->portdb[0]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
-		if (lp->was_fabric_dev && lp->fabric_dev == 0) {
-			loopid = lp - fcp->portdb;
-			lp->valid = 0;	/* should already be set */
-			(void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
-			MEMZERO((void *) lp, sizeof (*lp));
-			continue;
-		}
-		lp->was_fabric_dev = lp->fabric_dev;
-	}
-
-	if (fcp->isp_topo == TOPO_FL_PORT)
-		base = FC_SNS_ID+1;
-	else
-		base = 0;
-
-	if (fcp->isp_topo == TOPO_N_PORT)
-		lim = 1;
-	else
-		lim = MAX_FC_TARG;
-
-	/*
-	 * Now log in any fabric devices that the outer layer has
-	 * left for us to see. This seems the most sane policy
-	 * for the moment.
-	 */
-	for (lp = &fcp->portdb[base]; lp < &fcp->portdb[lim]; lp++) {
-		uint32_t portid;
-		mbreg_t mbs;
-
-		loopid = lp - fcp->portdb;
-		if (loopid >= FL_PORT_ID && loopid <= FC_SNS_ID) {
+		if (lp->state == FC_PORTDB_STATE_NIL) {
 			continue;
 		}
 
-		/*
-		 * Anything here?
-		 */
-		if (lp->port_wwn == 0) {
-			continue;
-		}
-
-		/*
-		 * Don't try to log into yourself.
-		 */
-		if ((portid = lp->portid) == fcp->isp_portid) {
-			continue;
-		}
-
-
-		/*
-		 * If we'd been logged in- see if we still are and we haven't
-		 * changed. If so, no need to log ourselves out, etc..
-		 *
-		 * Unfortunately, our charming Qlogic f/w has decided to
-		 * return a valid port database entry for a fabric device
-		 * that has, in fact, gone away. And it hangs trying to
-		 * log it out.
-		 */
-		if (lp->loggedin && lp->force_logout == 0 &&
-		    isp_getpdb(isp, lp->loopid, &pdb) == 0) {
-			int nrole;
-			uint64_t nwwnn, nwwpn;
-			nwwnn =
-			    (((uint64_t)pdb.pdb_nodename[0]) << 56) |
-			    (((uint64_t)pdb.pdb_nodename[1]) << 48) |
-			    (((uint64_t)pdb.pdb_nodename[2]) << 40) |
-			    (((uint64_t)pdb.pdb_nodename[3]) << 32) |
-			    (((uint64_t)pdb.pdb_nodename[4]) << 24) |
-			    (((uint64_t)pdb.pdb_nodename[5]) << 16) |
-			    (((uint64_t)pdb.pdb_nodename[6]) <<  8) |
-			    (((uint64_t)pdb.pdb_nodename[7]));
-			nwwpn =
-			    (((uint64_t)pdb.pdb_portname[0]) << 56) |
-			    (((uint64_t)pdb.pdb_portname[1]) << 48) |
-			    (((uint64_t)pdb.pdb_portname[2]) << 40) |
-			    (((uint64_t)pdb.pdb_portname[3]) << 32) |
-			    (((uint64_t)pdb.pdb_portname[4]) << 24) |
-			    (((uint64_t)pdb.pdb_portname[5]) << 16) |
-			    (((uint64_t)pdb.pdb_portname[6]) <<  8) |
-			    (((uint64_t)pdb.pdb_portname[7]));
-			nrole = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >>
-			    SVC3_ROLE_SHIFT;
-			if (pdb.pdb_loopid == lp->loopid && lp->portid ==
-			    (uint32_t) BITS2WORD(pdb.pdb_portid_bits) &&
-			    nwwnn == lp->node_wwn && nwwpn == lp->port_wwn &&
-			    lp->roles == nrole && lp->force_logout == 0) {
-				lp->loggedin = lp->valid = 1;
-				isp_prt(isp, ISP_LOGCONFIG, lretained,
-				    (int) (lp - fcp->portdb),
-				    (int) lp->loopid, lp->portid);
-				continue;
+		if (lp->state == FC_PORTDB_STATE_VALID) {
+			if (dbidx != FL_ID) {
+				isp_prt(isp,
+				    ISP_LOGERR, "portdb idx %d already valid",
+			    	    dbidx);
 			}
+			continue;
 		}
 
-		if (fcp->isp_fwstate != FW_READY ||
-		    fcp->isp_loopstate != LOOP_SYNCING_PDB) {
-			return (-1);
-		}
-
-		/*
-		 * Force a logout if we were logged in.
-		 */
-		if (lp->loggedin) {
-			if (lp->force_logout ||
-			    isp_getpdb(isp, lp->loopid, &pdb) == 0) {
-				MEMZERO(&mbs, sizeof (mbs));
-				mbs.param[0] = MBOX_FABRIC_LOGOUT;
-				if (IS_2KLOGIN(isp)) {
-					mbs.param[1] = lp->loopid;
-					mbs.ibits |= (1 << 10);
+		switch (lp->state) {
+		case FC_PORTDB_STATE_PROBATIONAL:
+		case FC_PORTDB_STATE_DEAD:
+			isp_async(isp, ISPASYNC_DEV_GONE, lp);
+			if (lp->ini_map_idx) {
+				fcp->isp_ini_map[lp->ini_map_idx-1] = 0;
+				lp->ini_map_idx = 0;
+			}
+			lp->state = FC_PORTDB_STATE_NIL;
+			if (lp->autologin == 0) {
+				if (IS_24XX(isp)) {
+					int action =
+					    PLOGX_FLG_CMD_LOGO |
+					    PLOGX_FLG_IMPLICIT |
+					    PLOGX_FLG_FREE_NPHDL;
+					FC_SCRATCH_ACQUIRE(isp);
+					isp_plogx_24xx(isp, lp->handle,
+					    lp->portid, &action);
+					FC_SCRATCH_RELEASE(isp);
 				} else {
-					mbs.param[1] = lp->loopid << 8;
-				}
-				isp_mboxcmd(isp, &mbs, MBLOGNONE);
-				isp_prt(isp, ISP_LOGINFO, plogout,
-				    (int) (lp - fcp->portdb), lp->loopid,
-				    lp->portid);
-			}
-			lp->force_logout = lp->loggedin = 0;
-			if (fcp->isp_fwstate != FW_READY ||
-			    fcp->isp_loopstate != LOOP_SYNCING_PDB) {
-				return (-1);
-			}
-		}
-
-		/*
-		 * And log in....
-		 */
-		loopid = lp - fcp->portdb;
-		lp->loopid = FL_PORT_ID;
-		do {
-			MEMZERO(&mbs, sizeof (mbs));
-			mbs.param[0] = MBOX_FABRIC_LOGIN;
-			if (IS_2KLOGIN(isp)) {
-				mbs.param[1] = loopid;
-				mbs.ibits |= (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 |
-			    MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR));
-			if (fcp->isp_fwstate != FW_READY ||
-			    fcp->isp_loopstate != LOOP_SYNCING_PDB) {
-				return (-1);
-			}
-			switch (mbs.param[0]) {
-			case MBOX_LOOP_ID_USED:
-				/*
-				 * Try the next available loop id.
-				 */
-				loopid++;
-				break;
-			case MBOX_PORT_ID_USED:
-				/*
-				 * This port is already logged in.
-				 * Snaffle the loop id it's using if it's
-				 * nonzero, otherwise we're hosed.
-				 */
-				if (mbs.param[1] != 0) {
-					loopid = mbs.param[1];
-					if (loopid >= MAX_FC_TARG) {
-						loopid = MAX_FC_TARG;
-						break;
-					}
-					isp_prt(isp, ISP_LOGINFO, retained,
-					    loopid, (int) (lp - fcp->portdb),
+					isp_port_logout(isp, lp->handle,
 					    lp->portid);
-				} else {
-					loopid = MAX_FC_TARG;
-					break;
 				}
-				/* FALLTHROUGH */
-			case MBOX_COMMAND_COMPLETE:
-				lp->loggedin = 1;
-				lp->loopid = loopid;
-				break;
-			case MBOX_COMMAND_ERROR:
-				isp_prt(isp, ISP_LOGINFO, plogierr,
-				    portid, mbs.param[1]);
-				/* FALLTHROUGH */
-			case MBOX_ALL_IDS_USED: /* We're outta IDs */
-			default:
-				loopid = MAX_FC_TARG;
-				break;
+			} else {
+				lp->autologin = 0;
 			}
-		} while (lp->loopid == FL_PORT_ID && loopid < MAX_FC_TARG);
-
-		/*
-		 * If we get here and we haven't set a Loop ID,
-		 * we failed to log into this device.
-		 */
-
-		if (lp->loopid == FL_PORT_ID) {
-			lp->loopid = 0;
-			continue;
-		}
-
-		/*
-		 * Make sure we can get the approriate port information.
-		 */
-		if (isp_getpdb(isp, lp->loopid, &pdb) != 0) {
-			isp_prt(isp, ISP_LOGWARN, nopdb, lp->portid);
-			goto dump_em;
-		}
-
-		if (fcp->isp_fwstate != FW_READY ||
-		    fcp->isp_loopstate != LOOP_SYNCING_PDB) {
-			return (-1);
-		}
-
-		if (pdb.pdb_loopid != lp->loopid) {
-			isp_prt(isp, ISP_LOGWARN, pdbmfail1,
-			    lp->portid, pdb.pdb_loopid);
-			goto dump_em;
-		}
-
-		if (lp->portid != (uint32_t) BITS2WORD(pdb.pdb_portid_bits)) {
-			isp_prt(isp, ISP_LOGWARN, pdbmfail2,
-			    lp->portid, BITS2WORD(pdb.pdb_portid_bits));
-			goto dump_em;
-		}
-
-		lp->roles =
-		    (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
-		lp->node_wwn =
-		    (((uint64_t)pdb.pdb_nodename[0]) << 56) |
-		    (((uint64_t)pdb.pdb_nodename[1]) << 48) |
-		    (((uint64_t)pdb.pdb_nodename[2]) << 40) |
-		    (((uint64_t)pdb.pdb_nodename[3]) << 32) |
-		    (((uint64_t)pdb.pdb_nodename[4]) << 24) |
-		    (((uint64_t)pdb.pdb_nodename[5]) << 16) |
-		    (((uint64_t)pdb.pdb_nodename[6]) <<  8) |
-		    (((uint64_t)pdb.pdb_nodename[7]));
-		lp->port_wwn =
-		    (((uint64_t)pdb.pdb_portname[0]) << 56) |
-		    (((uint64_t)pdb.pdb_portname[1]) << 48) |
-		    (((uint64_t)pdb.pdb_portname[2]) << 40) |
-		    (((uint64_t)pdb.pdb_portname[3]) << 32) |
-		    (((uint64_t)pdb.pdb_portname[4]) << 24) |
-		    (((uint64_t)pdb.pdb_portname[5]) << 16) |
-		    (((uint64_t)pdb.pdb_portname[6]) <<  8) |
-		    (((uint64_t)pdb.pdb_portname[7]));
-		/*
-		 * Check to make sure this all makes sense.
-		 */
-		if (lp->node_wwn && lp->port_wwn) {
-			lp->valid = 1;
-			loopid = lp - fcp->portdb;
-			(void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
-			continue;
-		}
-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;
-		if (IS_2KLOGIN(isp)) {
-			mbs.param[1] = lp->loopid;
-			mbs.ibits |= (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) {
-			return (-1);
+			lp->new_roles = 0;
+			lp->new_portid = 0;
+			break;
+		case FC_PORTDB_STATE_NEW:
+			/*
+			 * If *we* have a new target dole and *it* has a target
+			 * role, assign a new target id to it.
+			 */
+			lp->portid = lp->new_portid;
+			lp->roles = lp->new_roles;
+			lp->state = FC_PORTDB_STATE_VALID;
+			if ((isp->isp_role & ISP_ROLE_INITIATOR) &&
+			    (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
+				int i, t = dbidx;
+				for (i = 0; i < MAX_FC_TARG; i++) {
+					if (i < FL_ID || i > SNS_ID) {
+						if (fcp->isp_ini_map[t] == 0) {
+							break;
+						}
+					}
+					if (++t == MAX_FC_TARG) {
+						t = 0;
+					}
+				}
+				if (i < MAX_FC_TARG) {
+					fcp->isp_ini_map[t] = dbidx + 1;
+					lp->ini_map_idx = t + 1;
+				} else {
+					isp_prt(isp, ISP_LOGWARN,
+					    "out of target ids");
+				}
+			}
+			isp_async(isp, ISPASYNC_DEV_ARRIVED, lp);
+			lp->new_roles = 0;
+			lp->new_portid = 0;
+			break;
+		case FC_PORTDB_STATE_CHANGED:
+			lp->portid = lp->new_portid;
+			lp->roles = lp->new_roles;
+			lp->state = FC_PORTDB_STATE_VALID;
+			if (lp->ini_map_idx) {
+				int t = lp->ini_map_idx - 1;
+				fcp->isp_ini_map[t] = dbidx + 1;
+			}
+			isp_async(isp, ISPASYNC_DEV_CHANGED, lp);
+			lp->new_roles = 0;
+			lp->new_portid = 0;
+			break;
+		case FC_PORTDB_STATE_PENDING_VALID:
+			lp->portid = lp->new_portid;
+			lp->roles = lp->new_roles;
+			lp->state = FC_PORTDB_STATE_VALID;
+			if (lp->ini_map_idx) {
+				int t = lp->ini_map_idx - 1;
+				fcp->isp_ini_map[t] = dbidx + 1;
+			}
+			isp_async(isp, ISPASYNC_DEV_STAYED, lp);
+			if (dbidx != FL_ID) {
+				lp->new_roles = 0;
+				lp->new_portid = 0;
+			}
+			break;
+		default:
+			isp_prt(isp, ISP_LOGERR, "eh? state %d for idx %d",
+			    lp->state, dbidx);
+			isp_dump_portdb(isp);
 		}
 	}
+
 	/*
 	 * If we get here, we've for sure seen not only a valid loop
 	 * but know what is or isn't on it, so mark this for usage
@@ -2227,807 +2859,912 @@ isp_pdb_sync(ispsoftc_t *isp)
 	return (0);
 }
 
+/*
+ * Scan local loop for devices.
+ */
 static int
 isp_scan_loop(ispsoftc_t *isp)
 {
-	struct lportdb *lp;
+	fcportdb_t *lp, tmp;
 	fcparam *fcp = isp->isp_param;
+	int i;
 	isp_pdb_t pdb;
-	int loopid, lim, hival;
+	uint16_t dbidx, lim = 0;
 
+	if (fcp->isp_fwstate < FW_READY ||
+	    fcp->isp_loopstate < LOOP_PDB_RCVD) {
+		return (-1);
+	}
+
+	if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
+		return (0);
+	}
+
+	/*
+	 * Check our connection topology.
+	 *
+	 * If we're a public or private loop, we scan 0..125 as handle values.
+	 * The firmware has (typically) peformed a PLOGI for us.
+	 *
+	 * If we're a N-port connection, we treat this is a short loop (0..1).
+	 *
+	 * If we're in target mode, we can all possible handles to see who
+	 * might have logged into us.
+	 */
 	switch (fcp->isp_topo) {
 	case TOPO_NL_PORT:
-		hival = FL_PORT_ID;
+	case TOPO_FL_PORT:
+		lim = LOCAL_LOOP_LIM;
 		break;
 	case TOPO_N_PORT:
-		hival = 2;
-		break;
-	case TOPO_FL_PORT:
-		hival = FC_PORT_ID;
+		lim = 2;
 		break;
 	default:
 		isp_prt(isp, ISP_LOGDEBUG0, "no loop topology to scan");
 		fcp->isp_loopstate = LOOP_LSCAN_DONE;
 		return (0);
 	}
+
 	fcp->isp_loopstate = LOOP_SCANNING_LOOP;
-
-	isp_prt(isp, ISP_LOGDEBUG0, "scanning local loop 0..%d", hival);
+	isp_prt(isp, ISP_LOGDEBUG0, "scanning loop 0..%d", lim-1);
 
 
 	/*
-	 * make sure the temp port database is clean...
+	 * Run through the list and get the port database info for each one.
 	 */
-	MEMZERO((void *)fcp->tport, sizeof (fcp->tport));
-
-	/*
-	 * Run through the local loop ports and get port database info
-	 * for each loop ID.
-	 *
-	 * There's a somewhat unexplained situation where the f/w passes back
-	 * the wrong database entity- if that happens, just restart (up to
-	 * FL_PORT_ID times).
-	 */
-	for (lim = loopid = 0; loopid < hival; loopid++) {
-		lp = &fcp->tport[loopid];
-
+	for (dbidx = 0; dbidx < lim; dbidx++) {
 		/*
-		 * Don't even try for ourselves...
+		 * But don't even try for ourselves...
 	 	 */
-		if (loopid == fcp->isp_loopid) {
+		if (dbidx == fcp->isp_loopid) {
 			continue;
 		}
 
+		/*
+		 * In older cards with older f/w GET_PORT_DATABASE has been
+		 * known to hang. This trick gets around that problem.
+		 */
 		if (IS_2100(isp) || IS_2200(isp)) {
-			lp->node_wwn = isp_get_portname(isp, loopid, 1);
+			uint64_t node_wwn = isp_get_portname(isp, dbidx, 1);
 			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
 				return (-1);
 			}
-			if (lp->node_wwn == 0) {
+			if (node_wwn == 0) {
 				continue;
 			}
 		}
 
 		/*
-		 * Get an entry....
+		 * Get the port database entity for this index.
 		 */
-		if (isp_getpdb(isp, loopid, &pdb) != 0) {
+		if (isp_getpdb(isp, dbidx, &pdb, 1) != 0) {
 			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
+				isp_mark_portdb(isp, 1);
 				return (-1);
 			}
 			continue;
 		}
 
 		if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
+			isp_mark_portdb(isp, 1);
 			return (-1);
 		}
 
 		/*
-		 * If the returned database element doesn't match what we
-		 * asked for, restart the process entirely (up to a point...).
+		 * On *very* old 2100 firmware we would end up sometimes
+		 * with the firmware returning the port database entry
+		 * for something else. We used to restart locally, but
+		 * now we punt.
 		 */
-		if (pdb.pdb_loopid != loopid) {
-			loopid = 0;
-			if (lim++ < hival) {
-				continue;
-			}
+		if (IS_2100(isp) && pdb.handle != dbidx) {
 			isp_prt(isp, ISP_LOGWARN,
 			    "giving up on synchronizing the port database");
+			isp_mark_portdb(isp, 1);
 			return (-1);
 		}
 
 		/*
 		 * Save the pertinent info locally.
 		 */
-		lp->node_wwn =
-		    (((uint64_t)pdb.pdb_nodename[0]) << 56) |
-		    (((uint64_t)pdb.pdb_nodename[1]) << 48) |
-		    (((uint64_t)pdb.pdb_nodename[2]) << 40) |
-		    (((uint64_t)pdb.pdb_nodename[3]) << 32) |
-		    (((uint64_t)pdb.pdb_nodename[4]) << 24) |
-		    (((uint64_t)pdb.pdb_nodename[5]) << 16) |
-		    (((uint64_t)pdb.pdb_nodename[6]) <<  8) |
-		    (((uint64_t)pdb.pdb_nodename[7]));
-		lp->port_wwn =
-		    (((uint64_t)pdb.pdb_portname[0]) << 56) |
-		    (((uint64_t)pdb.pdb_portname[1]) << 48) |
-		    (((uint64_t)pdb.pdb_portname[2]) << 40) |
-		    (((uint64_t)pdb.pdb_portname[3]) << 32) |
-		    (((uint64_t)pdb.pdb_portname[4]) << 24) |
-		    (((uint64_t)pdb.pdb_portname[5]) << 16) |
-		    (((uint64_t)pdb.pdb_portname[6]) <<  8) |
-		    (((uint64_t)pdb.pdb_portname[7]));
-		lp->roles =
-		    (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
-		lp->portid = BITS2WORD(pdb.pdb_portid_bits);
-		lp->loopid = pdb.pdb_loopid;
-	}
-
-	/*
-	 * Mark all of the permanent local loop database entries as invalid
-	 * (except our own entry).
-	 */
-	for (loopid = 0; loopid < hival; loopid++) {
-		if (loopid == fcp->isp_iid) {
-			fcp->portdb[loopid].valid = 1;
-			fcp->portdb[loopid].loopid = fcp->isp_loopid;
-			continue;
-		}
-		fcp->portdb[loopid].valid = 0;
-	}
-
-	/*
-	 * Now merge our local copy of the port database into our saved copy.
-	 * Notify the outer layers of new devices arriving.
-	 */
-	for (loopid = 0; loopid < hival; loopid++) {
-		int i;
+		MAKE_WWN_FROM_NODE_NAME(tmp.node_wwn, pdb.nodename);
+		MAKE_WWN_FROM_NODE_NAME(tmp.port_wwn, pdb.portname);
+		tmp.roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
+		tmp.portid = pdb.portid;
+		tmp.handle = pdb.handle;
 
 		/*
-		 * If we don't have a non-zero Port WWN, we're not here.
+		 * Check to make sure it's still a valid entry. The 24XX seems
+		 * to return a portid but not a WWPN/WWNN or role for devices
+		 * which shift on a loop.
 		 */
-		if (fcp->tport[loopid].port_wwn == 0) {
+		if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) {
+			isp_prt(isp, ISP_LOGWARN,
+			    "bad pdb entry at loop %d", dbidx);
+			isp_dump_portdb(isp);
 			continue;
 		}
 
 		/*
-		 * Skip ourselves.
+		 * Now search the entire port database
+		 * for the same Port and Node WWN.
 		 */
-		if (loopid == fcp->isp_iid) {
-			continue;
-		}
-
-		/*
-		 * For the purposes of deciding whether this is the
-		 * 'same' device or not, we only search for an identical
-		 * Port WWN. Node WWNs may or may not be the same as
-		 * the Port WWN, and there may be multiple different
-		 * Port WWNs with the same Node WWN. It would be chaos
-		 * to have multiple identical Port WWNs, so we don't
-		 * allow that.
-		 */
-
-		for (i = 0; i < hival; i++) {
-			int j;
-			if (fcp->portdb[i].port_wwn == 0)
+		for (i = 0; i < MAX_FC_TARG; i++) {
+			lp = &fcp->portdb[i];
+			if (lp->state == FC_PORTDB_STATE_NIL) {
+				continue;
+			}
+			if (lp->node_wwn != tmp.node_wwn) {
+				continue;
+			}
+			if (lp->port_wwn != tmp.port_wwn) {
 				continue;
-			if (fcp->portdb[i].port_wwn !=
-			    fcp->tport[loopid].port_wwn)
-				continue;
-			/*
-			 * We found this WWN elsewhere- it's changed
-			 * loopids then. We don't change it's actual
-			 * position in our cached port database- we
-			 * just change the actual loop ID we'd use.
-			 */
-			if (fcp->portdb[i].loopid != loopid) {
-				isp_prt(isp, ISP_LOGINFO, portshift, i,
-				    fcp->portdb[i].loopid,
-				    fcp->portdb[i].portid, loopid,
-				    fcp->tport[loopid].portid);
 			}
-			fcp->portdb[i].portid = fcp->tport[loopid].portid;
-			fcp->portdb[i].loopid = loopid;
-			fcp->portdb[i].valid = 1;
-			fcp->portdb[i].roles = fcp->tport[loopid].roles;
 
 			/*
-			 * Now make sure this Port WWN doesn't exist elsewhere
-			 * in the port database.
+			 * Okay- we've found a non-nil entry that matches.
+			 * Check to make sure it's probational.
 			 */
-			for (j = i+1; j < hival; j++) {
-				if (fcp->portdb[i].port_wwn !=
-				    fcp->portdb[j].port_wwn) {
-					continue;
-				}
-				isp_prt(isp, ISP_LOGWARN, portdup, j, i);
-				/*
-				 * Invalidate the 'old' *and* 'new' ones.
-				 * This is really harsh and not quite right,
-				 * but if this happens, we really don't know
-				 * who is what at this point.
-				 */
-				fcp->portdb[i].valid = 0;
-				fcp->portdb[j].valid = 0;
+			if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
+				isp_prt(isp, ISP_LOGERR,
+				    "portdb entry %d not probational (0x%x)",
+				    i, lp->state);
+				isp_dump_portdb(isp);
+				isp_mark_portdb(isp, 1);
+				return (-1);
 			}
+
+			lp->autologin = 1;
+			/*
+			 * Check to make sure it's really the same
+			 * device and update the initiator map before
+			 * we mark it as pending valid.
+			 */
+			if (lp->portid == tmp.portid &&
+			    lp->handle == tmp.handle &&
+			    lp->roles == tmp.roles) {
+				lp->new_portid = tmp.portid;
+				lp->new_roles = tmp.roles;
+				lp->state = FC_PORTDB_STATE_PENDING_VALID;
+				break;
+			}
+		
+			/*
+			 * We can wipe out the old handle value here because
+			 * it's no longer valid.
+			 */
+			lp->handle = tmp.handle;
+
+			/*
+			 * Claim that this has changed and let somebody else
+			 * decide what to do.
+			 */
+			lp->state = FC_PORTDB_STATE_CHANGED;
+			lp->new_portid = tmp.portid;
+			lp->new_roles = tmp.roles;
 			break;
 		}
 
 		/*
-		 * If we didn't traverse the entire port database,
-		 * then we found (and remapped) an existing entry.
-		 * No need to notify anyone- go for the next one.
+		 * Did we find and update an old entry?
 		 */
-		if (i < hival) {
-			isp_prt(isp, ISP_LOGINFO, retained,
-			    fcp->portdb[i].loopid, i, fcp->portdb[i].portid);
+		if (i < MAX_FC_TARG) {
 			continue;
 		}
 
 		/*
-		 * We've not found this Port WWN anywhere. It's a new entry.
-		 * See if we can leave it where it is (with target == loopid).
+		 * Ah. A new device entry. Find an empty slot
+		 * for it and save info for later disposition.
 		 */
-		if (fcp->portdb[loopid].port_wwn != 0) {
-			for (lim = 0; lim < hival; lim++) {
-				if (fcp->portdb[lim].port_wwn == 0)
-					break;
+		for (i = 0; i < MAX_FC_TARG; i++) {
+			if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) {
+				break;
 			}
-			/* "Cannot Happen" */
-			if (lim == hival) {
-				isp_prt(isp, ISP_LOGWARN, "Remap Overflow");
-				continue;
-			}
-			i = lim;
-		} else {
-			i = loopid;
 		}
-
-		/*
-		 * NB:	The actual loopid we use here is loopid- we may
-		 *	in fact be at a completely different index (target).
-		 */
-		fcp->portdb[i].loopid = loopid;
-		fcp->portdb[i].port_wwn = fcp->tport[loopid].port_wwn;
-		fcp->portdb[i].node_wwn = fcp->tport[loopid].node_wwn;
-		fcp->portdb[i].roles = fcp->tport[loopid].roles;
-		fcp->portdb[i].portid = fcp->tport[loopid].portid;
-		fcp->portdb[i].valid = 1;
-
-		/*
-		 * Tell the outside world we've arrived.
-		 */
-		(void) isp_async(isp, ISPASYNC_PROMENADE, &i);
-	}
-
-	/*
-	 * Now find all previously used targets that are now invalid and
-	 * notify the outer layers that they're gone.
-	 */
-	for (lp = &fcp->portdb[0]; lp < &fcp->portdb[hival]; lp++) {
-		if (lp->valid || lp->port_wwn == 0) {
+		if (i == MAX_FC_TARG) {
+			isp_prt(isp, ISP_LOGERR,
+			    "could not find slot for new entry");
 			continue;
 		}
+		lp = &fcp->portdb[i];
 
-		/*
-		 * Tell the outside world we've gone
-		 * away and erase our pdb entry.
-		 *
-		 */
-		loopid = lp - fcp->portdb;
-		(void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
-		MEMZERO((void *) lp, sizeof (*lp));
+		lp->autologin = 1;
+		lp->state = FC_PORTDB_STATE_NEW;
+		lp->portid = 0;
+		lp->roles = 0;
+		lp->new_portid = tmp.portid;
+		lp->new_roles = tmp.roles;
+		lp->handle = tmp.handle;
+		lp->port_wwn = tmp.port_wwn;
+		lp->node_wwn = tmp.node_wwn;
 	}
+
 	fcp->isp_loopstate = LOOP_LSCAN_DONE;
 	return (0);
 }
 
+/*
+ * Scan the fabric for devices and add them to our port database.
+ *
+ * Use the GID_FT command to get all Port IDs for FC4 SCSI devices it knows.
+ *
+ * For 2100-23XX cards, we can use the SNS mailbox command to pass simple
+ * name server commands to the switch management server via the QLogic f/w.
+ *
+ * For the 24XX card, we have to use CT-Pass through run via the Execute IOCB
+ * mailbox command.
+ *
+ * The net result is to leave the list of Port IDs setting untranslated in
+ * offset IGPOFF of the FC scratch area, whereupon we'll canonicalize it to
+ * host order at OGPOFF.
+ */
 
-static int
-isp_fabric_mbox_cmd(ispsoftc_t *isp, mbreg_t *mbp)
-{
-	/* the caller sets up the mailbox */
-	isp_mboxcmd(isp, mbp, MBLOGNONE);
-	if (mbp->param[0] != MBOX_COMMAND_COMPLETE) {
-		if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) {
-			FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
-		}
-		if (mbp->param[0] == MBOX_COMMAND_ERROR) {
-			char tbuf[16];
-			char *m;
-			switch (mbp->param[1]) {
-			case 1:
-				m = "No Loop";
-				break;
-			case 2:
-				m = "Failed to allocate IOCB buffer";
-				break;
-			case 3:
-				m = "Failed to allocate XCB buffer";
-				break;
-			case 4:
-				m = "timeout or transmit failed";
-				break;
-			case 5:
-				m = "no fabric loop";
-				break;
-			case 6:
-				m = "remote device not a target";
-				break;
-			default:
-				SNPRINTF(tbuf, sizeof tbuf, "%x",
-				    mbp->param[1]);
-				m = tbuf;
-				break;
-			}
-			isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m);
-		}
-		return (-1);
-	}
-
-	if (FCPARAM(isp)->isp_fwstate != FW_READY ||
-	    FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) {
-		return (-1);
-	}
-	return(0);
-}
-
-#ifdef	ISP_USE_GA_NXT
-static int
-isp_scan_fabric(ispsoftc_t *isp, int ftype)
-{
-	fcparam *fcp = isp->isp_param;
-	uint32_t portid, first_portid, last_portid;
-	int hicap, last_port_same;
-
-	if (fcp->isp_onfabric == 0) {
-		fcp->isp_loopstate = LOOP_FSCAN_DONE;
-		return (0);
-	}
-
-	isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GA_NXT)");
-
-	FC_SCRATCH_ACQUIRE(isp);
-
-	/*
-	 * Since Port IDs are 24 bits, we can check against having seen
-	 * anything yet with this value.
-	 */
-	last_port_same = 0;
-	last_portid = 0xffffffff;	/* not a port */
-	first_portid = portid = fcp->isp_portid;
-	fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
-
-	for (hicap = 0; hicap < GA_NXT_MAX; hicap++) {
-		mbreg_t mbs;
-		sns_screq_t *rq;
-		sns_ga_nxt_rsp_t *rs0, *rs1;
-		struct lportdb lcl;
-		uint8_t sc[SNS_GA_NXT_RESP_SIZE];
-
-		rq = (sns_screq_t *)sc;
-		MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE);
-		rq->snscb_rblen = SNS_GA_NXT_RESP_SIZE >> 1;
-		rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100);
-		rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100);
-		rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100);
-		rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100);
-		rq->snscb_sblen = 6;
-		rq->snscb_data[0] = SNS_GA_NXT;
-		rq->snscb_data[4] = portid & 0xffff;
-		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);
-		mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-		/*
-		 * Leave 4 and 5 alone
-		 */
-		mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-		mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-		if (isp_fabric_mbox_cmd(isp, &mbs)) {
-			if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
-				fcp->isp_loopstate = LOOP_PDB_RCVD;
-			}
-			FC_SCRATCH_RELEASE(isp);
-			return (-1);
-		}
-		MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE);
-		rs1 = (sns_ga_nxt_rsp_t *) sc;
-		rs0 = (sns_ga_nxt_rsp_t *) ((uint8_t *)fcp->isp_scratch+0x100);
-		isp_get_ga_nxt_response(isp, rs0, rs1);
-		if (rs1->snscb_cthdr.ct_response != FS_ACC) {
-			int level;
-			if (rs1->snscb_cthdr.ct_reason == 9 &&
-			    rs1->snscb_cthdr.ct_explanation == 7)
-				level = ISP_LOGDEBUG0;
-			else
-				level = ISP_LOGWARN;
-			isp_prt(isp, level, swrej, "GA_NXT",
-			    rs1->snscb_cthdr.ct_reason,
-			    rs1->snscb_cthdr.ct_explanation, portid);
-			FC_SCRATCH_RELEASE(isp);
-			fcp->isp_loopstate = LOOP_FSCAN_DONE;
-			return (0);
-		}
-		portid =
-		    (((uint32_t) rs1->snscb_port_id[0]) << 16) |
-		    (((uint32_t) rs1->snscb_port_id[1]) << 8) |
-		    (((uint32_t) rs1->snscb_port_id[2]));
-
-		/*
-		 * XXX: We should check to make sure that this entry
-		 * XXX: supports the type(s) we are interested in.
-		 */
-		/*
-		 * Okay, we now have information about a fabric object.
-		 * If it is the type we're interested in, tell the outer layers
-		 * about it. The outer layer needs to  know: Port ID, WWNN,
-		 * WWPN, FC4 type, and port type.
-		 *
-		 * The lportdb structure is adequate for this.
-		 */
-		MEMZERO(&lcl, sizeof (lcl));
-		lcl.port_type = rs1->snscb_port_type;
-		lcl.fc4_type = ftype;
-		lcl.portid = portid;
-		lcl.node_wwn =
-		    (((uint64_t)rs1->snscb_nodename[0]) << 56) |
-		    (((uint64_t)rs1->snscb_nodename[1]) << 48) |
-		    (((uint64_t)rs1->snscb_nodename[2]) << 40) |
-		    (((uint64_t)rs1->snscb_nodename[3]) << 32) |
-		    (((uint64_t)rs1->snscb_nodename[4]) << 24) |
-		    (((uint64_t)rs1->snscb_nodename[5]) << 16) |
-		    (((uint64_t)rs1->snscb_nodename[6]) <<  8) |
-		    (((uint64_t)rs1->snscb_nodename[7]));
-		lcl.port_wwn =
-		    (((uint64_t)rs1->snscb_portname[0]) << 56) |
-		    (((uint64_t)rs1->snscb_portname[1]) << 48) |
-		    (((uint64_t)rs1->snscb_portname[2]) << 40) |
-		    (((uint64_t)rs1->snscb_portname[3]) << 32) |
-		    (((uint64_t)rs1->snscb_portname[4]) << 24) |
-		    (((uint64_t)rs1->snscb_portname[5]) << 16) |
-		    (((uint64_t)rs1->snscb_portname[6]) <<  8) |
-		    (((uint64_t)rs1->snscb_portname[7]));
-
-		/*
-		 * Does this fabric object support the type we want?
-		 * If not, skip it.
-		 */
-		if (rs1->snscb_fc4_types[ftype >> 5] & (1 << (ftype & 0x1f))) {
-			if (first_portid == portid) {
-				lcl.last_fabric_dev = 1;
-			} else {
-				lcl.last_fabric_dev = 0;
-			}
-			(void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
-		} else {
-			isp_prt(isp, ISP_LOGDEBUG0,
-			    "PortID 0x%x doesn't support FC4 type 0x%x",
-			    portid, ftype);
-		}
-		if (first_portid == portid) {
-			fcp->isp_loopstate = LOOP_FSCAN_DONE;
-			FC_SCRATCH_RELEASE(isp);
-			return (0);
-		}
-		if (portid == last_portid) {
-			if (last_port_same++ > 20) {
-				isp_prt(isp, ISP_LOGWARN,
-				    "tangled fabric database detected");
-				break;
-			}
-		} else {
-			last_port_same = 0 ;
-			last_portid = portid;
-		}
-	}
-	FC_SCRATCH_RELEASE(isp);
-	if (hicap >= GA_NXT_MAX) {
-		isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX);
-	}
-	fcp->isp_loopstate = LOOP_FSCAN_DONE;
-	return (0);
-}
-#else
-#define	GIDLEN	((ISP2100_SCRLEN >> 1) + 16)
+/*
+ * Take less than half of our scratch area to store Port IDs 
+ */
+#define	GIDLEN	((ISP2100_SCRLEN >> 1) - 16 - SNS_GID_FT_REQ_SIZE)
 #define	NGENT	((GIDLEN - 16) >> 2)
 
-#define	IGPOFF	(ISP2100_SCRLEN - GIDLEN)
-#define	GXOFF	(256)
+#define	IGPOFF	(2 * QENTRY_LEN)
+#define	OGPOFF	(ISP2100_SCRLEN >> 1)
+#define	ZTXOFF	(ISP2100_SCRLEN - (1 * QENTRY_LEN))
+#define	CTXOFF	(ISP2100_SCRLEN - (2 * QENTRY_LEN))
+#define	XTXOFF	(ISP2100_SCRLEN - (3 * QENTRY_LEN))
 
 static int
-isp_scan_fabric(ispsoftc_t *isp, int ftype)
+isp_gid_ft_sns(ispsoftc_t *isp)
 {
+	union {
+		sns_gid_ft_req_t _x;
+		uint8_t _y[SNS_GID_FT_REQ_SIZE];
+	} un;
 	fcparam *fcp = FCPARAM(isp);
+	sns_gid_ft_req_t *rq = &un._x;
 	mbreg_t mbs;
-	int i;
-	sns_gid_ft_req_t *rq;
-	sns_gid_ft_rsp_t *rs0, *rs1;
 
-	if (fcp->isp_onfabric == 0) {
-		fcp->isp_loopstate = LOOP_FSCAN_DONE;
-		return (0);
-	}
+	isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via SNS");
 
-	isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT)");
-
-	FC_SCRATCH_ACQUIRE(isp);
-	fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
-
-	rq = (sns_gid_ft_req_t *)fcp->tport;
-	MEMZERO((void *) rq, SNS_GID_FT_REQ_SIZE);
+	MEMZERO(rq, SNS_GID_FT_REQ_SIZE);
 	rq->snscb_rblen = GIDLEN >> 1;
-	rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+IGPOFF);
-	rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+IGPOFF);
-	rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+IGPOFF);
-	rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+IGPOFF);
+	rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + IGPOFF);
+	rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + IGPOFF);
+	rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + IGPOFF);
+	rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + IGPOFF);
 	rq->snscb_sblen = 6;
 	rq->snscb_cmd = SNS_GID_FT;
 	rq->snscb_mword_div_2 = NGENT;
-	rq->snscb_fc4_type = ftype;
-	isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch);
+	rq->snscb_fc4_type = FC4_SCSI;
+
+	isp_put_gid_ft_request(isp, rq, 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);
 	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-
-	/*
-	 * Leave 4 and 5 alone
-	 */
 	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
 	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-	if (isp_fabric_mbox_cmd(isp, &mbs)) {
-		if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
-			fcp->isp_loopstate = LOOP_PDB_RCVD;
+	mbs.logval = MBLOGALL;
+	mbs.timeout = 1000000;
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		if (mbs.param[0] == MBOX_INVALID_COMMAND) {
+			return (1);
+		} else {
+			return (-1);
 		}
-		FC_SCRATCH_RELEASE(isp);
+	}
+	return (0);
+}
+
+static int
+isp_gid_ft_ct_passthru(ispsoftc_t *isp)
+{
+	mbreg_t mbs;
+	fcparam *fcp = FCPARAM(isp);
+	union {
+		isp_ct_pt_t plocal;
+		ct_hdr_t clocal;
+		uint8_t q[QENTRY_LEN];
+	} un;
+	isp_ct_pt_t *pt;
+	ct_hdr_t *ct;
+	uint32_t *rp;
+	uint8_t *scp = fcp->isp_scratch;
+
+	isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via CT");
+
+	if (!IS_24XX(isp)) {
+		return (1);
+	}
+
+	/*
+	 * Build a Passthrough IOCB in memory.
+	 */
+	pt = &un.plocal;
+	MEMZERO(un.q, QENTRY_LEN);
+	pt->ctp_header.rqs_entry_count = 1;
+	pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
+	pt->ctp_handle = 0xffffffff;
+	pt->ctp_nphdl = NPH_SNS_ID;
+	pt->ctp_cmd_cnt = 1;
+	pt->ctp_time = 30;
+	pt->ctp_rsp_cnt = 1;
+	pt->ctp_rsp_bcnt = GIDLEN;
+	pt->ctp_cmd_bcnt = sizeof (*ct) + sizeof (uint32_t);
+	pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
+	pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
+	pt->ctp_dataseg[0].ds_count = sizeof (*ct) + sizeof (uint32_t);
+	pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF);
+	pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF);
+	pt->ctp_dataseg[1].ds_count = GIDLEN;
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "ct IOCB", QENTRY_LEN, pt);
+	}
+	isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]);
+
+	/*
+	 * Build the CT header and command in memory.
+	 *
+	 * Note that the CT header has to end up as Big Endian format in memory.
+	 */
+	ct = &un.clocal;
+	MEMZERO(ct, sizeof (*ct));
+	ct->ct_revision = CT_REVISION;
+	ct->ct_fcs_type = CT_FC_TYPE_FC;
+	ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
+	ct->ct_cmd_resp = SNS_GID_FT;
+	ct->ct_bcnt_resid = (GIDLEN - 16) >> 2;
+
+	isp_put_ct_hdr(isp, ct, (ct_hdr_t *) &scp[XTXOFF]);
+	rp = (uint32_t *) &scp[XTXOFF+sizeof (*ct)];
+	ISP_IOZPUT_32(isp, FC4_SCSI, rp);
+	MEMZERO(&scp[ZTXOFF], QENTRY_LEN);
+	MEMZERO(&mbs, sizeof (mbs));
+	mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64;
+	mbs.param[1] = QENTRY_LEN;
+	mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
+	mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
+	mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
+	mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
+	mbs.logval = MBLOGALL;
+	MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN);
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 		return (-1);
 	}
+	MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN);
+	pt = &un.plocal;
+	isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt);
+	}
+
+	if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) {
+		isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x",
+		    pt->ctp_status);
+		return (-1);
+	}
+	MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN + 16);
+	return (0);
+}
+
+static int
+isp_scan_fabric(ispsoftc_t *isp)
+{
+	fcparam *fcp = FCPARAM(isp);
+	uint32_t portid;
+	uint16_t handle, oldhandle;
+	int portidx, portlim, r;
+	sns_gid_ft_rsp_t *rs0, *rs1;
+
+	isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric");
+	if (fcp->isp_fwstate != FW_READY ||
+	    fcp->isp_loopstate < LOOP_LSCAN_DONE) {
+		return (-1);
+	}
+	if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
+		return (0);
+	}
+	if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
+		fcp->isp_loopstate = LOOP_FSCAN_DONE;
+		isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done (no fabric)");
+		return (0);
+	}
+
+	FC_SCRATCH_ACQUIRE(isp);
+	fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
+
+	if (IS_24XX(isp)) {
+		r = isp_gid_ft_ct_passthru(isp);
+	} else {
+		r = isp_gid_ft_sns(isp);
+	}
+
+	if (r > 0) {
+		fcp->isp_loopstate = LOOP_FSCAN_DONE;
+		FC_SCRATCH_RELEASE(isp);
+		return (0);
+	} else if (r < 0) {
+		fcp->isp_loopstate = LOOP_PDB_RCVD;	/* try again */
+		FC_SCRATCH_RELEASE(isp);
+		return (0);
+	}
 	if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
 		FC_SCRATCH_RELEASE(isp);
 		return (-1);
 	}
+
 	MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN);
-	rs1 = (sns_gid_ft_rsp_t *) fcp->tport;
 	rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF);
+	rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF);
 	isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
-	if (rs1->snscb_cthdr.ct_response != FS_ACC) {
+	if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
 		int level;
 		if (rs1->snscb_cthdr.ct_reason == 9 &&
-		    rs1->snscb_cthdr.ct_explanation == 7)
+		    rs1->snscb_cthdr.ct_explanation == 7) {
 			level = ISP_LOGDEBUG0;
-		else
+		} else {
 			level = ISP_LOGWARN;
-		isp_prt(isp, level, swrej, "GID_FT",
-		    rs1->snscb_cthdr.ct_reason,
-		    rs1->snscb_cthdr.ct_explanation, 0);
+		}
+		isp_prt(isp, level, "Fabric Nameserver rejected GID_FT "
+		    "(Reason=0x%x Expl=0x%x)", rs1->snscb_cthdr.ct_reason,
+		    rs1->snscb_cthdr.ct_explanation);
 		FC_SCRATCH_RELEASE(isp);
 		fcp->isp_loopstate = LOOP_FSCAN_DONE;
 		return (0);
 	}
 
-	/*
-	 * Okay, we now have a list of Port IDs for this class of device.
-	 * Go through the list and for each one get the WWPN/WWNN for it
-	 * and tell the outer layers about it. The outer layer needs to
-	 * know: Port ID, WWNN, WWPN, FC4 type, and (possibly) port type.
-	 *
-	 * The lportdb structure is adequate for this.
-	 */
-	i = -1;
-	do {
-		sns_gxn_id_req_t grqbuf, *gq = &grqbuf;
-		sns_gxn_id_rsp_t *gs0, grsbuf, *gs1 = &grsbuf;
-		struct lportdb lcl;
-#if	0
-		sns_gff_id_rsp_t *fs0, ffsbuf, *fs1 = &ffsbuf;
-#endif
-
-		i++;
-		MEMZERO(&lcl, sizeof (lcl));
-		lcl.fc4_type = ftype;
-		lcl.portid =
-		    (((uint32_t) rs1->snscb_ports[i].portid[0]) << 16) |
-		    (((uint32_t) rs1->snscb_ports[i].portid[1]) << 8) |
-		    (((uint32_t) rs1->snscb_ports[i].portid[2]));
-
-		MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
-		gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
-		gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
-		gq->snscb_sblen = 6;
-		gq->snscb_cmd = SNS_GPN_ID;
-		gq->snscb_portid = lcl.portid;
-		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);
-		mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-		/*
-		 * Leave 4 and 5 alone
-		 */
-		mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-		mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-		if (isp_fabric_mbox_cmd(isp, &mbs)) {
-			if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
-				fcp->isp_loopstate = LOOP_PDB_RCVD;
-			}
-			FC_SCRATCH_RELEASE(isp);
-			return (-1);
-		}
-		if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
-			FC_SCRATCH_RELEASE(isp);
-			return (-1);
-		}
-		MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
-		gs0 = (sns_gxn_id_rsp_t *) ((uint8_t *)fcp->isp_scratch+GXOFF);
-		isp_get_gxn_id_response(isp, gs0, gs1);
-		if (gs1->snscb_cthdr.ct_response != FS_ACC) {
-			isp_prt(isp, ISP_LOGWARN, swrej, "GPN_ID",
-			    gs1->snscb_cthdr.ct_reason,
-			    gs1->snscb_cthdr.ct_explanation, lcl.portid);
-			if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
-				FC_SCRATCH_RELEASE(isp);
-				return (-1);
-			}
-			continue;
-		}
-		lcl.port_wwn = 
-		    (((uint64_t)gs1->snscb_wwn[0]) << 56) |
-		    (((uint64_t)gs1->snscb_wwn[1]) << 48) |
-		    (((uint64_t)gs1->snscb_wwn[2]) << 40) |
-		    (((uint64_t)gs1->snscb_wwn[3]) << 32) |
-		    (((uint64_t)gs1->snscb_wwn[4]) << 24) |
-		    (((uint64_t)gs1->snscb_wwn[5]) << 16) |
-		    (((uint64_t)gs1->snscb_wwn[6]) <<  8) |
-		    (((uint64_t)gs1->snscb_wwn[7]));
-
-		MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
-		gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
-		gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
-		gq->snscb_sblen = 6;
-		gq->snscb_cmd = SNS_GNN_ID;
-		gq->snscb_portid = lcl.portid;
-		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);
-		mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-		/*
-		 * Leave 4 and 5 alone
-		 */
-		mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-		mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-		if (isp_fabric_mbox_cmd(isp, &mbs)) {
-			if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
-				fcp->isp_loopstate = LOOP_PDB_RCVD;
-			}
-			FC_SCRATCH_RELEASE(isp);
-			return (-1);
-		}
-		if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
-			FC_SCRATCH_RELEASE(isp);
-			return (-1);
-		}
-		MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
-		gs0 = (sns_gxn_id_rsp_t *) ((uint8_t *)fcp->isp_scratch+GXOFF);
-		isp_get_gxn_id_response(isp, gs0, gs1);
-		if (gs1->snscb_cthdr.ct_response != FS_ACC) {
-			isp_prt(isp, ISP_LOGWARN, swrej, "GNN_ID",
-			    gs1->snscb_cthdr.ct_reason,
-			    gs1->snscb_cthdr.ct_explanation, lcl.portid);
-			if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
-				FC_SCRATCH_RELEASE(isp);
-				return (-1);
-			}
-			continue;
-		}
-		lcl.node_wwn = 
-		    (((uint64_t)gs1->snscb_wwn[0]) << 56) |
-		    (((uint64_t)gs1->snscb_wwn[1]) << 48) |
-		    (((uint64_t)gs1->snscb_wwn[2]) << 40) |
-		    (((uint64_t)gs1->snscb_wwn[3]) << 32) |
-		    (((uint64_t)gs1->snscb_wwn[4]) << 24) |
-		    (((uint64_t)gs1->snscb_wwn[5]) << 16) |
-		    (((uint64_t)gs1->snscb_wwn[6]) <<  8) |
-		    (((uint64_t)gs1->snscb_wwn[7]));
-
-		/*
-		 * The QLogic f/w is bouncing this with a parameter error.
-		 */
-#if	0
-		/*
-		 * Try and get FC4 Features (FC-GS-3 only).
-		 * We can use the sns_gxn_id_req_t for this request.
-		 */
-		MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
-		gq->snscb_rblen = SNS_GFF_ID_RESP_SIZE >> 1;
-		gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
-		gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
-		gq->snscb_sblen = 6;
-		gq->snscb_cmd = SNS_GFF_ID;
-		gq->snscb_portid = lcl.portid;
-		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);
-		mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-		/*
-		 * Leave 4 and 5 alone
-		 */
-		mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-		mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-		if (isp_fabric_mbox_cmd(isp, &mbs)) {
-			if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
-				fcp->isp_loopstate = LOOP_PDB_RCVD;
-			}
-			FC_SCRATCH_RELEASE(isp);
-			return (-1);
-		}
-		if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
-			FC_SCRATCH_RELEASE(isp);
-			return (-1);
-		}
-		MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GFF_ID_RESP_SIZE);
-		fs0 = (sns_gff_id_rsp_t *) ((uint8_t *)fcp->isp_scratch+GXOFF);
-		isp_get_gff_id_response(isp, fs0, fs1);
-		if (fs1->snscb_cthdr.ct_response != FS_ACC) {
-			isp_prt(isp, /* ISP_LOGDEBUG0 */ ISP_LOGWARN,
-			    swrej, "GFF_ID",
-			    fs1->snscb_cthdr.ct_reason,
-			    fs1->snscb_cthdr.ct_explanation, lcl.portid);
-			if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
-				FC_SCRATCH_RELEASE(isp);
-				return (-1);
-			}
-		} else {
-			int index = (ftype >> 3);
-			int bshft = (ftype & 0x7) * 4;
-			int fc4_fval =
-			    (fs1->snscb_fc4_features[index] >> bshft) & 0xf;
-			if (fc4_fval & 0x1) {
-				lcl.roles |=
-				    (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT);
-			}
-			if (fc4_fval & 0x2) {
-				lcl.roles |=
-				    (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
-			}
-		}
-#endif
-
-		/*
-		 * If we really want to know what kind of port type this is,
-		 * we have to run another CT command. Otherwise, we'll leave
-		 * it as undefined.
-		 *
-		lcl.port_type = 0;
-		 */
-		if (rs1->snscb_ports[i].control & 0x80) {
-			lcl.last_fabric_dev = 1;
-		} else {
-			lcl.last_fabric_dev = 0;
-		}
-		(void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
-
-	} while ((rs1->snscb_ports[i].control & 0x80) == 0 && i < NGENT-1);
 
 	/*
-	 * If we're not at the last entry, our list isn't big enough.
+	 * If we get this far, we certainly still have the fabric controller.
 	 */
-	if ((rs1->snscb_ports[i].control & 0x80) == 0) {
-		isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area");
+	fcp->portdb[FL_ID].state = FC_PORTDB_STATE_PENDING_VALID;
+
+	/*
+	 * Prime the handle we will start using.
+	 */
+	oldhandle = 0xffff;
+
+	/*
+	 * Okay, we now have a list of Port IDs for all FC4 SCSI devices
+	 * that the Fabric Name server knows about. Go through the list
+	 * and remove duplicate port ids.
+	 */
+
+	portlim = 0;
+	portidx = 0;
+	for (portidx = 0; portidx < NGENT-1; portidx++) {
+		if (rs1->snscb_ports[portidx].control & 0x80) {
+			break;
+		}
 	}
 
+	/*
+	 * If we're not at the last entry, our list wasn't big enough.
+	 */
+	if ((rs1->snscb_ports[portidx].control & 0x80) == 0) {
+		isp_prt(isp, ISP_LOGWARN,
+		    "fabric too big for scratch area: increase ISP2100_SCRLEN");
+	}
+	portlim = portidx + 1;
+	isp_prt(isp, ISP_LOGDEBUG0, "got %d ports back from name server",
+	    portlim);
+
+	for (portidx = 0; portidx < portlim; portidx++) {
+		int npidx;
+
+		portid =
+		    ((rs1->snscb_ports[portidx].portid[0]) << 16) |
+		    ((rs1->snscb_ports[portidx].portid[1]) << 8) |
+		    ((rs1->snscb_ports[portidx].portid[2]));
+
+		for (npidx = portidx + 1; npidx < portlim; npidx++) {
+			uint32_t new_portid =
+			    ((rs1->snscb_ports[npidx].portid[0]) << 16) |
+			    ((rs1->snscb_ports[npidx].portid[1]) << 8) |
+			    ((rs1->snscb_ports[npidx].portid[2]));
+			if (new_portid == portid) {
+				break;
+			}
+		}
+
+		if (npidx < portlim) {
+			rs1->snscb_ports[npidx].portid[0] = 0;
+			rs1->snscb_ports[npidx].portid[1] = 0;
+			rs1->snscb_ports[npidx].portid[2] = 0;
+			isp_prt(isp, ISP_LOGDEBUG0,
+			    "removing duplicate PortID 0x%x entry from list",
+			    portid);
+		}
+	}
+
+	/*
+	 * Okay, we now have a list of Port IDs for all FC4 SCSI devices
+	 * that the Fabric Name server knows about.
+	 *
+	 * For each entry on this list go through our port database looking
+	 * for probational entries- if we find one, then an old entry is
+	 * is maybe still this one. We get some information to find out.
+	 *
+	 * Otherwise, it's a new fabric device, and we log into it
+	 * (unconditionally). After searching the entire database
+	 * again to make sure that we never ever ever ever have more
+	 * than one entry that has the same PortID or the same
+	 * WWNN/WWPN duple, we enter the device into our database.
+	 */
+
+	for (portidx = 0; portidx < portlim; portidx++) {
+		fcportdb_t *lp;
+		isp_pdb_t pdb;
+		uint64_t wwnn, wwpn;
+		int dbidx, r, nr;
+
+		portid =
+		    ((rs1->snscb_ports[portidx].portid[0]) << 16) |
+		    ((rs1->snscb_ports[portidx].portid[1]) << 8) |
+		    ((rs1->snscb_ports[portidx].portid[2]));
+
+		if (portid == 0) {
+			isp_prt(isp, ISP_LOGDEBUG0,
+			    "skipping null PortID at idx %d", portidx);
+			continue;
+		}
+
+		/*
+		 * Skip ourselves...
+		 */
+		if (portid == fcp->isp_portid) {
+			isp_prt(isp, ISP_LOGDEBUG0,
+			    "skip ourselves @ PortID 0x%06x", portid);
+			continue;
+		}
+		isp_prt(isp, ISP_LOGDEBUG0, "Fabric Port 0x%06x", portid);
+
+		/*
+		 * We now search our Port Database for any
+		 * probational entries with this PortID.
+		 */
+		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+			lp = &fcp->portdb[dbidx];
+
+			if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
+				continue;
+			}
+			if (lp->portid == portid) {
+				break;
+			}
+		}
+
+		/*
+		 * We found a probational entry with this Port ID.
+		 */
+		if (dbidx < MAX_FC_TARG) {
+			int handle_changed = 0;
+
+			lp = &fcp->portdb[dbidx];
+
+			/*
+			 * See if we're still logged into it.
+			 *
+			 * If we aren't, mark it as a dead device and
+			 * leave the new portid in the database entry
+			 * for somebody further along to decide what to
+			 * do (policy choice).
+			 *
+			 * If we are, check to see if it's the same
+			 * device still (it should be). If for some
+			 * reason it isn't, mark it as a changed device
+			 * and leave the new portid and role in the
+			 * database entry for somebody further along to
+			 * decide what to do (policy choice).
+			 *
+			 */
+
+			r = isp_getpdb(isp, lp->handle, &pdb, 0);
+			if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+				FC_SCRATCH_RELEASE(isp);
+				isp_mark_portdb(isp, 1);
+				return (-1);
+			}
+			if (r != 0) {
+				lp->new_portid = portid;
+				lp->state = FC_PORTDB_STATE_DEAD;
+				continue;
+			}
+
+
+			/*
+			 * Check to make sure that handle, portid, WWPN and
+			 * WWNN agree. If they don't, then the association
+			 * between this PortID and the stated handle has been
+			 * broken by the firmware.
+			 */
+			MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
+			MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
+			if (pdb.handle != lp->handle ||
+			    pdb.portid != portid ||
+			    wwpn != lp->port_wwn ||
+			    wwnn != lp->node_wwn) {
+				isp_prt(isp, ISP_LOGDEBUG0, fconf, dbidx,
+				    pdb.handle, pdb.portid,
+				    (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
+				    (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
+				    lp->handle, portid,
+				    (uint32_t) (lp->node_wwn >> 32),
+				    (uint32_t) lp->node_wwn,
+				    (uint32_t) (lp->port_wwn >> 32),
+				    (uint32_t) lp->port_wwn);
+				/*
+				 * Try to re-login to this device using a
+				 * new handle. If that fails, mark it dead.
+				 * 
+				 * isp_login_device will check for handle and
+				 * portid consistency after re-login.
+				 * 
+				 */
+				if (isp_login_device(isp, portid, &pdb,
+				    &oldhandle)) {
+					lp->new_portid = portid;
+					lp->state = FC_PORTDB_STATE_DEAD;
+					if (fcp->isp_loopstate !=
+					    LOOP_SCANNING_FABRIC) {
+						FC_SCRATCH_RELEASE(isp);
+						isp_mark_portdb(isp, 1);
+						return (-1);
+					}
+					continue;
+				}
+				MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
+				MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
+				if (wwpn != lp->port_wwn ||
+				    wwnn != lp->node_wwn) {
+					isp_prt(isp, ISP_LOGWARN, "changed WWN"
+					    " after relogin");
+					lp->new_portid = portid;
+					lp->state = FC_PORTDB_STATE_DEAD;
+					continue;
+				}
+
+				lp->handle = pdb.handle;
+				handle_changed++;
+			}
+
+			nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
+
+			/*
+			 * Check to see whether the portid and roles have
+			 * stayed the same. If they have stayed the same,
+			 * we believe that this is the same device and it
+			 * hasn't become disconnected and reconnected, so
+			 * mark it as pending valid.
+			 *
+			 * If they aren't the same, mark the device as a
+			 * changed device and save the new port id and role
+			 * and let somebody else decide.
+			 */
+
+			lp->new_portid = portid;
+			lp->new_roles = nr;
+			if (pdb.portid != lp->portid || nr != lp->roles ||
+			    handle_changed) {
+				lp->state = FC_PORTDB_STATE_CHANGED;
+			} else {
+				lp->state = FC_PORTDB_STATE_PENDING_VALID;
+			}
+			continue;
+		}
+
+		/*
+		 * Ah- a new entry. Search the database again for all non-NIL
+		 * entries to make sure we never ever make a database entry
+		 * with the same port id.
+		 */
+		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+			if (dbidx >= FL_ID && dbidx <= SNS_ID) {
+				continue;
+			}
+			if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+				continue;
+			}
+			if (fcp->portdb[dbidx].portid == portid) {
+				break;
+			}
+		}
+
+		if (dbidx != MAX_FC_TARG) {
+			isp_prt(isp, ISP_LOGWARN,
+			    "PortID 0x%06x already at %d handle %d state %d",
+			    portid, dbidx, fcp->portdb[dbidx].handle,
+			    fcp->portdb[dbidx].state);
+			continue;
+		}
+
+		/*
+		 * Find an empty database entry for it.
+		 */
+		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+			if (dbidx >= FL_ID && dbidx <= SNS_ID) {
+				continue;
+			}
+			if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+				break;
+			}
+		}
+
+		if (dbidx == MAX_FC_TARG) {
+			isp_prt(isp, ISP_LOGERR,
+			    "port database too small to login fabric device"
+			    "- increase MAX_FC_TARG");
+			continue;
+		}
+
+		/*
+		 * Try to see if we are logged into this device,
+		 * and maybe log into it.
+		 *
+		 * isp_login_device will check for handle and
+		 * portid consistency after login.
+		 */
+		if (isp_login_device(isp, portid, &pdb, &oldhandle)) {
+			if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+				FC_SCRATCH_RELEASE(isp);
+				isp_mark_portdb(isp, 1);
+				return (-1);
+			}
+			continue;
+		}
+
+		handle = pdb.handle;
+		MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
+		MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
+		nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
+
+		/*
+		 * And go through the database *one* more time to make sure
+		 * that we do not make more than one entry that has the same
+		 * WWNN/WWPN duple
+		 */
+		lp = &fcp->portdb[dbidx];
+
+		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+			if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+				continue;
+			}
+			if (dbidx >= FL_ID && dbidx <= SNS_ID) {
+				continue;
+			}
+			if (fcp->portdb[dbidx].node_wwn == wwnn &&
+			    fcp->portdb[dbidx].port_wwn == wwpn) {
+				break;
+			}
+		}
+
+		if (dbidx != MAX_FC_TARG) {
+			isp_prt(isp, ISP_LOGWARN,
+			    "PortID 0x%x 0x%08x%08x/0x%08x%08x %ld already at "
+			    "idx %d", portid,
+			    (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
+			    (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
+			    (long) (lp - fcp->portdb), dbidx);
+			continue;
+		}
+
+		lp->handle = handle;
+		lp->ini_map_idx = 0;
+		lp->node_wwn = wwnn;
+		lp->port_wwn = wwpn;
+		lp->new_portid = portid;
+		lp->new_roles = nr;
+		lp->state = FC_PORTDB_STATE_NEW;
+	}
+
+
 	FC_SCRATCH_RELEASE(isp);
+	if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+		isp_mark_portdb(isp, 1);
+		return (-1);
+	}
 	fcp->isp_loopstate = LOOP_FSCAN_DONE;
+	isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done");
 	return (0);
 }
-#endif
 
-static void
+/*
+ * Find an unused handle and try and use to login to a port.
+ */
+static int
+isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
+{
+	int lim, i, r, logval;
+	uint16_t handle;
+
+	if (IS_24XX(isp)) {
+		lim = NPH_MAX_24XX;
+	} else {
+		lim = NPH_MAX;
+	}
+
+	handle = isp_nxt_handle(isp, *ohp);
+	for (i = 0; i < lim; i++) {
+		/*
+		 * See if we're still logged into something with
+		 * this handle and that something agrees with this
+		 * port id.
+		 */
+		r = isp_getpdb(isp, handle, p, 0);
+		if (r == 0 && p->portid != portid) {
+			if (IS_24XX(isp)) {
+				logval =
+				    PLOGX_FLG_CMD_LOGO |
+				    PLOGX_FLG_IMPLICIT;
+				isp_plogx_24xx(isp, handle, portid, &logval);
+			} else {
+				isp_port_logout(isp, handle, portid);
+			}
+		} else if (r == 0) {
+			break;
+		}
+		if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+			return (-1);
+		}
+		/*
+		 * Now try and log into the device
+		 */
+		if (IS_24XX(isp)) {
+			logval = PLOGX_FLG_CMD_PLOGI;
+			isp_plogx_24xx(isp, handle, portid, &logval);
+		} else {
+			logval = isp_port_login(isp, handle, portid);
+		}
+		if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+			return (-1);
+		}
+		if (logval == 0) {
+			*ohp = handle;
+			break;
+		} else if ((logval & 0xffff) == MBOX_PORT_ID_USED) {
+			handle = logval >> 16;
+			break;
+		} else if (logval != MBOX_LOOP_ID_USED) {
+			i = lim;
+			break;
+		} else {
+			*ohp = handle;
+			handle = isp_nxt_handle(isp, *ohp);
+		}
+	}
+
+	if (i == lim) {
+		isp_prt(isp, ISP_LOGINFO, "PLOGI 0x%06x failed", portid);
+		return (-1);
+	}
+
+	/*
+	 * If we successfully logged into it, get the PDB for it
+	 * so we can crosscheck that it is still what we think it
+	 * is and that we also have the role it plays
+	 */
+	r = isp_getpdb(isp, handle, p, 0);
+	if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+		return (-1);
+	}
+	if (r != 0) {
+		isp_prt(isp, ISP_LOGERR, "new device 0x%06x@0x%x disappeared",
+		    portid, handle);
+		return (-1);
+	}
+
+	if (p->handle != handle || p->portid != portid) {
+		isp_prt(isp, ISP_LOGERR,
+		    "new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
+		    portid, handle, p->portid, p->handle);
+		return (-1);
+	}
+	return (0);
+}
+
+static int
 isp_register_fc4_type(ispsoftc_t *isp)
 {
 	fcparam *fcp = isp->isp_param;
@@ -3046,9 +3783,6 @@ isp_register_fc4_type(ispsoftc_t *isp)
 	reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
 	reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
 	reqp->snscb_data[6] = (1 << FC4_SCSI);
-#if	0
-	reqp->snscb_data[6] |= (1 << FC4_IP);	/* ISO/IEC 8802-2 LLC/SNAP */
-#endif
 	FC_SCRATCH_ACQUIRE(isp);
 	isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
 	MEMZERO(&mbs, sizeof (mbs));
@@ -3056,16 +3790,149 @@ isp_register_fc4_type(ispsoftc_t *isp)
 	mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
 	mbs.param[2] = DMA_WD1(fcp->isp_scdma);
 	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-	/*
-	 * Leave 4 and 5 alone
-	 */
 	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
 	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+	mbs.logval = MBLOGALL;
+	mbs.timeout = 1000000;
 	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_RFT_ID_REQ_SIZE);
-	isp_mboxcmd(isp, &mbs, MBLOGALL);
+	isp_mboxcmd(isp, &mbs);
 	FC_SCRATCH_RELEASE(isp);
 	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
-		isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded");
+		return (0);
+	} else {
+		return (-1);
+	}
+}
+
+static int
+isp_register_fc4_type_24xx(ispsoftc_t *isp)
+{
+	mbreg_t mbs;
+	fcparam *fcp = FCPARAM(isp);
+	union {
+		isp_ct_pt_t plocal;
+		rft_id_t clocal;
+		uint8_t q[QENTRY_LEN];
+	} un;
+	isp_ct_pt_t *pt;
+	ct_hdr_t *ct;
+	rft_id_t *rp;
+	uint8_t *scp = fcp->isp_scratch;
+
+	FC_SCRATCH_ACQUIRE(isp);
+	/*
+	 * Build a Passthrough IOCB in memory.
+	 */
+	MEMZERO(un.q, QENTRY_LEN);
+	pt = &un.plocal;
+	pt->ctp_header.rqs_entry_count = 1;
+	pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
+	pt->ctp_handle = 0xffffffff;
+	pt->ctp_nphdl = NPH_SNS_ID;
+	pt->ctp_cmd_cnt = 1;
+	pt->ctp_time = 1;
+	pt->ctp_rsp_cnt = 1;
+	pt->ctp_rsp_bcnt = sizeof (ct_hdr_t);
+	pt->ctp_cmd_bcnt = sizeof (rft_id_t);
+	pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
+	pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
+	pt->ctp_dataseg[0].ds_count = sizeof (rft_id_t);
+	pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF);
+	pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF);
+	pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t);
+	isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]);
+
+	/*
+	 * Build the CT header and command in memory.
+	 *
+	 * Note that the CT header has to end up as Big Endian format in memory.
+	 */
+	MEMZERO(&un.clocal, sizeof (un.clocal));
+	ct = &un.clocal.rftid_hdr;
+	ct->ct_revision = CT_REVISION;
+	ct->ct_fcs_type = CT_FC_TYPE_FC;
+	ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
+	ct->ct_cmd_resp = SNS_RFT_ID;
+	ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
+	rp = &un.clocal;
+	rp->rftid_portid[0] = fcp->isp_portid >> 16;
+	rp->rftid_portid[1] = fcp->isp_portid >> 8;
+	rp->rftid_portid[2] = fcp->isp_portid;
+	rp->rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
+	isp_put_rft_id(isp, rp, (rft_id_t *) &scp[XTXOFF]);
+
+	MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t));
+
+	MEMZERO(&mbs, sizeof (mbs));
+	mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64;
+	mbs.param[1] = QENTRY_LEN;
+	mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
+	mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
+	mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
+	mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
+	mbs.logval = MBLOGALL;
+	MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN);
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		FC_SCRATCH_RELEASE(isp);
+		return (-1);
+	}
+	MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN);
+	pt = &un.plocal;
+	isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt);
+	}
+	if (pt->ctp_status) {
+		FC_SCRATCH_RELEASE(isp);
+		isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x",
+		    pt->ctp_status);
+		return (-1);
+	}
+
+	isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct);
+	FC_SCRATCH_RELEASE(isp);
+
+	if (ct->ct_cmd_resp == LS_RJT) {
+		isp_prt(isp, ISP_LOGWARN, "Register FC4 Type rejected");
+		return (-1);
+	} else if (ct->ct_cmd_resp == LS_ACC) {
+		isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 Type accepted");
+		return(0);
+	} else {
+		isp_prt(isp, ISP_LOGWARN,
+		    "Register FC4 Type: %x", ct->ct_cmd_resp);
+		return (-1);
+	}
+}
+
+static uint16_t
+isp_nxt_handle(ispsoftc_t *isp, uint16_t handle)
+{
+	if (handle == 0xffff) {
+		if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) {
+			handle = 0;
+		} else {
+			handle = SNS_ID+1;
+		}
+	} else {
+		handle += 1;
+		if (handle >= FL_ID && handle <= SNS_ID) {
+			handle = SNS_ID+1;
+		} else if (IS_24XX(isp)) {
+			if (handle == 0xffff) {
+				handle = 0;
+			}
+		} else {
+			if (handle == MAX_FC_TARG) {
+				handle = 0;
+			}
+		}
+	}
+	if (handle == FCPARAM(isp)->isp_loopid) {
+		return (isp_nxt_handle(isp, handle));
+	} else {
+		return (handle);
 	}
 }
 
@@ -3077,9 +3944,12 @@ int
 isp_start(XS_T *xs)
 {
 	ispsoftc_t *isp;
-	uint16_t nxti, optr, handle;
+	uint32_t nxti, optr, handle, isr;
+	uint16_t sema, mbox;
 	uint8_t local[QENTRY_LEN];
 	ispreq_t *reqp, *qep;
+	void *cdbp;
+	uint16_t *tptr;
 	int target, i;
 
 	XS_INITERR(xs);
@@ -3119,198 +3989,42 @@ isp_start(XS_T *xs)
 	}
 
 	/*
-	 * Check to see whether we have good firmware state still or
-	 * need to refresh our port database for this target.
+	 * Translate the target to device handle as appropriate, checking
+	 * for correct device state as well.
 	 */
 	target = XS_TGT(xs);
 	if (IS_FC(isp)) {
 		fcparam *fcp = isp->isp_param;
-		struct lportdb *lp;
-#ifdef	HANDLE_LOOPSTATE_IN_OUTER_LAYERS
+
 		if (fcp->isp_fwstate != FW_READY ||
 		    fcp->isp_loopstate != LOOP_READY) {
 			return (CMD_RQLATER);
 		}
 
-		/*
-		 * If we're not on a Fabric, we can't have a target
-		 * above FL_PORT_ID-1.
-		 *
-		 * If we're on a fabric and *not* connected as an F-port,
-		 * we can't have a target less than FC_SNS_ID+1. This
-		 * keeps us from having to sort out the difference between
-		 * local public loop devices and those which we might get
-		 * from a switch's database.
-		 */
-		if (fcp->isp_onfabric == 0) {
-			if (target >= FL_PORT_ID) {
-				XS_SETERR(xs, HBA_SELTIMEOUT);
-				return (CMD_COMPLETE);
-			}
-		} else {
-			if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
-				XS_SETERR(xs, HBA_SELTIMEOUT);
-				return (CMD_COMPLETE);
-			}
-			/*
-			 * We used to exclude having local loop ports
-			 * at the same time that we have fabric ports.
-			 * That is, we used to exclude having ports
-			 * at < FL_PORT_ID if we're FL-port.
-			 *
-			 * That's wrong. The only thing that could be
-			 * dicey is if the switch you're connected to
-			 * has these local loop ports appear on the
-			 * fabric and we somehow attach them twice.
-			 */
-		}
-#else
-		/*
-		 * Check for f/w being in ready state. If the f/w
-		 * isn't in ready state, then we don't know our
-		 * loop ID and the f/w hasn't completed logging
-		 * into all targets on the loop. If this is the
-		 * case, then bounce the command. We pretend this is
-		 * a SELECTION TIMEOUT error if we've never gone to
-		 * FW_READY state at all- in this case we may not
-		 * be hooked to a loop at all and we shouldn't hang
-		 * the machine for this. Otherwise, defer this command
-		 * until later.
-		 */
-		if (fcp->isp_fwstate != FW_READY) {
-			/*
-			 * Give ourselves at most a 250ms delay.
-			 */
-			if (isp_fclink_test(isp, 250000)) {
-				XS_SETERR(xs, HBA_SELTIMEOUT);
-				if (fcp->loop_seen_once) {
-					return (CMD_RQLATER);
-				} else {
-					return (CMD_COMPLETE);
-				}
-			}
-		}
-
-		/*
-		 * If we're not on a Fabric, we can't have a target
-		 * above FL_PORT_ID-1.
-		 *
-		 * If we're on a fabric and *not* connected as an F-port,
-		 * we can't have a target less than FC_SNS_ID+1. This
-		 * keeps us from having to sort out the difference between
-		 * local public loop devices and those which we might get
-		 * from a switch's database.
-		 */
-		if (fcp->isp_onfabric == 0) {
-			if (target >= FL_PORT_ID) {
-				XS_SETERR(xs, HBA_SELTIMEOUT);
-				return (CMD_COMPLETE);
-			}
-		} else {
-			if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
-				XS_SETERR(xs, HBA_SELTIMEOUT);
-				return (CMD_COMPLETE);
-			}
-			if (fcp->isp_topo != TOPO_F_PORT &&
-			    target < FL_PORT_ID) {
-				XS_SETERR(xs, HBA_SELTIMEOUT);
-				return (CMD_COMPLETE);
-			}
-		}
-
-		/*
-		 * If our loop state is such that we haven't yet received
-		 * a "Port Database Changed" notification (after a LIP or
-		 * a Loop Reset or firmware initialization), then defer
-		 * sending commands for a little while, but only if we've
-		 * seen a valid loop at one point (otherwise we can get
-		 * stuck at initialization time).
-		 */
-		if (fcp->isp_loopstate < LOOP_PDB_RCVD) {
-			XS_SETERR(xs, HBA_SELTIMEOUT);
-			if (fcp->loop_seen_once) {
-				return (CMD_RQLATER);
-			} else {
-				return (CMD_COMPLETE);
-			}
-		}
-
-		/*
-		 * If we're in the middle of loop or fabric scanning
-		 * or merging the port databases, retry this command later.
-		 */
-		if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC ||
-		    fcp->isp_loopstate == LOOP_SCANNING_LOOP ||
-		    fcp->isp_loopstate == LOOP_SYNCING_PDB) {
-			return (CMD_RQLATER);
-		}
-
-		/*
-		 * If our loop state is now such that we've just now
-		 * received a Port Database Change notification, then
-		 * we have to go off and (re)scan the fabric. We back
-		 * out and try again later if this doesn't work.
-		 */
-		if (fcp->isp_loopstate == LOOP_PDB_RCVD && fcp->isp_onfabric) {
-			if (isp_scan_fabric(isp, FC4_SCSI)) {
-				return (CMD_RQLATER);
-			}
-			if (fcp->isp_fwstate != FW_READY ||
-			    fcp->isp_loopstate < LOOP_FSCAN_DONE) {
-				return (CMD_RQLATER);
-			}
-		}
-
-		/*
-		 * If our loop state is now such that we've just now
-		 * received a Port Database Change notification, then
-		 * we have to go off and (re)synchronize our port
-		 * database.
-		 */
-		if (fcp->isp_loopstate < LOOP_READY) {
-			if (isp_pdb_sync(isp)) {
-				return (CMD_RQLATER);
-			}
-			if (fcp->isp_fwstate != FW_READY ||
-			    fcp->isp_loopstate != LOOP_READY) {
-				return (CMD_RQLATER);
-			}
-		}
-
-		/*
-		 * XXX: Here's were we would cancel any loop_dead flag
-		 * XXX: also cancel in dead_loop timeout that's running
-		 */
-#endif
-
-		/*
-		 * Now check whether we should even think about pursuing this.
-		 */
-		lp = &fcp->portdb[target];
-		if (lp->valid == 0) {
+		if (XS_TGT(xs) >= MAX_FC_TARG) {
 			XS_SETERR(xs, HBA_SELTIMEOUT);
 			return (CMD_COMPLETE);
 		}
-		if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) {
-			isp_prt(isp, ISP_LOGDEBUG2,
-			    "Target %d does not have target service", target);
+
+		i = fcp->isp_ini_map[XS_TGT(xs)];
+		isp_prt(isp, ISP_LOGDEBUG1, "XS_TGT(xs)=%d- handle value %d",
+		    XS_TGT(xs), i);
+		if (i < 1 || i >= MAX_FC_TARG) {
 			XS_SETERR(xs, HBA_SELTIMEOUT);
 			return (CMD_COMPLETE);
 		}
-		/*
-		 * Now turn target into what the actual Loop ID is.
-		 */
-		target = lp->loopid;
+		target = fcp->portdb[i - 1].handle;
 	}
 
 	/*
-	 * Next check to see if any HBA or Device
-	 * parameters need to be updated.
+	 * Next check to see if any HBA or Device parameters need to be updated.
 	 */
 	if (isp->isp_update != 0) {
 		isp_update(isp);
 	}
 
+ start_again:
+
 	if (isp_getrqentry(isp, &nxti, &optr, (void *)&qep)) {
 		isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow");
 		XS_SETERR(xs, HBA_BOTCH);
@@ -3324,34 +4038,40 @@ isp_start(XS_T *xs)
 	 */
 	reqp = (ispreq_t *) local;
 	if (isp->isp_sendmarker) {
-		uint8_t n = (IS_DUALBUS(isp)? 2: 1);
-		/*
-		 * Check ports to send markers for...
-		 */
-		for (i = 0; i < n; i++) {
-			if ((isp->isp_sendmarker & (1 << i)) == 0) {
-				continue;
-			}
-			MEMZERO((void *) reqp, QENTRY_LEN);
-			reqp->req_header.rqs_entry_count = 1;
-			reqp->req_header.rqs_entry_type = RQSTYPE_MARKER;
-			reqp->req_modifier = SYNC_ALL;
-			reqp->req_target = i << 7;	/* insert bus number */
-			isp_put_request(isp, reqp, qep);
+		if (IS_24XX(isp)) {
+			isp_marker_24xx_t *m = (isp_marker_24xx_t *) qep;
+			MEMZERO(m, QENTRY_LEN);
+			m->mrk_header.rqs_entry_count = 1;
+			m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
+			m->mrk_modifier = SYNC_ALL;
+			isp_put_marker_24xx(isp, m, (isp_marker_24xx_t *)qep);
 			ISP_ADD_REQUEST(isp, nxti);
-			isp->isp_sendmarker &= ~(1 << i);
-			if (isp_getrqentry(isp, &nxti, &optr, (void *) &qep)) {
-				isp_prt(isp, ISP_LOGDEBUG0,
-				    "Request Queue Overflow+");
-				XS_SETERR(xs, HBA_BOTCH);
-				return (CMD_EAGAIN);
+			isp->isp_sendmarker = 0;
+			goto start_again;
+		} else {
+			for (i = 0; i < (IS_DUALBUS(isp)? 2: 1); i++) {
+				isp_marker_t *m = (isp_marker_t *) qep;
+				if ((isp->isp_sendmarker & (1 << i)) == 0) {
+					continue;
+				}
+				MEMZERO(m, QENTRY_LEN);
+				m->mrk_header.rqs_entry_count = 1;
+				m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
+				m->mrk_target = (i << 7);	/* bus # */
+				m->mrk_modifier = SYNC_ALL;
+				isp_put_marker(isp, m, (isp_marker_t *) qep);
+				ISP_ADD_REQUEST(isp, nxti);
+				isp->isp_sendmarker &= ~(1 << i);
+				goto start_again;
 			}
 		}
 	}
 
 	MEMZERO((void *)reqp, QENTRY_LEN);
 	reqp->req_header.rqs_entry_count = 1;
-	if (IS_FC(isp)) {
+	if (IS_24XX(isp)) {
+		reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
+	} else if (IS_FC(isp)) {
 		reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
 	} else {
 		if (XS_CDBLEN(xs) > 12)
@@ -3361,7 +4081,26 @@ isp_start(XS_T *xs)
 	}
 	/* reqp->req_header.rqs_flags = 0; */
 	/* reqp->req_header.rqs_seqno = 0; */
-	if (IS_FC(isp)) {
+	if (IS_24XX(isp)) {
+		int ttype;
+		if (XS_TAG_P(xs)) {
+			ttype = XS_TAG_TYPE(xs);
+		} else {
+			if (XS_CDBP(xs)[0] == 0x3) {
+				ttype = REQFLAG_HTAG;
+			} else {
+				ttype = REQFLAG_STAG;
+			}
+		}
+		if (ttype == REQFLAG_OTAG) {
+			ttype = FCP_CMND_TASK_ATTR_ORDERED;
+		} else if (ttype == REQFLAG_HTAG) {
+			ttype = FCP_CMND_TASK_ATTR_HEAD;
+		} else {
+			ttype = FCP_CMND_TASK_ATTR_SIMPLE;
+		}
+		((ispreqt7_t *)reqp)->req_task_attribute = ttype;
+	} else if (IS_FC(isp)) {
 		/*
 		 * See comment in isp_intr
 		 */
@@ -3392,25 +4131,47 @@ isp_start(XS_T *xs)
 			reqp->req_flags = XS_TAG_TYPE(xs);
 		}
 	}
+	cdbp = reqp->req_cdb;
+	tptr = &reqp->req_time;
+
 	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)) {
+	} else if (IS_24XX(isp)) {
+		fcportdb_t *lp;
+
+		i = FCPARAM(isp)->isp_ini_map[XS_TGT(xs)] - 1;
+		lp = &FCPARAM(isp)->portdb[i];
+
+		((ispreqt7_t *)reqp)->req_nphdl = target;
+		((ispreqt7_t *)reqp)->req_tidlo = lp->portid;
+		((ispreqt7_t *)reqp)->req_tidhi = lp->portid >> 16;
+		if (XS_LUN(xs) > 256) {
+			((ispreqt7_t *)reqp)->req_lun[0] = XS_LUN(xs) >> 8;
+			((ispreqt7_t *)reqp)->req_lun[0] |= 0x40;
+		}
+		((ispreqt7_t *)reqp)->req_lun[1] = XS_LUN(xs);
+		cdbp = ((ispreqt7_t *)reqp)->req_cdb;
+		tptr = &((ispreqt7_t *)reqp)->req_time;
+	} else if (FCPARAM(isp)->isp_2klogin) {
 		((ispreqt2e_t *)reqp)->req_target = target;
 		((ispreqt2e_t *)reqp)->req_scclun = XS_LUN(xs);
-	} else if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
+	} else if (FCPARAM(isp)->isp_sccfw) {
 		((ispreqt2_t *)reqp)->req_target = target;
 		((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs);
 	} else {
 		((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));
+	MEMCPY(cdbp, XS_CDBP(xs), XS_CDBLEN(xs));
 
-	reqp->req_time = XS_TIME(xs) / 1000;
-	if (reqp->req_time == 0 && XS_TIME(xs)) {
-		reqp->req_time = 1;
+	*tptr = XS_TIME(xs) / 1000;
+	if (*tptr == 0 && XS_TIME(xs)) {
+		*tptr = 1;
+	}
+	if (IS_24XX(isp) && *tptr > 0x1999) {
+		*tptr = 0x1999;
 	}
 
 	if (isp_save_xs(isp, xs, &handle)) {
@@ -3418,6 +4179,7 @@ isp_start(XS_T *xs)
 		XS_SETERR(xs, HBA_BOTCH);
 		return (CMD_EAGAIN);
 	}
+	/* Whew. Thankfully the same for type 7 requests */
 	reqp->req_handle = handle;
 
 	/*
@@ -3440,6 +4202,11 @@ isp_start(XS_T *xs)
 	    (long) XS_XFRLEN(xs));
 	ISP_ADD_REQUEST(isp, nxti);
 	isp->isp_nactive++;
+	if (IS_23XX(isp) || IS_24XX(isp)) {
+		if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
+			isp_intr(isp, isr, sema, mbox);
+		}
+	}
 	return (CMD_QUEUED);
 }
 
@@ -3454,7 +4221,7 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 	XS_T *xs;
 	mbreg_t mbs;
 	int bus, tgt;
-	uint16_t handle;
+	uint32_t handle;
 
 	MEMZERO(&mbs, sizeof (mbs));
 
@@ -3467,10 +4234,14 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 		/*
 		 * Issue a bus reset.
 		 */
-		mbs.param[0] = MBOX_BUS_RESET;
-		if (IS_SCSI(isp)) {
-			mbs.param[1] =
-			    ((sdparam *) isp->isp_param)->isp_bus_reset_delay;
+		if (IS_24XX(isp)) {
+			isp_prt(isp, ISP_LOGWARN, "RESET BUS NOT IMPLETENTED");
+			break;
+		} else if (IS_FC(isp)) {
+			mbs.param[1] = 10;
+			bus = 0;
+		} else {
+			mbs.param[1] = SDPARAM(isp)->isp_bus_reset_delay;
 			if (mbs.param[1] < 2) {
 				mbs.param[1] = 2;
 			}
@@ -3478,12 +4249,11 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 			if (IS_DUALBUS(isp)) {
 				mbs.param[2] = bus;
 			}
-		} else {
-			mbs.param[1] = 10;
-			bus = 0;
 		}
+		mbs.param[0] = MBOX_BUS_RESET;
 		isp->isp_sendmarker |= (1 << bus);
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			break;
 		}
@@ -3493,20 +4263,25 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 
 	case ISPCTL_RESET_DEV:
 		tgt = (*((int *) arg)) & 0xffff;
-		bus = (*((int *) arg)) >> 16;
-		mbs.param[0] = MBOX_ABORT_TARGET;
-		if (IS_SCSI(isp)) {
-			mbs.param[1] = (tgt << 8) | (bus << 15);
-		} else {
-			if (IS_2KLOGIN(isp)) {
+		if (IS_24XX(isp)) {
+			isp_prt(isp, ISP_LOGWARN, "RESET DEV NOT IMPLETENTED");
+			break;
+		} else if (IS_FC(isp)) {
+			if (FCPARAM(isp)->isp_2klogin) {
 				mbs.param[1] = tgt;
-				mbs.ibits |= (1 << 10);
+				mbs.ibits = (1 << 10);
 			} else {
 				mbs.param[1] = (tgt << 8);
 			}
+			bus = 0;
+		} else {
+			bus = (*((int *) arg)) >> 16;
+			mbs.param[1] = (bus << 15) | (tgt << 8);
 		}
+		mbs.param[0] = MBOX_ABORT_TARGET;
 		mbs.param[2] = 3;	/* 'delay', in seconds */
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			break;
 		}
@@ -3518,17 +4293,19 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 	case ISPCTL_ABORT_CMD:
 		xs = (XS_T *) arg;
 		tgt = XS_TGT(xs);
+
 		handle = isp_find_handle(isp, xs);
 		if (handle == 0) {
 			isp_prt(isp, ISP_LOGWARN,
 			    "cannot find handle for command to abort");
 			break;
 		}
-		bus = XS_CHANNEL(xs);
-		mbs.param[0] = MBOX_ABORT;
-		if (IS_FC(isp)) {
-			if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)  {
-				if (IS_2KLOGIN(isp)) {
+		if (IS_24XX(isp)) {
+			isp_prt(isp, ISP_LOGWARN, "ABORT CMD NOT IMPLETENTED");
+			break;
+		} else if (IS_FC(isp)) {
+			if (FCPARAM(isp)->isp_sccfw) {
+				if (FCPARAM(isp)->isp_2klogin) {
 					mbs.param[1] = tgt;
 				} else {
 					mbs.param[1] = tgt << 8;
@@ -3538,19 +4315,17 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 				mbs.param[1] = tgt << 8 | XS_LUN(xs);
 			}
 		} else {
-			mbs.param[1] =
-			    (bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs);
+			bus = XS_CHANNEL(xs);
+			mbs.param[1] = (bus << 15) | (tgt << 8) | XS_LUN(xs);
 		}
+		mbs.param[0] = MBOX_ABORT;
 		mbs.param[2] = handle;
-		isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_ERROR);
-		if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
-			return (0);
+		mbs.logval = MBLOGALL & ~MBOX_COMMAND_ERROR;
+		isp_mboxcmd(isp, &mbs);
+		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+			break;
 		}
-		/*
-		 * XXX: Look for command in the REQUEST QUEUE. That is,
-		 * XXX: It hasen't been picked up by firmware yet.
-		 */
-		break;
+		return (0);
 
 	case ISPCTL_UPDATE_PARAMS:
 
@@ -3571,8 +4346,7 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 	case ISPCTL_SCAN_FABRIC:
 
 		if (IS_FC(isp)) {
-			int ftype = (arg)? *((int *) arg) : FC4_SCSI;
-			return (isp_scan_fabric(isp, ftype));
+			return (isp_scan_fabric(isp));
 		}
 		break;
 
@@ -3592,37 +4366,41 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 
 	case ISPCTL_SEND_LIP:
 
-		if (IS_FC(isp)) {
+		if (IS_FC(isp) && !IS_24XX(isp)) {
 			mbs.param[0] = MBOX_INIT_LIP;
-			if (IS_2KLOGIN(isp)) {
-				mbs.ibits |= (1 << 10);
+			if (FCPARAM(isp)->isp_2klogin) {
+				mbs.ibits = (1 << 10);
 			}
-			isp_mboxcmd(isp, &mbs, MBLOGALL);
+			mbs.logval = MBLOGALL;
+			isp_mboxcmd(isp, &mbs);
 			if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
 				return (0);
 			}
 		}
 		break;
 
-	case ISPCTL_GET_POSMAP:
-
-		if (IS_FC(isp) && arg) {
-			return (isp_getmap(isp, arg));
-		}
-		break;
-
-
 	case ISPCTL_GET_PDB:
 		if (IS_FC(isp) && arg) {
 			int id = *((int *)arg);
 			isp_pdb_t *pdb = arg;
-			return (isp_getpdb(isp, id, pdb));
+			return (isp_getpdb(isp, id, pdb, 1));
 		}
 		break;
 
+	case ISPCTL_GET_PORTNAME:
+	{
+		uint64_t *wwnp = arg;
+		int loopid = *wwnp;
+		*wwnp = isp_get_portname(isp, loopid, 0);
+		if (*wwnp == (uint64_t) -1) {
+			break;
+		} else {
+			return (0);
+		}
+	}
 	case ISPCTL_RUN_MBOXCMD:
 
-		isp_mboxcmd(isp, arg, MBLOGALL);
+		isp_mboxcmd(isp, arg);
 		return(0);
 
 #ifdef	ISP_TARGET_MODE
@@ -3638,7 +4416,8 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
 			mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
 			mbs.param[1] = param & 0xffff;
 			mbs.param[2] = param >> 16;
-			isp_mboxcmd(isp, &mbs, MBLOGALL);
+			mbs.logval = MBLOGALL;
+			isp_mboxcmd(isp, &mbs);
 			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 				break;
 			}
@@ -3662,17 +4441,18 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
  * of completions on a request queue at any one time.
  */
 #ifndef	MAX_REQUESTQ_COMPLETIONS
-#define	MAX_REQUESTQ_COMPLETIONS	64
+#define	MAX_REQUESTQ_COMPLETIONS	32
 #endif
 
 void
-isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
+isp_intr(ispsoftc_t *isp, uint32_t isr, uint16_t sema, uint16_t mbox)
 {
 	XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs;
-	uint16_t iptr, optr, junk;
+	uint32_t iptr, optr, junk;
 	int i, nlooked = 0, ndone = 0;
 
 again:
+	optr = isp->isp_residx;
 	/*
 	 * Is this a mailbox related interrupt?
 	 * The mailbox semaphore will be nonzero if so.
@@ -3698,16 +4478,14 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 				MBOX_NOTIFY_COMPLETE(isp);
 			} else {
 				isp_prt(isp, ISP_LOGWARN,
-				    "Mbox Command Async (0x%x) with no waiters",
-				    mbox);
+				    "mailbox cmd (0x%x) with no waiters", mbox);
 			}
 		} else if (isp_parse_async(isp, mbox) < 0) {
 			return;
 		}
 		if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) ||
 		    isp->isp_state != ISP_RUNSTATE) {
-			ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
-			ISP_WRITE(isp, BIU_SEMA, 0);
+			goto out;
 			return;
 		}
 	}
@@ -3716,32 +4494,72 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 	 * We can't be getting this now.
 	 */
 	if (isp->isp_state != ISP_RUNSTATE) {
-		isp_prt(isp, ISP_LOGWARN,
+		isp_prt(isp, ISP_LOGINFO,
 		    "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema);
 		/*
 		 * Thank you very much!  *Burrrp*!
 		 */
-		WRITE_RESPONSE_QUEUE_OUT_POINTER(isp,
-		    READ_RESPONSE_QUEUE_IN_POINTER(isp));
-
-		ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
-		ISP_WRITE(isp, BIU_SEMA, 0);
-		return;
+		ISP_WRITE(isp, isp->isp_respoutrp,
+		    ISP_READ(isp, isp->isp_respinrp));
+		if (IS_24XX(isp)) {
+			ISP_DISABLE_INTS(isp);
+		}
+		goto out;
 	}
 
+#ifdef	ISP_TARGET_MODE
+	/*
+	 * Check for ATIO Queue entries.
+	 */
+	if (isp->isp_rspbsy == 0 && (isp->isp_role & ISP_ROLE_TARGET) &&
+	    IS_24XX(isp)) {
+		iptr = ISP_READ(isp, isp->isp_atioinrp);
+		optr = ISP_READ(isp, isp->isp_atiooutrp);
+
+		isp->isp_rspbsy = 1;
+		while (optr != iptr) {
+			uint8_t qe[QENTRY_LEN];
+			isphdr_t *hp;
+			uint32_t oop;
+			void *addr;
+
+			oop = optr;
+			MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN);
+			addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
+			isp_get_hdr(isp, addr, (isphdr_t *)qe);
+			hp = (isphdr_t *)qe;
+			switch (hp->rqs_entry_type) {
+			case RQSTYPE_NOTIFY:
+			case RQSTYPE_ATIO:
+				(void) isp_target_notify(isp, addr, &oop);
+				break;
+			default:
+				isp_print_qentry(isp, "?ATIOQ entry?",
+				    oop, addr);
+				break;
+			}
+			optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp));
+			ISP_WRITE(isp, isp->isp_atiooutrp, optr);
+		}
+		isp->isp_rspbsy = 0;
+	}
+#endif
+
 	/*
 	 * Get the current Response Queue Out Pointer.
 	 *
-	 * If we're a 2300, we can ask what hardware what it thinks.
+	 * If we're a 2300 or 2400, we can ask what hardware what it thinks.
 	 */
-	if (IS_23XX(isp)) {
+	if (IS_23XX(isp) || IS_24XX(isp)) {
 		optr = ISP_READ(isp, isp->isp_respoutrp);
 		/*
 		 * Debug: to be taken out eventually
 		 */
 		if (isp->isp_residx != optr) {
-			isp_prt(isp, ISP_LOGWARN, "optr %x soft optr %x",
+			isp_prt(isp, ISP_LOGINFO,
+			    "isp_intr: hard optr=%x, soft optr %x",
 			    optr, isp->isp_residx);
+			isp->isp_residx = optr;
 		}
 	} else {
 		optr = isp->isp_residx;
@@ -3756,19 +4574,18 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 	if (IS_2100(isp) || (IS_2300(isp) && isp->isp_revision < 2)) {
 		i = 0;
 		do {
-			iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
-			junk = READ_RESPONSE_QUEUE_IN_POINTER(isp);
+			iptr = ISP_READ(isp, isp->isp_respinrp);
+			junk = ISP_READ(isp, isp->isp_respinrp);
 		} while (junk != iptr && ++i < 1000);
 
 		if (iptr != junk) {
-			ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
 			isp_prt(isp, ISP_LOGWARN,
 			    "Response Queue Out Pointer Unstable (%x, %x)",
 			    iptr, junk);
-			return;
+			goto out;
 		}
 	} else {
-		iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
+		iptr = ISP_READ(isp, isp->isp_respinrp);
 	}
 	isp->isp_resodx = iptr;
 
@@ -3782,15 +4599,17 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 		 * make sure the old interrupt went away (to avoid 'ringing'
 		 * effects), but that didn't stop this from occurring.
 		 */
-		if (IS_23XX(isp)) {
+		if (IS_24XX(isp)) {
+			junk = 0;
+		} else if (IS_23XX(isp)) {
 			USEC_DELAY(100);
-			iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
+			iptr = ISP_READ(isp, isp->isp_respinrp);
 			junk = ISP_READ(isp, BIU_R2HSTSLO);
 		} else {
 			junk = ISP_READ(isp, BIU_ISR);
 		}
 		if (optr == iptr) {
-			if (IS_23XX(isp)) {
+			if (IS_23XX(isp) || IS_24XX(isp)) {
 				;
 			} else {
 				sema = ISP_READ(isp, BIU_SEMA);
@@ -3806,43 +4625,73 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 		}
 	}
 	isp->isp_resodx = iptr;
-	ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
-	ISP_WRITE(isp, BIU_SEMA, 0);
+
 
 	if (isp->isp_rspbsy) {
-		return;
+		goto out;
 	}
 	isp->isp_rspbsy = 1;
-
 	while (optr != iptr) {
-		ispstatusreq_t local, *sp = &local;
+		uint8_t qe[QENTRY_LEN];
+		ispstatusreq_t *sp = (ispstatusreq_t *) qe;
 		isphdr_t *hp;
-		int type;
+		int buddaboom, etype, scsi_status, completion_status;
+		int req_status_flags, req_state_flags;
+		long resid;
 		uint16_t oop;
-		int buddaboom = 0;
 
 		hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr);
 		oop = optr;
 		optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
 		nlooked++;
  read_again:
+		buddaboom = req_status_flags = req_state_flags = 0;
+		resid = 0L;
+
 		/*
 		 * Synchronize our view of this response queue entry.
 		 */
 		MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN);
+		isp_get_hdr(isp, hp, &sp->req_header);
+		etype = sp->req_header.rqs_entry_type;
 
-		type = isp_get_response_type(isp, hp);
-
-		if (type == RQSTYPE_RESPONSE) {
-			isp_get_response(isp, (ispstatusreq_t *) hp, sp);
-		} else if (type == RQSTYPE_RIO2) {
-			isp_rio2_t rio;
-			isp_get_rio2(isp, (isp_rio2_t *) hp, &rio);
-			for (i = 0; i < rio.req_header.rqs_seqno; i++) {
-				isp_fastpost_complete(isp, rio.req_handles[i]);
+		if (IS_24XX(isp) && etype == RQSTYPE_T7RQS) {
+			isp24xx_statusreq_t *sp2 = (isp24xx_statusreq_t *)qe;
+			isp_get_24xx_response(isp,
+			    (isp24xx_statusreq_t *)hp, sp2);
+			if (isp->isp_dblev & ISP_LOGDEBUG1) {
+				isp_print_bytes(isp,
+				    "Response Queue Entry", QENTRY_LEN, sp2);
+			}
+			scsi_status = sp2->req_scsi_status;
+			completion_status = sp2->req_completion_status;
+			req_state_flags = 0;
+			resid = sp2->req_resid;
+		} else if (etype == RQSTYPE_RESPONSE) {
+			isp_get_response(isp, (ispstatusreq_t *) hp, sp);
+			if (isp->isp_dblev & ISP_LOGDEBUG1) {
+				isp_print_bytes(isp,
+				    "Response Queue Entry", QENTRY_LEN, sp);
+			}
+			scsi_status = sp->req_scsi_status;
+			completion_status = sp->req_completion_status;
+			req_status_flags = sp->req_status_flags;
+			req_state_flags = sp->req_state_flags;
+			resid = sp->req_resid;
+		} else if (etype == RQSTYPE_RIO2) {
+			isp_rio2_t *rio = (isp_rio2_t *)qe;
+			isp_get_rio2(isp, (isp_rio2_t *) hp, rio);
+			if (isp->isp_dblev & ISP_LOGDEBUG1) {
+				isp_print_bytes(isp,
+				    "Response Queue Entry", QENTRY_LEN, rio);
+			}
+			for (i = 0; i < rio->req_header.rqs_seqno; i++) {
+				isp_fastpost_complete(isp, rio->req_handles[i]);
+			}
+			if (isp->isp_fpcchiwater < rio->req_header.rqs_seqno) {
+				isp->isp_fpcchiwater =
+				    rio->req_header.rqs_seqno;
 			}
-			if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno)
-				isp->isp_fpcchiwater = rio.req_header.rqs_seqno;
 			MEMZERO(hp, QENTRY_LEN);	/* PERF */
 			continue;
 		} else {
@@ -3851,10 +4700,12 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 			 * may have updated the response queue pointers for
 			 * us, so we reload our goal index.
 			 */
-			int i = isp_handle_other_response(isp, type, hp, &optr);
-			if (i < 0) {
+			int r;
+			r = isp_handle_other_response(isp, etype, hp, &optr);
+			if (r < 0) {
 				goto read_again;
-			} else if (i > 0) {
+			}
+			if (r > 0) {
 				iptr = isp->isp_resodx;
 				MEMZERO(hp, QENTRY_LEN);	/* PERF */
 				continue;
@@ -3865,34 +4716,33 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 			 * we don't know how to deal with the rest of the
 			 * response.
 			 */
-			isp_get_response(isp, (ispstatusreq_t *) hp, sp);
 
 			/*
 			 * It really has to be a bounced request just copied
 			 * from the request queue to the response queue. If
 			 * not, something bad has happened.
 			 */
-			if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) {
+			if (etype != RQSTYPE_REQUEST) {
 				isp_prt(isp, ISP_LOGERR, notresp,
-				    sp->req_header.rqs_entry_type, oop, optr,
-				    nlooked);
-				if (isp->isp_dblev & ISP_LOGDEBUG0) {
-					isp_print_bytes(isp, "Queue Entry",
-					    QENTRY_LEN, sp);
-				}
+				    etype, oop, optr, nlooked);
+				isp_print_bytes(isp,
+				    "Reqeonse Queue Entry", QENTRY_LEN, sp);
 				MEMZERO(hp, QENTRY_LEN);	/* PERF */
 				continue;
 			}
 			buddaboom = 1;
+			scsi_status = sp->req_scsi_status;
+			completion_status = sp->req_completion_status;
+			req_status_flags = sp->req_status_flags;
+			req_state_flags = sp->req_state_flags;
+			resid = sp->req_resid;
 		}
 
-		if (sp->req_header.rqs_flags & 0xf) {
-#define	_RQS_OFLAGS	\
-	~(RQSFLAG_CONTINUATION|RQSFLAG_FULL|RQSFLAG_BADHEADER|RQSFLAG_BADPACKET)
+		if (sp->req_header.rqs_flags & RQSFLAG_MASK) {
 			if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
 				isp_prt(isp, ISP_LOGWARN,
 				    "continuation segment");
-				WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
+				ISP_WRITE(isp, isp->isp_respoutrp, optr);
 				continue;
 			}
 			if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
@@ -3903,53 +4753,47 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 				 */
 			}
 			if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {
-				isp_prt(isp, ISP_LOGERR,  "bad header flag");
+				isp_print_bytes(isp, "bad header flag",
+				    QENTRY_LEN, sp);
 				buddaboom++;
 			}
 			if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {
-				isp_prt(isp, ISP_LOGERR, "bad request packet");
+				isp_print_bytes(isp, "bad request packet",
+				    QENTRY_LEN, sp);
 				buddaboom++;
 			}
-			if (sp->req_header.rqs_flags & _RQS_OFLAGS) {
-				isp_prt(isp, ISP_LOGERR,
-				    "unknown flags (0x%x) in response",
-				    sp->req_header.rqs_flags);
-				buddaboom++;
-			}
-#undef	_RQS_OFLAGS
 		}
+
 		if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) {
-			MEMZERO(hp, QENTRY_LEN);	/* PERF */
 			isp_prt(isp, ISP_LOGERR,
-			    "bad request handle %d (type 0x%x, flags 0x%x)",
-			    sp->req_handle, sp->req_header.rqs_entry_type,
-			    sp->req_header.rqs_flags);
-			WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
+			    "bad request handle %d (type 0x%x)",
+			    sp->req_handle, etype);
+			MEMZERO(hp, QENTRY_LEN);	/* PERF */
+			ISP_WRITE(isp, isp->isp_respoutrp, optr);
 			continue;
 		}
 		xs = isp_find_xs(isp, sp->req_handle);
 		if (xs == NULL) {
-			uint8_t ts = sp->req_completion_status & 0xff;
-			MEMZERO(hp, QENTRY_LEN);	/* PERF */
+			uint8_t ts = completion_status & 0xff;
 			/*
 			 * Only whine if this isn't the expected fallout of
 			 * aborting the command.
 			 */
-			if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) {
+			if (etype != RQSTYPE_RESPONSE) {
 				isp_prt(isp, ISP_LOGERR,
 				    "cannot find handle 0x%x (type 0x%x)",
-				    sp->req_handle,
-				    sp->req_header.rqs_entry_type);
+				    sp->req_handle, etype);
 			} else if (ts != RQCS_ABORTED) {
 				isp_prt(isp, ISP_LOGERR,
 				    "cannot find handle 0x%x (status 0x%x)",
 				    sp->req_handle, ts);
 			}
-			WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
+			MEMZERO(hp, QENTRY_LEN);	/* PERF */
+			ISP_WRITE(isp, isp->isp_respoutrp, optr);
 			continue;
 		}
 		isp_destroy_handle(isp, sp->req_handle);
-		if (sp->req_status_flags & RQSTF_BUS_RESET) {
+		if (req_status_flags & RQSTF_BUS_RESET) {
 			XS_SETERR(xs, HBA_BUSRESET);
 			isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
 		}
@@ -3957,31 +4801,37 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 			XS_SETERR(xs, HBA_BOTCH);
 		}
 
-		if (IS_FC(isp) && (sp->req_scsi_status & RQCS_SV)) {
+		if (IS_FC(isp) && (scsi_status & RQCS_SV) != 0) {
 			/*
 			 * Fibre Channel F/W doesn't say we got status
 			 * if there's Sense Data instead. I guess they
 			 * think it goes w/o saying.
 			 */
-			sp->req_state_flags |= RQSF_GOT_STATUS;
+			req_state_flags |= RQSF_GOT_STATUS;
 		}
-		if (sp->req_state_flags & RQSF_GOT_STATUS) {
-			*XS_STSP(xs) = sp->req_scsi_status & 0xff;
+		if (req_state_flags & RQSF_GOT_STATUS) {
+			*XS_STSP(xs) = scsi_status & 0xff;
 		}
 
-		switch (sp->req_header.rqs_entry_type) {
+		switch (etype) {
 		case RQSTYPE_RESPONSE:
+			/* XXX won't work for 24xx */
 			XS_SET_STATE_STAT(isp, xs, sp);
-			isp_parse_status(isp, sp, xs);
+			if (IS_24XX(isp)) {
+				isp_parse_status_24xx(isp,
+				    (isp24xx_statusreq_t *)sp, xs, &resid);
+			} else {
+				isp_parse_status(isp, (void *)sp, xs, &resid);
+			}
 			if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
 			    (*XS_STSP(xs) == SCSI_BUSY)) {
 				XS_SETERR(xs, HBA_TGTBSY);
 			}
 			if (IS_SCSI(isp)) {
-				XS_RESID(xs) = sp->req_resid;
-				if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
+				XS_RESID(xs) = resid;
+				if ((req_state_flags & RQSF_GOT_STATUS) &&
 				    (*XS_STSP(xs) == SCSI_CHECK) &&
-				    (sp->req_state_flags & RQSF_GOT_SENSE)) {
+				    (req_state_flags & RQSF_GOT_SENSE)) {
 					XS_SAVE_SENSE(xs, sp);
 				}
 				/*
@@ -3989,7 +4839,7 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 				 * this target. Mark state such that we'll go
 				 * look up that which has changed later.
 				 */
-				if (sp->req_status_flags & RQSTF_NEGOTIATION) {
+				if (req_status_flags & RQSTF_NEGOTIATION) {
 					int t = XS_TGT(xs);
 					sdparam *sdp = isp->isp_param;
 					sdp += XS_CHANNEL(xs);
@@ -3998,27 +4848,30 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 					    (1 << XS_CHANNEL(xs));
 				}
 			} else {
-				if (sp->req_status_flags & RQSF_XFER_COMPLETE) {
+				if (req_status_flags & RQSF_XFER_COMPLETE) {
 					XS_RESID(xs) = 0;
-				} else if (sp->req_scsi_status & RQCS_RESID) {
-					XS_RESID(xs) = sp->req_resid;
+				} else if (scsi_status & RQCS_RESID) {
+					XS_RESID(xs) = resid;
 				} else {
 					XS_RESID(xs) = 0;
 				}
-				if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
+				if ((req_state_flags & RQSF_GOT_STATUS) &&
 				    (*XS_STSP(xs) == SCSI_CHECK) &&
-				    (sp->req_scsi_status & RQCS_SV)) {
+				    (scsi_status & RQCS_SV)) {
 					XS_SAVE_SENSE(xs, sp);
 					/* solely for the benefit of debug */
-					sp->req_state_flags |= RQSF_GOT_SENSE;
+					req_state_flags |= RQSF_GOT_SENSE;
 				}
 			}
 			isp_prt(isp, ISP_LOGDEBUG2,
 			   "asked for %ld got raw resid %ld settled for %ld",
-			    (long) XS_XFRLEN(xs), (long) sp->req_resid,
-			    (long) XS_RESID(xs));
+			    (long) XS_XFRLEN(xs), resid, (long) XS_RESID(xs));
 			break;
 		case RQSTYPE_REQUEST:
+		case RQSTYPE_A64:
+		case RQSTYPE_T2RQS:
+		case RQSTYPE_T3RQS:
+		case RQSTYPE_T7RQS:
 			if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
 				/*
 				 * Force Queue Full status.
@@ -4029,16 +4882,19 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 				/*
 				 * ????
 				 */
+				XS_SETERR(xs, HBA_BOTCH);
 				isp_prt(isp, ISP_LOGDEBUG0,
 				    "Request Queue Entry bounced back");
-				XS_SETERR(xs, HBA_BOTCH);
+				if ((isp->isp_dblev & ISP_LOGDEBUG1) == 0) {
+					isp_print_bytes(isp, "Bounced Request",
+					    QENTRY_LEN, qe);
+				}
 			}
 			XS_RESID(xs) = XS_XFRLEN(xs);
 			break;
 		default:
-			isp_prt(isp, ISP_LOGWARN,
-			    "unhandled response queue type 0x%x",
-			    sp->req_header.rqs_entry_type);
+			isp_print_bytes(isp, "Unhandled Response Type",
+			    QENTRY_LEN, qe);
 			if (XS_NOERR(xs)) {
 				XS_SETERR(xs, HBA_BOTCH);
 			}
@@ -4056,7 +4912,7 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 		    ((isp->isp_dblev & ISP_LOGDEBUG1) && ((!XS_NOERR(xs)) ||
 		    (*XS_STSP(xs) != SCSI_GOOD)))) {
 			char skey;
-			if (sp->req_state_flags & RQSF_GOT_SENSE) {
+			if (req_state_flags & RQSF_GOT_SENSE) {
 				skey = XS_SNSKEY(xs) & 0xf;
 				if (skey < 10)
 					skey += '0';
@@ -4087,13 +4943,23 @@ isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox)
 	 * ISP's notion of what we've seen so far.
 	 */
 	if (nlooked) {
-		WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
+		ISP_WRITE(isp, isp->isp_respoutrp, optr);
 		/*
 		 * While we're at it, read the requst queue out pointer.
 		 */
-		isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp);
-		if (isp->isp_rscchiwater < ndone)
+		isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
+		if (isp->isp_rscchiwater < ndone) {
 			isp->isp_rscchiwater = ndone;
+		}
+	}
+
+out:
+
+	if (IS_24XX(isp)) {
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
+	} else {
+		ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
+		ISP_WRITE(isp, BIU_SEMA, 0);
 	}
 
 	isp->isp_residx = optr;
@@ -4128,8 +4994,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 	case ASYNC_BUS_RESET:
 		isp->isp_sendmarker |= (1 << bus);
 #ifdef	ISP_TARGET_MODE
-		if (isp_target_async(isp, bus, mbox))
+		if (isp_target_async(isp, bus, mbox)) {
 			rval = -1;
+		}
 #endif
 		isp_async(isp, ISPASYNC_BUS_RESET, &bus);
 		break;
@@ -4179,7 +5046,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 		 * We don't need to be chatty about this- just unlatch things
 		 * and move on.
 		 */
-		mbox = READ_REQUEST_QUEUE_OUT_POINTER(isp);
+		mbox = ISP_READ(isp, isp->isp_rqstoutrp);
 		break;
 
 	case ASYNC_TIMEOUT_RESET:
@@ -4187,8 +5054,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 		    "timeout initiated SCSI bus reset of bus %d", bus);
 		isp->isp_sendmarker |= (1 << bus);
 #ifdef	ISP_TARGET_MODE
-		if (isp_target_async(isp, bus, mbox))
+		if (isp_target_async(isp, bus, mbox)) {
 			rval = -1;
+		}
 #endif
 		break;
 
@@ -4196,8 +5064,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 		isp_prt(isp, ISP_LOGINFO, "device reset on bus %d", bus);
 		isp->isp_sendmarker |= (1 << bus);
 #ifdef	ISP_TARGET_MODE
-		if (isp_target_async(isp, bus, mbox))
+		if (isp_target_async(isp, bus, mbox)) {
 			rval = -1;
+		}
 #endif
 		break;
 
@@ -4300,16 +5169,18 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 #endif
 		break;
 	}
+	case ASYNC_LIP_ERROR:
 	case ASYNC_LIP_F8:
 	case ASYNC_LIP_OCCURRED:
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
 		isp->isp_sendmarker = 1;
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		isp_async(isp, ISPASYNC_LIP, NULL);
 #ifdef	ISP_TARGET_MODE
-		if (isp_target_async(isp, bus, mbox))
+		if (isp_target_async(isp, bus, mbox)) {
 			rval = -1;
+		}
 #endif
 		/*
 		 * We've had problems with data corruption occuring on
@@ -4340,7 +5211,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		isp_async(isp, ISPASYNC_LOOP_UP, NULL);
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_async(isp, bus, mbox)) {
@@ -4353,7 +5224,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_NIL;
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		isp_async(isp, ISPASYNC_LOOP_DOWN, NULL);
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_async(isp, bus, mbox)) {
@@ -4366,7 +5237,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_NIL;
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		isp_async(isp, ISPASYNC_LOOP_RESET, NULL);
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_async(isp, bus, mbox)) {
@@ -4378,39 +5249,37 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 	case ASYNC_PDB_CHANGED:
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB);
 		break;
 
 	case ASYNC_CHANGE_NOTIFY:
-		/*
-		 * Not correct, but it will force us to rescan the loop.
-		 */
-		FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
-		isp_mark_getpdb_all(isp);
+	    	if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) {
+			FCPARAM(isp)->isp_loopstate = LOOP_LSCAN_DONE;
+		} else {
+			FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
+		}
+		isp_mark_portdb(isp, 1);
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS);
 		break;
 
 	case ASYNC_PTPMODE:
-		if (FCPARAM(isp)->isp_onfabric)
-			FCPARAM(isp)->isp_topo = TOPO_F_PORT;
-		else
-			FCPARAM(isp)->isp_topo = TOPO_N_PORT;
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
 #ifdef	ISP_TARGET_MODE
-		if (isp_target_async(isp, bus, mbox))
+		if (isp_target_async(isp, bus, mbox)) {
 			rval = -1;
+		}
 #endif
 		isp_prt(isp, ISP_LOGINFO, "Point-to-Point mode");
 		break;
 
 	case ASYNC_CONNMODE:
 		mbox = ISP_READ(isp, OUTMAILBOX1);
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		switch (mbox) {
 		case ISP_CONN_LOOP:
 			isp_prt(isp, ISP_LOGINFO,
@@ -4449,6 +5318,15 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 		FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
 		break;
 
+	case ASYNC_RJT_SENT:	/* same as ASYNC_QFULL_SENT */
+		if (IS_24XX(isp)) {
+			isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
+			break;
+		} else if (IS_2200(isp)) {
+			isp_prt(isp, ISP_LOGTDEBUG0, "QFULL sent");
+			break;
+		}
+		/* FALLTHROUGH */
 	default:
 		isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
 		break;
@@ -4469,8 +5347,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 			isp_prt(isp,  ISP_LOGDEBUG3,
 			    "fast post completion of %u", handles[i]);
 		}
-		if (isp->isp_fpcchiwater < nh)
+		if (isp->isp_fpcchiwater < nh) {
 			isp->isp_fpcchiwater = nh;
+		}
 	} else {
 		isp->isp_intoasync++;
 	}
@@ -4485,11 +5364,14 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
 
 static int
 isp_handle_other_response(ispsoftc_t *isp, int type,
-    isphdr_t *hp, uint16_t *optrp)
+    isphdr_t *hp, uint32_t *optrp)
 {
 	switch (type) {
 	case RQSTYPE_STATUS_CONT:
-		isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response");
+		isp_prt(isp, ISP_LOGDEBUG0, "Ignored Continuation Response");
+		return (1);
+	case RQSTYPE_MARKER:
+		isp_prt(isp, ISP_LOGDEBUG0, "Marker Response");
 		return (1);
 	case RQSTYPE_ATIO:
 	case RQSTYPE_CTIO:
@@ -4501,6 +5383,9 @@ isp_handle_other_response(ispsoftc_t *isp, int type,
 	case RQSTYPE_ATIO2:
 	case RQSTYPE_CTIO2:
 	case RQSTYPE_CTIO3:
+	case RQSTYPE_CTIO7:
+	case RQSTYPE_ABTS_RCVD:
+	case RQSTYPE_ABTS_RSP:
 		isp->isp_rsltccmplt++;	/* count as a response completion */
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) {
@@ -4534,7 +5419,7 @@ isp_handle_other_response(ispsoftc_t *isp, int type,
 }
 
 static void
-isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
+isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
 {
 	switch (sp->req_completion_status & 0xff) {
 	case RQCS_COMPLETE:
@@ -4550,6 +5435,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 			    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
 			if (XS_NOERR(xs)) {
 				XS_SETERR(xs, HBA_SELTIMEOUT);
+				*rp = XS_XFRLEN(xs);
 			}
 			return;
 		}
@@ -4562,6 +5448,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 	case RQCS_DMA_ERROR:
 		isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d",
 		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+		*rp = XS_XFRLEN(xs);
 		break;
 
 	case RQCS_TRANSPORT_ERROR:
@@ -4617,6 +5504,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 		isp_prt(isp, ISP_LOGERR, "%s", buf);
 		isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s",
 		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), buf);
+		*rp = XS_XFRLEN(xs);
 		break;
 	}
 	case RQCS_RESET_OCCURRED:
@@ -4627,6 +5515,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 		if (XS_NOERR(xs)) {
 			XS_SETERR(xs, HBA_BUSRESET);
 		}
+		*rp = XS_XFRLEN(xs);
 		return;
 
 	case RQCS_ABORTED:
@@ -4642,15 +5531,8 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 		isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d",
 		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
 		/*
-	 	 * Check to see if we logged out the device.
+	 	 * XXX: Check to see if we logged out of the device.
 		 */
-		if (IS_FC(isp)) {
-			if ((sp->req_completion_status & RQSTF_LOGOUT) &&
-			    FCPARAM(isp)->portdb[XS_TGT(xs)].valid &&
-			    FCPARAM(isp)->portdb[XS_TGT(xs)].fabric_dev) {
-				FCPARAM(isp)->portdb[XS_TGT(xs)].relogin = 1;
-			}
-		}
 		if (XS_NOERR(xs)) {
 			XS_SETERR(xs, HBA_CMDTIMEOUT);
 		}
@@ -4857,28 +5739,36 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 		 * No such port on the loop. Moral equivalent of SELTIMEO
 		 */
 	case RQCS_PORT_LOGGED_OUT:
+	{
+		char *reason;
+		uint8_t sts = sp->req_completion_status & 0xff;
+
 		/*
 		 * It was there (maybe)- treat as a selection timeout.
 		 */
-		if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE)
-			isp_prt(isp, ISP_LOGINFO,
-			    "port unavailable for target %d", XS_TGT(xs));
-		else
-			isp_prt(isp, ISP_LOGINFO,
-			    "port logout for target %d", XS_TGT(xs));
+		if (sts == RQCS_PORT_UNAVAILABLE) {
+			reason = "unavailable";
+		} else {
+			reason = "logout";
+		}
+
+		isp_prt(isp, ISP_LOGINFO, "port %s for target %d",
+		    reason, XS_TGT(xs));
+
 		/*
 		 * If we're on a local loop, force a LIP (which is overkill)
 		 * to force a re-login of this unit. If we're on fabric,
-		 * then we'll have to relogin as a matter of course.
+		 * then we'll have to log in again as a matter of course.
 		 */
 		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;
-			if (IS_2KLOGIN(isp)) {
-				mbs.ibits |= (1 << 10);
+			if (FCPARAM(isp)->isp_2klogin) {
+				mbs.ibits = (1 << 10);
 			}
+			mbs.logval = MBLOGALL;
 			isp_mboxcmd_qnw(isp, &mbs, 1);
 		}
 
@@ -4887,13 +5777,13 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 		 */
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 1);
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
 		if (XS_NOERR(xs)) {
 			XS_SETERR(xs, HBA_SELTIMEOUT);
 		}
 		return;
-
+	}
 	case RQCS_PORT_CHANGED:
 		isp_prt(isp, ISP_LOGWARN,
 		    "port changed for target %d", XS_TGT(xs));
@@ -4920,6 +5810,176 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
 	}
 }
 
+static void
+isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
+    XS_T *xs, long *rp)
+{
+	switch (sp->req_completion_status) {
+	case RQCS_COMPLETE:
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_NOERROR);
+		}
+		return;
+
+	case RQCS_DMA_ERROR:
+		isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d",
+		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+		break;
+
+	case RQCS_TRANSPORT_ERROR:
+		isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d",
+		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+		break;
+
+	case RQCS_RESET_OCCURRED:
+		isp_prt(isp, ISP_LOGWARN,
+		    "bus reset destroyed command for %d.%d.%d",
+		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+		isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_BUSRESET);
+		}
+		return;
+
+	case RQCS_ABORTED:
+		isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d",
+		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+		isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_ABORTED);
+		}
+		return;
+
+	case RQCS_TIMEOUT:
+		isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d",
+		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_CMDTIMEOUT);
+		}
+		return;
+
+	case RQCS_DATA_OVERRUN:
+		XS_RESID(xs) = sp->req_resid;
+		isp_prt(isp, ISP_LOGERR, "data overrun for command on %d.%d.%d",
+		    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_DATAOVR);
+		}
+		return;
+
+	case RQCS_24XX_DRE:	/* data reassembly error */
+		isp_prt(isp, ISP_LOGERR, "data reassembly error for target %d",
+		    XS_TGT(xs));
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_ABORTED);
+		}
+		*rp = XS_XFRLEN(xs);
+		return;
+
+	case RQCS_24XX_TABORT:	/* aborted by target */
+		isp_prt(isp, ISP_LOGERR, "target %d sent ABTS",
+		    XS_TGT(xs));
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_ABORTED);
+		}
+		return;
+
+	case RQCS_DATA_UNDERRUN:
+
+		XS_RESID(xs) = sp->req_resid;
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_NOERROR);
+		}
+		return;
+
+	case RQCS_PORT_UNAVAILABLE:
+		/*
+		 * No such port on the loop. Moral equivalent of SELTIMEO
+		 */
+	case RQCS_PORT_LOGGED_OUT:
+	{
+		char *reason;
+		uint8_t sts = sp->req_completion_status & 0xff;
+
+		/*
+		 * It was there (maybe)- treat as a selection timeout.
+		 */
+		if (sts == RQCS_PORT_UNAVAILABLE) {
+			reason = "unavailable";
+		} else {
+			reason = "logout";
+		}
+
+		isp_prt(isp, ISP_LOGINFO, "port %s for target %d",
+		    reason, XS_TGT(xs));
+
+		/*
+		 * If we're on a local loop, force a LIP (which is overkill)
+		 * to force a re-login of this unit. If we're on fabric,
+		 * then we'll have to log in again as a matter of course.
+		 */
+		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;
+			if (FCPARAM(isp)->isp_2klogin) {
+				mbs.ibits = (1 << 10);
+			}
+			mbs.logval = MBLOGALL;
+			isp_mboxcmd_qnw(isp, &mbs, 1);
+		}
+
+		/*
+		 * Probably overkill.
+		 */
+		isp->isp_sendmarker = 1;
+		FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
+		isp_mark_portdb(isp, 1);
+		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_SELTIMEOUT);
+		}
+		return;
+	}
+	case RQCS_PORT_CHANGED:
+		isp_prt(isp, ISP_LOGWARN,
+		    "port changed for target %d", XS_TGT(xs));
+		if (XS_NOERR(xs)) {
+			XS_SETERR(xs, HBA_SELTIMEOUT);
+		}
+		return;
+
+
+	case RQCS_24XX_ENOMEM:	/* f/w resource unavailable */
+		isp_prt(isp, ISP_LOGWARN,
+		    "f/w resource unavailable for target %d", XS_TGT(xs));
+		if (XS_NOERR(xs)) {
+			*XS_STSP(xs) = SCSI_BUSY;
+			XS_SETERR(xs, HBA_TGTBSY);
+		}
+		return;
+
+	case RQCS_24XX_TMO:	/* task management overrun */
+		isp_prt(isp, ISP_LOGWARN,
+		    "command for target %d overlapped task management",
+		    XS_TGT(xs));
+		if (XS_NOERR(xs)) {
+			*XS_STSP(xs) = SCSI_BUSY;
+			XS_SETERR(xs, HBA_TGTBSY);
+		}
+		return;
+
+	default:
+		isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x",
+		    sp->req_completion_status);
+		break;
+	}
+	if (XS_NOERR(xs)) {
+		XS_SETERR(xs, HBA_BOTCH);
+	}
+}
+
 static void
 isp_fastpost_complete(ispsoftc_t *isp, uint16_t fph)
 {
@@ -4977,8 +6037,12 @@ isp_mbox_continue(ispsoftc_t *isp)
 	/*
 	 * Clear the previous interrupt.
 	 */
-	ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
-	ISP_WRITE(isp, BIU_SEMA, 0);
+	if (IS_24XX(isp)) {
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
+	} else {
+		ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
+		ISP_WRITE(isp, BIU_SEMA, 0);
+	}
 
 	/*
 	 * Continue with next word.
@@ -4996,7 +6060,7 @@ isp_mbox_continue(ispsoftc_t *isp)
 		break;
 	case MBOX_WRITE_RAM_WORD_EXTENDED:
 		offset = isp->isp_mbxwrk1;
-		offset |= ((uint32_t) isp->isp_mbxwrk8 << 16);
+		offset |= isp->isp_mbxwrk8 << 16;
 
 		mbs.param[2] = *ptr++;;
 		mbs.param[1] = offset;
@@ -5006,7 +6070,7 @@ isp_mbox_continue(ispsoftc_t *isp)
 		break;
 	case MBOX_READ_RAM_WORD_EXTENDED:
 		offset = isp->isp_mbxwrk1;
-		offset |= ((uint32_t) isp->isp_mbxwrk8 << 16);
+		offset |= isp->isp_mbxwrk8 << 16;
 
 		*ptr++ = isp->isp_mboxtmp[2];
 		mbs.param[1] = offset;
@@ -5018,11 +6082,11 @@ isp_mbox_continue(ispsoftc_t *isp)
 	isp->isp_mbxworkp = ptr;
 	isp->isp_mbxwrk0--;
 	mbs.param[0] = isp->isp_lastmbxcmd;
+	mbs.logval = MBLOGALL;
 	isp_mboxcmd_qnw(isp, &mbs, 0);
 	return (0);
 }
 
-
 #define	HIWRD(x)			((x) >> 16)
 #define	LOWRD(x)			((x)  & 0xffff)
 #define	ISPOPMAP(a, b)			(((a) << 16) | (b))
@@ -5111,7 +6175,7 @@ static const uint32_t mbpscsi[] = {
 	ISPOPMAP(0xdf, 0xdf),	/* 0x51: DUMP RAM A64 */
 	ISPOPMAP(0xdf, 0xff),	/* 0x52: INITIALIZE REQUEST QUEUE A64 */
 	ISPOPMAP(0xef, 0xff),	/* 0x53: INITIALIZE RESPONSE QUEUE A64 */
-	ISPOPMAP(0xcf, 0x01),	/* 0x54: EXECUTE IOCB A64 */
+	ISPOPMAP(0xcf, 0x01),	/* 0x54: EXECUCUTE COMMAND IOCB A64 */
 	ISPOPMAP(0x07, 0x01),	/* 0x55: ENABLE TARGET MODE */
 	ISPOPMAP(0x03, 0x0f),	/* 0x56: GET TARGET STATUS */
 	ISPOPMAP(0x00, 0x00),	/* 0x57: */
@@ -5123,7 +6187,6 @@ static const uint32_t mbpscsi[] = {
 	ISPOPMAP(0x01, 0x01)	/* 0x5d: GET NOST DATA */
 };
 
-#ifndef	ISP_STRIPPED
 static char *scsi_mbcmd_names[] = {
 	"NO-OP",
 	"LOAD RAM",
@@ -5220,23 +6283,22 @@ static char *scsi_mbcmd_names[] = {
 	"SET HOST DATA",
 	"GET NOST DATA",
 };
-#endif
 
 static const uint32_t mbpfc[] = {
 	ISPOPMAP(0x01, 0x01),	/* 0x00: MBOX_NO_OP */
 	ISPOPMAP(0x1f, 0x01),	/* 0x01: MBOX_LOAD_RAM */
-	ISPOPMAP(0x07, 0x01),	/* 0x02: MBOX_EXEC_FIRMWARE */
+	ISPOPMAP(0x0f, 0x01),	/* 0x02: MBOX_EXEC_FIRMWARE */
 	ISPOPMAP(0xdf, 0x01),	/* 0x03: MBOX_DUMP_RAM */
 	ISPOPMAP(0x07, 0x07),	/* 0x04: MBOX_WRITE_RAM_WORD */
 	ISPOPMAP(0x03, 0x07),	/* 0x05: MBOX_READ_RAM_WORD */
 	ISPOPMAP(0xff, 0xff),	/* 0x06: MBOX_MAILBOX_REG_TEST */
-	ISPOPMAP(0x03, 0x05),	/* 0x07: MBOX_VERIFY_CHECKSUM	*/
+	ISPOPMAP(0x03, 0x07),	/* 0x07: MBOX_VERIFY_CHECKSUM	*/
 	ISPOPMAP(0x01, 0x4f),	/* 0x08: MBOX_ABOUT_FIRMWARE */
 	ISPOPMAP(0xdf, 0x01),	/* 0x09: LOAD RAM */
 	ISPOPMAP(0xdf, 0x01),	/* 0x0a: DUMP RAM */
-	ISPOPMAP(0x00, 0x00),	/* 0x0b: */
+	ISPOPMAP(0x1ff, 0x01),	/* 0x0b: MBOX_LOAD_RISC_RAM */
 	ISPOPMAP(0x00, 0x00),	/* 0x0c: */
-	ISPOPMAP(0x10f, 0x01),	/* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED) */
+	ISPOPMAP(0x10f, 0x01),	/* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
 	ISPOPMAP(0x01, 0x05),	/* 0x0e: MBOX_CHECK_FIRMWARE */
 	ISPOPMAP(0x10f, 0x05),	/* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
 	ISPOPMAP(0x1f, 0x11),	/* 0x10: MBOX_INIT_REQ_QUEUE */
@@ -5289,8 +6351,8 @@ static const uint32_t mbpfc[] = {
 	ISPOPMAP(0x00, 0x00),	/* 0x3f: */
 	ISPOPMAP(0x03, 0x01),	/* 0x40: MBOX_LOOP_PORT_BYPASS */
 	ISPOPMAP(0x03, 0x01),	/* 0x41: MBOX_LOOP_PORT_ENABLE */
-	ISPOPMAP(0x03, 0x07),	/* 0x42: MBOX_GET_RESOURCE_COUNTS */
-	ISPOPMAP(0x01, 0x01),	/* 0x43: MBOX_REQUEST_NON_PARTICIPATING_MODE */
+	ISPOPMAP(0x03, 0x07),	/* 0x42: MBOX_GET_RESOURCE_COUNT */
+	ISPOPMAP(0x01, 0x01),	/* 0x43: MBOX_REQUEST_OFFLINE_MODE */
 	ISPOPMAP(0x00, 0x00),	/* 0x44: */
 	ISPOPMAP(0x00, 0x00),	/* 0x45: */
 	ISPOPMAP(0x00, 0x00),	/* 0x46: */
@@ -5319,7 +6381,7 @@ static const uint32_t mbpfc[] = {
 	ISPOPMAP(0x07, 0x03),	/* 0x5d: MBOX_GET_SET_DATA_RATE */
 	ISPOPMAP(0x00, 0x00),	/* 0x5e: */
 	ISPOPMAP(0x00, 0x00),	/* 0x5f: */
-	ISPOPMAP(0xcd, 0x31),	/* 0x60: MBOX_INIT_FIRMWARE */
+	ISPOPMAP(0xcd, 0x01),	/* 0x60: MBOX_INIT_FIRMWARE */
 	ISPOPMAP(0x00, 0x00),	/* 0x61: */
 	ISPOPMAP(0x01, 0x01),	/* 0x62: MBOX_INIT_LIP */
 	ISPOPMAP(0xcd, 0x03),	/* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
@@ -5360,7 +6422,6 @@ static const uint32_t mbpfc[] = {
  *	is that we won't overflow.
  */
 
-#ifndef	ISP_STRIPPED
 static char *fc_mbcmd_names[] = {
 	"NO-OP",
 	"LOAD RAM",
@@ -5428,7 +6489,7 @@ static char *fc_mbcmd_names[] = {
 	NULL,
 	"LOOP PORT BYPASS",
 	"LOOP PORT ENABLE",
-	"GET RESOURCE COUNTS",
+	"GET RESOURCE COUNT",
 	"REQUEST NON PARTICIPATING MODE",
 	NULL,
 	NULL,
@@ -5490,7 +6551,6 @@ static char *fc_mbcmd_names[] = {
 	"SEND LFA",
 	"Lun RESET"
 };
-#endif
 
 static void
 isp_mboxcmd_qnw(ispsoftc_t *isp, mbreg_t *mbp, int nodelay)
@@ -5521,19 +6581,23 @@ isp_mboxcmd_qnw(ispsoftc_t *isp, mbreg_t *mbp, int nodelay)
 		isp->isp_obits = obits;
 		isp->isp_mboxbsy = 1;
 	}
-	ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
+	if (IS_24XX(isp)) {
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
+	} else {
+		ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
+	}
 	/*
 	 * Oddly enough, if we're not delaying for an answer,
 	 * delay a bit to give the f/w a chance to pick up the
 	 * command.
 	 */
 	if (nodelay) {
-		USEC_DELAY(100);
+		USEC_DELAY(1000);
 	}
 }
 
 static void
-isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask)
+isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
 {
 	char *cname, *xname, tname[16], mname[16];
 	unsigned int lim, ibits, obits, box, opcode;
@@ -5571,11 +6635,14 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask)
 	/*
 	 * Get exclusive usage of mailbox registers.
 	 */
-	MBOX_ACQUIRE(isp);
+	if (MBOX_ACQUIRE(isp)) {
+		mbp->param[0] = MBOX_REGS_BUSY;
+		goto out;
+	}
 
 	for (box = 0; box < MAX_MAILBOX(isp); box++) {
 		if (ibits & (1 << box)) {
-			isp_prt(isp, ISP_LOGDEBUG1, "IN mbox %d = 0x%x", box,
+			isp_prt(isp, ISP_LOGDEBUG1, "IN mbox %d = 0x%04x", box,
 			    mbp->param[box]);
 			ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
 		}
@@ -5593,20 +6660,23 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask)
 	/*
 	 * Set Host Interrupt condition so that RISC will pick up mailbox regs.
 	 */
-	ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
+	if (IS_24XX(isp)) {
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
+	} else {
+		ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
+	}
 
 	/*
 	 * While we haven't finished the command, spin our wheels here.
 	 */
-	MBOX_WAIT_COMPLETE(isp);
+	MBOX_WAIT_COMPLETE(isp, mbp);
 
 	/*
 	 * Did the command time out?
 	 */
-	if (isp->isp_mboxbsy) {
-		isp->isp_mboxbsy = 0;
+	if (mbp->param[0] == MBOX_TIMEOUT) {
 		MBOX_RELEASE(isp);
-		return;
+		goto out;
 	}
 
 	/*
@@ -5615,21 +6685,18 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask)
 	for (box = 0; box < MAX_MAILBOX(isp); box++) {
 		if (obits & (1 << box)) {
 			mbp->param[box] = isp->isp_mboxtmp[box];
-			isp_prt(isp, ISP_LOGDEBUG1, "OUT mbox %d = 0x%x", box,
+			isp_prt(isp, ISP_LOGDEBUG1, "OUT mbox %d = 0x%04x", box,
 			    mbp->param[box]);
 		}
 	}
 
 	MBOX_RELEASE(isp);
-
-	if (logmask == 0 || opcode == MBOX_EXEC_FIRMWARE) {
+ out:
+	isp->isp_mboxbsy = 0;
+	if (mbp->logval == 0 || opcode == MBOX_EXEC_FIRMWARE) {
 		return;
 	}
-#ifdef	ISP_STRIPPED
-	cname = NULL;
-#else
 	cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode];
-#endif
 	if (cname == NULL) {
 		cname = tname;
 		SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
@@ -5643,46 +6710,49 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask)
 	case MBOX_COMMAND_COMPLETE:
 		break;
 	case MBOX_INVALID_COMMAND:
-		if (logmask & MBLOGMASK(MBOX_COMMAND_COMPLETE)) {
+		if (mbp->logval & MBLOGMASK(MBOX_COMMAND_COMPLETE)) {
 			xname = "INVALID COMMAND";
 		}
 		break;
 	case MBOX_HOST_INTERFACE_ERROR:
-		if (logmask & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) {
+		if (mbp->logval & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) {
 			xname = "HOST INTERFACE ERROR";
 		}
 		break;
 	case MBOX_TEST_FAILED:
-		if (logmask & MBLOGMASK(MBOX_TEST_FAILED)) {
+		if (mbp->logval & MBLOGMASK(MBOX_TEST_FAILED)) {
 			xname = "TEST FAILED";
 		}
 		break;
 	case MBOX_COMMAND_ERROR:
-		if (logmask & MBLOGMASK(MBOX_COMMAND_ERROR)) {
+		if (mbp->logval & MBLOGMASK(MBOX_COMMAND_ERROR)) {
 			xname = "COMMAND ERROR";
 		}
 		break;
 	case MBOX_COMMAND_PARAM_ERROR:
-		if (logmask & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) {
+		if (mbp->logval & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) {
 			xname = "COMMAND PARAMETER ERROR";
 		}
 		break;
 	case MBOX_LOOP_ID_USED:
-		if (logmask & MBLOGMASK(MBOX_LOOP_ID_USED)) {
+		if (mbp->logval & MBLOGMASK(MBOX_LOOP_ID_USED)) {
 			xname = "LOOP ID ALREADY IN USE";
 		}
 		break;
 	case MBOX_PORT_ID_USED:
-		if (logmask & MBLOGMASK(MBOX_PORT_ID_USED)) {
+		if (mbp->logval & MBLOGMASK(MBOX_PORT_ID_USED)) {
 			xname = "PORT ID ALREADY IN USE";
 		}
 		break;
 	case MBOX_ALL_IDS_USED:
-		if (logmask & MBLOGMASK(MBOX_ALL_IDS_USED)) {
+		if (mbp->logval & MBLOGMASK(MBOX_ALL_IDS_USED)) {
 			xname = "ALL LOOP IDS IN USE";
 		}
 		break;
-	case 0:		/* special case */
+	case MBOX_REGS_BUSY:
+		xname = "REGISTERS BUSY";
+		break;
+	case MBOX_TIMEOUT:
 		xname = "TIMEOUT";
 		break;
 	default:
@@ -5705,7 +6775,9 @@ isp_fw_state(ispsoftc_t *isp)
 
 		MEMZERO(&mbs, sizeof (mbs));
 		mbs.param[0] = MBOX_GET_FW_STATE;
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
+		mbs.logval = MBLOGALL;
+		mbs.timeout = 100000;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
 			fcp->isp_fwstate = mbs.param[1];
 		}
@@ -5767,17 +6839,16 @@ isp_update_bus(ispsoftc_t *isp, int bus)
 		 */
 		if (sdp->isp_devparam[tgt].dev_refresh) {
 			mbs.param[0] = MBOX_GET_TARGET_PARAMS;
-			sdp->isp_devparam[tgt].dev_refresh = 0;
 			get = 1;
 		} else if (sdp->isp_devparam[tgt].dev_update) {
 			mbs.param[0] = MBOX_SET_TARGET_PARAMS;
+
 			/*
 			 * Make sure goal_flags has "Renegotiate on Error"
 			 * on and "Freeze Queue on Error" off.
 			 */
 			sdp->isp_devparam[tgt].goal_flags |= DPARM_RENEG;
 			sdp->isp_devparam[tgt].goal_flags &= ~DPARM_QFRZ;
-
 			mbs.param[2] = sdp->isp_devparam[tgt].goal_flags;
 
 			/*
@@ -5811,26 +6882,31 @@ isp_update_bus(ispsoftc_t *isp, int bus)
 			    "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x",
 			    bus, tgt, mbs.param[2], mbs.param[3] >> 8,
 			    mbs.param[3] & 0xff);
-			sdp->isp_devparam[tgt].dev_update = 0;
-			sdp->isp_devparam[tgt].dev_refresh = 1;
 			get = 0;
 		} else {
 			continue;
 		}
 		mbs.param[1] = (bus << 15) | (tgt << 8);
-		isp_mboxcmd(isp, &mbs, MBLOGALL);
-		if (get == 0) {
-			isp->isp_sendmarker |= (1 << bus);
+		mbs.logval = MBLOGALL;
+		isp_mboxcmd(isp, &mbs);
+		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			continue;
 		}
-		flags = mbs.param[2];
-		period = mbs.param[3] & 0xff;
-		offset = mbs.param[3] >> 8;
-		sdp->isp_devparam[tgt].actv_flags = flags;
-		sdp->isp_devparam[tgt].actv_period = period;
-		sdp->isp_devparam[tgt].actv_offset = offset;
-		get = (bus << 16) | tgt;
-		(void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get);
+		if (get == 0) {
+			isp->isp_sendmarker |= (1 << bus);
+			sdp->isp_devparam[tgt].dev_update = 0;
+			sdp->isp_devparam[tgt].dev_refresh = 1;
+		} else {
+			sdp->isp_devparam[tgt].dev_refresh = 0;
+			flags = mbs.param[2];
+			period = mbs.param[3] & 0xff;
+			offset = mbs.param[3] >> 8;
+			sdp->isp_devparam[tgt].actv_flags = flags;
+			sdp->isp_devparam[tgt].actv_period = period;
+			sdp->isp_devparam[tgt].actv_offset = offset;
+			get = (bus << 16) | tgt;
+			(void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get);
+		}
 	}
 
 	for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
@@ -5921,7 +6997,7 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
 			ISP_NODEWWN(isp) = fcp->isp_nodewwn;
 			if (fcp->isp_nodewwn == 0) {
 				isp_prt(isp, ISP_LOGCONFIG,
-				    "bad WWNN- using default\n");
+				    "bad WWNN- using default");
 				ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
 			}
 		}
@@ -5938,7 +7014,7 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
 			ISP_PORTWWN(isp) = fcp->isp_portwwn;
 			if (fcp->isp_portwwn == 0) {
 				isp_prt(isp, ISP_LOGCONFIG,
-				    "bad WWPN- using default\n");
+				    "bad WWPN- using default");
 				ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
 			}
 		}
@@ -6005,7 +7081,8 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
 
 		MEMZERO(&mbs, sizeof (mbs));
 		mbs.param[0] = MBOX_GET_ACT_NEG_STATE;
-		isp_mboxcmd(isp, &mbs, MBLOGNONE);
+		mbs.logval = MBLOGNONE;
+		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			sdp->isp_req_ack_active_neg = 1;
 			sdp->isp_data_line_active_neg = 1;
@@ -6082,18 +7159,16 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
  * Re-initialize the ISP and complete all orphaned commands
  * with a 'botched' notice. The reset/init routines should
  * not disturb an already active list of commands.
- *
- * Locks held prior to coming here.
  */
 
 void
 isp_reinit(ispsoftc_t *isp)
 {
 	XS_T *xs;
-	int i;
+	uint32_t tmp;
 
 	if (IS_FC(isp)) {
-		isp_mark_getpdb_all(isp);
+		isp_mark_portdb(isp, 0);
 	}
 	isp_reset(isp);
 	if (isp->isp_state != ISP_RESETSTATE) {
@@ -6106,17 +7181,36 @@ isp_reinit(ispsoftc_t *isp)
 		if (isp->isp_state != ISP_RUNSTATE) {
 			isp_prt(isp, ISP_LOGERR,
 			    "isp_reinit cannot restart card");
+			ISP_DISABLE_INTS(isp);
 		}
-	}
+	} else {
+		ISP_DISABLE_INTS(isp);
+		if (IS_FC(isp)) {
+			/*
+			 * If we're in ISP_ROLE_NONE, turn off the lasers.
+			 */
+			if (!IS_24XX(isp)) {
+				ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
+				ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
+				ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
+				ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
+				ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
+			}
+		}
+ 	}
 	isp->isp_nactive = 0;
 
-	for (i = 0; i < isp->isp_maxcmds; i++) {
-		uint16_t handle;
-		xs = isp->isp_xflist[i];
+	for (tmp = 0; tmp < isp->isp_maxcmds; tmp++) {
+		uint32_t handle;
+
+		xs = isp->isp_xflist[tmp];
 		if (xs == NULL) {
 			continue;
 		}
-		handle = isp_index_handle(i);
+		handle = isp_find_handle(isp, xs);
+		if (handle == 0) {
+			continue;
+		}
 		isp_destroy_handle(isp, handle);
 		if (XS_XFRLEN(xs)) {
 			ISP_DMAFREE(isp, xs, handle);
@@ -6127,6 +7221,9 @@ isp_reinit(ispsoftc_t *isp)
 		XS_SETERR(xs, HBA_BUSRESET);
 		isp_done(xs);
 	}
+#ifdef	ISP_TARGET_MODE
+	MEMZERO(isp->isp_tgtlist, isp->isp_maxcmds * sizeof (void **));
+#endif
 }
 
 /*
@@ -6144,7 +7241,9 @@ isp_read_nvram(ispsoftc_t *isp)
 #define	nvram_data	_n._x
 #define	nvram_words	_n._s
 
-	if (IS_FC(isp)) {
+	if (IS_24XX(isp)) {
+		return (isp_read_nvram_2400(isp));
+	} else if (IS_FC(isp)) {
 		amt = ISP2100_NVRAM_SIZE;
 		minversion = 1;
 	} else if (IS_ULTRA2(isp)) {
@@ -6155,13 +7254,10 @@ isp_read_nvram(ispsoftc_t *isp)
 		minversion = 2;
 	}
 
-	/*
-	 * Just read the first two words first to see if we have a valid
-	 * NVRAM to continue reading the rest with.
-	 */
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < amt>>1; i++) {
 		isp_rdnvram_word(isp, i, &nvram_words[i]);
 	}
+
 	if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
 	    nvram_data[2] != 'P') {
 		if (isp->isp_bustype != ISP_BT_SBUS) {
@@ -6172,9 +7268,7 @@ isp_read_nvram(ispsoftc_t *isp)
 		retval = -1;
 		goto out;
 	}
-	for (i = 2; i < amt>>1; i++) {
-		isp_rdnvram_word(isp, i, &nvram_words[i]);
-	}
+
 	for (csum = 0, i = 0; i < amt; i++) {
 		csum += nvram_data[i];
 	}
@@ -6183,6 +7277,7 @@ isp_read_nvram(ispsoftc_t *isp)
 		retval = -1;
 		goto out;
 	}
+
 	if (ISP_NVRAM_VERSION(nvram_data) < minversion) {
 		isp_prt(isp, ISP_LOGWARN, "version %d NVRAM not understood",
 		    ISP_NVRAM_VERSION(nvram_data));
@@ -6211,6 +7306,43 @@ isp_read_nvram(ispsoftc_t *isp)
 #undef	nvram_words
 }
 
+static int
+isp_read_nvram_2400(ispsoftc_t *isp)
+{
+	uint8_t *nvram_data = FCPARAM(isp)->isp_scratch;
+	int retval = 0;
+	uint32_t addr, csum, lwrds, *dptr;
+	
+	if (isp->isp_port) {
+		addr = ISP2400_NVRAM_PORT1_ADDR;
+	} else {
+		addr = ISP2400_NVRAM_PORT0_ADDR;
+	}
+	
+	dptr = (uint32_t *) nvram_data;
+	for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
+		isp_rd_2400_nvram(isp, addr++, dptr++);
+	}
+	if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
+	    nvram_data[2] != 'P') {
+		isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header");
+		retval = -1;
+		goto out;
+	}
+	dptr = (uint32_t *) nvram_data;
+	for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
+		csum += dptr[lwrds];
+	}
+	if (csum != 0) {
+		isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
+		retval = -1;
+		goto out;
+	}
+	isp_parse_nvram_2400(isp, nvram_data);
+out:
+	return (retval);
+}
+
 static void
 isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
 {
@@ -6282,6 +7414,29 @@ isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
 	ISP_SWIZZLE_NVRAM_WORD(isp, rp);
 }
 
+static void
+isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
+{
+	int loops = 0;
+	const uint32_t base = 0x7ffe0000;
+	uint32_t tmp;
+
+	ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
+	for (loops = 0; loops < 5000; loops++) {
+		USEC_DELAY(10);
+		tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
+		if ((tmp & (1 << 31)) != 0) {
+			break;
+		}
+	}
+	if (tmp & (1 << 31)) {
+		tmp = ISP_READ(isp, BIU2400_FLASH_DATA);
+		*rp = tmp;
+	} else {
+		*rp = 0xffffffff;
+	}
+}
+
 static void
 isp_parse_nvram_1020(ispsoftc_t *isp, uint8_t *nvram_data)
 {
@@ -6591,10 +7746,42 @@ isp_parse_nvram_12160(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
 	}
 }
 
+static void
+isp_fix_nvram_wwns(ispsoftc_t *isp)
+{
+	fcparam *fcp = FCPARAM(isp);
+
+	/*
+	 * Make sure we have both Node and Port as non-zero values.
+	 */
+	if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) {
+		fcp->isp_portwwn = fcp->isp_nodewwn;
+	} else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) {
+		fcp->isp_nodewwn = fcp->isp_portwwn;
+	}
+
+	/*
+	 * Make the Node and Port values sane if they're NAA == 2.
+	 * This means to clear bits 48..56 for the Node WWN and
+	 * make sure that there's some non-zero value in 48..56
+	 * for the Port WWN.
+	 */
+	if (fcp->isp_nodewwn && fcp->isp_portwwn) {
+		if ((fcp->isp_nodewwn & (((uint64_t) 0xfff) << 48)) != 0 &&
+		    (fcp->isp_nodewwn >> 60) == 2) {
+			fcp->isp_nodewwn &= ~((uint64_t) 0xfff << 48);
+		}
+		if ((fcp->isp_portwwn & (((uint64_t) 0xfff) << 48)) == 0 &&
+		    (fcp->isp_portwwn >> 60) == 2) {
+			fcp->isp_portwwn |= ((uint64_t) 1 << 56);
+		}
+	}
+}
+
 static void
 isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
 {
-	fcparam *fcp = (fcparam *) isp->isp_param;
+	fcparam *fcp = FCPARAM(isp);
 	uint64_t wwn;
 
 	/*
@@ -6632,47 +7819,21 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
 	}
 	fcp->isp_nodewwn = wwn;
 
-	/*
-	 * Make sure we have both Node and Port as non-zero values.
-	 */
-	if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) {
-		fcp->isp_portwwn = fcp->isp_nodewwn;
-	} else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) {
-		fcp->isp_nodewwn = fcp->isp_portwwn;
-	}
+	isp_fix_nvram_wwns(isp);
 
-	/*
-	 * Make the Node and Port values sane if they're NAA == 2.
-	 * This means to clear bits 48..56 for the Node WWN and
-	 * make sure that there's some non-zero value in 48..56
-	 * for the Port WWN.
-	 */
-	if (fcp->isp_nodewwn && fcp->isp_portwwn) {
-		if ((fcp->isp_nodewwn & (((uint64_t) 0xfff) << 48)) != 0 &&
-		    (fcp->isp_nodewwn >> 60) == 2) {
-			fcp->isp_nodewwn &= ~((uint64_t) 0xfff << 48);
-		}
-		if ((fcp->isp_portwwn & (((uint64_t) 0xfff) << 48)) == 0 &&
-		    (fcp->isp_portwwn >> 60) == 2) {
-			fcp->isp_portwwn |= ((uint64_t) 1 << 56);
-		}
+	fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
+	if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
+		fcp->isp_maxfrmlen = ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data);
 	}
-
-	fcp->isp_maxalloc =
-		ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
-	if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0)
-		fcp->isp_maxfrmlen =
-			ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data);
-	fcp->isp_retry_delay =
-		ISP2100_NVRAM_RETRY_DELAY(nvram_data);
-	fcp->isp_retry_count =
-		ISP2100_NVRAM_RETRY_COUNT(nvram_data);
-	if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
-		fcp->isp_loopid =
-			ISP2100_NVRAM_HARDLOOPID(nvram_data);
-	if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0)
+	fcp->isp_retry_delay = ISP2100_NVRAM_RETRY_DELAY(nvram_data);
+	fcp->isp_retry_count = ISP2100_NVRAM_RETRY_COUNT(nvram_data);
+	if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
+		fcp->isp_loopid = ISP2100_NVRAM_HARDLOOPID(nvram_data);
+	}
+	if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) {
 		fcp->isp_execthrottle =
 			ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data);
+	}
 	fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data);
 	isp_prt(isp, ISP_LOGDEBUG0,
 	    "NVRAM 0x%08x%08x 0x%08x%08x maxalloc %d maxframelen %d",
@@ -6693,6 +7854,64 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
 	    ISP2100_XFW_OPTIONS(nvram_data), ISP2100_ZFW_OPTIONS(nvram_data));
 }
 
+static void
+isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
+{
+	fcparam *fcp = FCPARAM(isp);
+	uint64_t wwn;
+
+	isp_prt(isp, ISP_LOGDEBUG0,
+	    "NVRAM 0x%08x%08x 0x%08x%08x exchg_cnt %d maxframelen %d",
+	    (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
+	    (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
+	    (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
+	    (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
+	    ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data),
+	    ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
+	isp_prt(isp, ISP_LOGDEBUG0,
+	    "NVRAM execthr %d loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
+	    ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data),
+	    ISP2400_NVRAM_HARDLOOPID(nvram_data),
+	    ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
+	    ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
+	    ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
+
+	wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
+	if (wwn) {
+		if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
+			wwn = 0;
+		}
+	}
+	fcp->isp_portwwn = wwn;
+
+	wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
+	if (wwn) {
+		if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
+			wwn = 0;
+		}
+	}
+	fcp->isp_nodewwn = wwn;
+
+	isp_fix_nvram_wwns(isp);
+
+	if (ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data)) {
+		fcp->isp_maxalloc = ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data);
+	}
+	if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
+		fcp->isp_maxfrmlen = ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
+	}
+	if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
+		fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
+	}
+	if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) {
+		fcp->isp_execthrottle =
+			ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data);
+	}
+	fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
+	fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
+	fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);
+}
+
 #ifdef	ISP_FW_CRASH_DUMP
 static void isp2200_fw_dump(ispsoftc_t *);
 static void isp2300_fw_dump(ispsoftc_t *);
@@ -6823,7 +8042,7 @@ isp2200_fw_dump(ispsoftc_t *isp)
 			break;
 		}
 	}
-	ENABLE_INTS(isp);
+	ISP_ENABLE_INTS(isp);
 	mbs.param[0] = MBOX_READ_RAM_WORD;
 	mbs.param[1] = 0x1000;
 	isp->isp_mbxworkp = (void *) ptr;
@@ -6966,7 +8185,7 @@ isp2300_fw_dump(ispsoftc_t *isp)
 		isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
 		return;
 	}
-	ENABLE_INTS(isp);
+	ISP_ENABLE_INTS(isp);
 	MEMZERO(&mbs, sizeof (mbs));
 	mbs.param[0] = MBOX_READ_RAM_WORD;
 	mbs.param[1] = 0x800;
@@ -7008,5 +8227,8 @@ isp_fw_dump(ispsoftc_t *isp)
 		isp2200_fw_dump(isp);
 	else if (IS_23XX(isp))
 		isp2300_fw_dump(isp);
+	else if (IS_24XX(isp))
+		isp_prt(isp, ISP_LOGERR, "24XX dump method undefined");
+
 }
 #endif
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 5e1d8ce7682a..2750969a5c48 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$");
 MODULE_VERSION(isp, 1);
 MODULE_DEPEND(isp, cam, 1, 1, 1);
 int isp_announced = 0;
+int isp_fabric_hysteresis = 5;
+int isp_loop_down_limit = 300;	/* default loop down limit */
+int isp_quickboot_time = 5;	/* don't wait more than N secs for loop up */
 
 static d_ioctl_t ispioctl;
 static void isp_intr_enable(void *);
@@ -242,7 +245,7 @@ isp_attach(ispsoftc_t *isp)
 
 	if (isp->isp_role != ISP_ROLE_NONE) {
 		isp->isp_state = ISP_RUNSTATE;
-		ENABLE_INTS(isp);
+		ISP_ENABLE_INTS(isp);
 	}
 	if (isplist == NULL) {
 		isplist = isp;
@@ -387,7 +390,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
 	case ISP_FC_GETDINFO:
 	{
 		struct isp_fc_device *ifc = (struct isp_fc_device *) addr;
-		struct lportdb *lp;
+		fcportdb_t *lp;
 
 		if (IS_SCSI(isp)) {
 			break;
@@ -398,9 +401,9 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
 		}
 		ISP_LOCK(isp);
 		lp = &FCPARAM(isp)->portdb[ifc->loopid];
-		if (lp->valid) {
+		if (lp->state == FC_PORTDB_STATE_VALID) {
 			ifc->role = lp->roles;
-			ifc->loopid = lp->loopid;
+			ifc->loopid = lp->handle;
 			ifc->portid = lp->portid;
 			ifc->node_wwn = lp->node_wwn;
 			ifc->port_wwn = lp->port_wwn;
@@ -566,7 +569,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
 		memset(&mbs, 0, sizeof (mbs));
 		needmarker = retval = 0;
 		loopid = fct->loopid;
-		if (IS_2KLOGIN(isp) == 0) {
+		if (FCPARAM(isp)->isp_2klogin == 0) {
 			loopid <<= 8;
 		}
 		switch (fct->action) {
@@ -657,10 +660,7 @@ isp_intr_enable(void *arg)
 {
 	ispsoftc_t *isp = arg;
 	if (isp->isp_role != ISP_ROLE_NONE) {
-		ENABLE_INTS(isp);
-#if	0
-		isp->isp_osinfo.intsok = 1;
-#endif
+		ISP_ENABLE_INTS(isp);
 	}
 	/* Release our hook so that the boot can continue. */
 	config_intrhook_disestablish(&isp->isp_osinfo.ehook);
@@ -911,7 +911,7 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
 		/*
 		 * This is as a good a place as any to check f/w capabilities.
 		 */
-		if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) == 0) {
+		if (FCPARAM(isp)->isp_tmode == 0) {
 			isp_prt(isp, ISP_LOGERR,
 			    "firmware does not support target mode");
 			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
@@ -921,9 +921,8 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
 		 * XXX: We *could* handle non-SCCLUN f/w, but we'd have to
 		 * XXX: dorks with our already fragile enable/disable code.
 		 */
-		if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
-			isp_prt(isp, ISP_LOGERR,
-			    "firmware not SCCLUN capable");
+		if (FCPARAM(isp)->isp_sccfw == 0) {
+			isp_prt(isp, ISP_LOGERR, "firmware not SCCLUN capable");
 			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
 			return (-1);
 		}
@@ -1280,8 +1279,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
 {
 	void *qe;
 	struct ccb_scsiio *cso = &ccb->csio;
-	uint16_t *hp, save_handle;
-	uint16_t nxti, optr;
+	uint32_t nxti, optr, handle;
 	uint8_t local[QENTRY_LEN];
 
 
@@ -1303,11 +1301,11 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
 
 		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
 		cto->ct_header.rqs_entry_count = 1;
-		if (IS_2KLOGIN(isp)) {
+		if (FCPARAM(isp)->isp_2klogin) {
 			((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
 		} else {
 			cto->ct_iid = cso->init_id;
-			if (!(FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)) {
+			if (FCPARAM(isp)->isp_sccfw == 0) {
 				cto->ct_lun = ccb->ccb_h.target_lun;
 			}
 		}
@@ -1386,7 +1384,6 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
 			atp->state = ATPD_STATE_CTIO;
 		}
 		cto->ct_timeout = 10;
-		hp = &cto->ct_syshandle;
 	} else {
 		ct_entry_t *cto = (ct_entry_t *) local;
 
@@ -1422,10 +1419,9 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
 		}
 		ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
 		cto->ct_timeout = 10;
-		hp = &cto->ct_syshandle;
 	}
 
-	if (isp_save_xs_tgt(isp, ccb, hp)) {
+	if (isp_save_xs_tgt(isp, ccb, &handle)) {
 		xpt_print_path(ccb->ccb_h.path);
 		printf("No XFLIST pointers for isp_target_start_ctio\n");
 		XS_SETERR(ccb, CAM_REQUEUE_REQ);
@@ -1442,7 +1438,13 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
 	 * format.
 	 */
 
-	save_handle = *hp;
+	if (IS_FC(isp)) {
+		ct2_entry_t *cto = (ct2_entry_t *) local;
+		cto->ct_syshandle = handle;
+	} else {
+		ct_entry_t *cto = (ct_entry_t *) local;
+		cto->ct_syshandle = handle;
+	}
 
 	switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) {
 	case CMD_QUEUED:
@@ -1457,7 +1459,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
 	default:
 		break;
 	}
-	isp_destroy_tgt_handle(isp, save_handle);
+	isp_destroy_tgt_handle(isp, handle);
 
 out:
 	ISPLOCK_2_CAMLOCK(isp);
@@ -1478,7 +1480,7 @@ isp_target_putback_atio(union ccb *ccb)
 {
 	ispsoftc_t *isp;
 	struct ccb_scsiio *cso;
-	uint16_t nxti, optr;
+	uint32_t nxti, optr;
 	void *qe;
 
 	isp = XS_ISP(ccb);
@@ -1496,7 +1498,7 @@ isp_target_putback_atio(union ccb *ccb)
 		MEMZERO(at, sizeof (at2_entry_t));
 		at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
 		at->at_header.rqs_entry_count = 1;
-		if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) {
+		if (FCPARAM(isp)->isp_sccfw) {
 			at->at_scclun = (uint16_t) ccb->ccb_h.target_lun;
 		} else {
 			at->at_lun = (uint8_t) ccb->ccb_h.target_lun;
@@ -1685,7 +1687,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
 		return (0);
 	}
 
-	if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) {
+	if (FCPARAM(isp)->isp_sccfw) {
 		lun = aep->at_scclun;
 	} else {
 		lun = aep->at_lun;
@@ -1731,8 +1733,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
 	    lun, tptr->atio_count);
 
 	if (tptr == &isp->isp_osinfo.tsdflt[0]) {
-		atiop->ccb_h.target_id =
-		    ((fcparam *)isp->isp_param)->isp_loopid;
+		atiop->ccb_h.target_id = FCPARAM(isp)->isp_loopid;
 		atiop->ccb_h.target_lun = lun;
 	}
 	/*
@@ -2004,7 +2005,8 @@ static void
 isp_poll(struct cam_sim *sim)
 {
 	ispsoftc_t *isp = cam_sim_softc(sim);
-	uint16_t isr, sema, mbox;
+	uint32_t isr;
+	uint16_t sema, mbox;
 
 	ISP_LOCK(isp);
 	if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
@@ -2020,7 +2022,6 @@ isp_watchdog(void *arg)
 	XS_T *xs = arg;
 	ispsoftc_t *isp = XS_ISP(xs);
 	uint32_t handle;
-	int iok;
 
 	/*
 	 * We've decided this command is dead. Make sure we're not trying
@@ -2028,11 +2029,10 @@ isp_watchdog(void *arg)
 	 * and seeing whether it's still alive.
 	 */
 	ISP_LOCK(isp);
-	iok = isp->isp_osinfo.intsok;
-	isp->isp_osinfo.intsok = 0;
 	handle = isp_find_handle(isp, xs);
 	if (handle) {
-		uint16_t isr, sema, mbox;
+		uint32_t isr;
+		uint16_t sema, mbox;
 
 		if (XS_CMD_DONE_P(xs)) {
 			isp_prt(isp, ISP_LOGDEBUG1,
@@ -2077,28 +2077,14 @@ isp_watchdog(void *arg)
 			XS_CMD_C_WDOG(xs);
 			isp_done(xs);
 		} else {
-			uint16_t nxti, optr;
-			ispreq_t local, *mp= &local, *qe;
-
 			XS_CMD_C_WDOG(xs);
 			xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
-			if (isp_getrqentry(isp, &nxti, &optr, (void **) &qe)) {
-				ISP_UNLOCK(isp);
-				return;
-			}
 			XS_CMD_S_GRACE(xs);
-			MEMZERO((void *) mp, sizeof (*mp));
-			mp->req_header.rqs_entry_count = 1;
-			mp->req_header.rqs_entry_type = RQSTYPE_MARKER;
-			mp->req_modifier = SYNC_ALL;
-			mp->req_target = XS_CHANNEL(xs) << 7;
-			isp_put_request(isp, mp, qe);
-			ISP_ADD_REQUEST(isp, nxti);
+			isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
 		}
 	} else {
 		isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command");
 	}
-	isp->isp_osinfo.intsok = iok;
 	ISP_UNLOCK(isp);
 }
 
@@ -2106,13 +2092,13 @@ static void
 isp_kthread(void *arg)
 {
 	ispsoftc_t *isp = arg;
+	int slp;
 
 
 #if __FreeBSD_version < 500000  
         int s;
 
         s = splcam();
-        isp->isp_osinfo.intsok = 1;
 #else
 #ifdef	ISP_SMPLOCK
 	mtx_lock(&isp->isp_lock);
@@ -2125,32 +2111,63 @@ isp_kthread(void *arg)
 	 * gotten good fibre channel state.
 	 */
 	for (;;) {
-		int wasfrozen;
+		int wasfrozen, lb;
 
 		isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state");
-		while (isp_fc_runstate(isp, 2 * 1000000) != 0) {
-			isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state ungood");
-			if (FCPARAM(isp)->isp_fwstate != FW_READY ||
-			    FCPARAM(isp)->isp_loopstate < LOOP_PDB_RCVD) {
-				if (FCPARAM(isp)->loop_seen_once == 0 ||
-				    isp->isp_osinfo.ktmature == 0) {
-					break;
-				}
+		lb = isp_fc_runstate(isp, 250000);
+		if (lb) {
+			unsigned int inc = 1;
+
+			if (lb < 0) {
+				isp_prt(isp, ISP_LOGDEBUG0,
+				    "kthread: FC loop not up (down count %d)",
+				    isp->isp_osinfo.loop_down_time);
+			} else {
+				isp_prt(isp, ISP_LOGDEBUG0,
+				    "kthread: FC got to %d (down count %d)",
+				    lb, isp->isp_osinfo.loop_down_time);
 			}
-#ifdef	ISP_SMPLOCK
-			msleep(isp_kthread, &isp->isp_lock,
-			    PRIBIO, "isp_fcthrd", hz);
-#else
-			(void) tsleep(isp_kthread, PRIBIO, "isp_fcthrd", hz);
-#endif
+
+
+			/*
+			 * If we've never seen loop up and we've waited longer
+			 * than quickboot time, give up and go to sleep until
+			 * loop comes up. Otherwise, increment the loop down
+			 * time and figure out how long to sleep to the next
+			 * check. 
+			 */
+			if (FCPARAM(isp)->loop_seen_once == 0 &&
+			    isp->isp_osinfo.loop_down_time >=
+			    isp_quickboot_time) {
+				isp->isp_osinfo.loop_down_time = 0xffff;
+				slp = 0;
+			} else if (isp->isp_osinfo.loop_down_time > 30) {
+				inc = 30;
+				slp = 30 * hz;
+			} else if (isp->isp_osinfo.loop_down_time > 1) {
+				slp = hz;
+			} else {
+				slp = 1;
+			}
+
+			inc += isp->isp_osinfo.loop_down_time;
+			if (inc < 0xffff) {
+				isp->isp_osinfo.loop_down_time = inc;
+			} else {
+				isp->isp_osinfo.loop_down_time = 0xfffe;
+			}
+		} else {
+			isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state OK");
+			isp->isp_osinfo.loop_down_time = 0;
+			slp = 0;
 		}
 
 		/*
-		 * Even if we didn't get good loop state we may be
-		 * unfreezing the SIMQ so that we can kill off
-		 * commands (if we've never seen loop before, for example).
+		 * If we'd frozen the simq, unfreeze it now so that CAM
+		 * can start sending us commands. If the FC state isn't
+		 * okay yet, they'll hit that in isp_start which will
+		 * freeze the queue again.
 		 */
-		isp->isp_osinfo.ktmature = 1;
 		wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
 		isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
 		if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
@@ -2159,16 +2176,26 @@ isp_kthread(void *arg)
 			xpt_release_simq(isp->isp_sim, 1);
 			CAMLOCK_2_ISPLOCK(isp);
 		}
-		isp_prt(isp, ISP_LOGDEBUG0, "kthread: waiting until called");
 #if __FreeBSD_version < 500000  
-		tsleep(&isp->isp_osinfo.kproc, PRIBIO, "isp_fc_worker", 0);
+		tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp);
 #else
 #ifdef	ISP_SMPLOCK
-		cv_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock);
+		cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock, slp);
 #else
-		(void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "fc_cv", 0);
+		(void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf", slp);
 #endif
 #endif
+		/*
+		 * If slp is zero, we're waking up for the first time after
+		 * things have been okay. In this case, we set a deferral state
+		 * for all commands and delay hysteresis seconds before starting
+		 * the FC state evaluation. This gives the loop/fabric a chance
+		 * to settle.
+		 */
+		if (slp == 0 && isp->isp_osinfo.hysteresis) {
+			(void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
+			    (isp->isp_osinfo.hysteresis * hz));
+		}
 	}
 }
 
@@ -2260,8 +2287,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
 			 * This can only happen for Fibre Channel
 			 */
 			KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
-			if (FCPARAM(isp)->loop_seen_once == 0 &&
-			    isp->isp_osinfo.ktmature) {
+			/*
+			 * If we've exceeded the loop down limit start
+			 * failing commands.
+			 */
+			if (isp->isp_osinfo.loop_down_time > 
+			    isp->isp_osinfo.loop_down_limit) {
 				ISPLOCK_2_CAMLOCK(isp);
 				XS_SETERR(ccb, CAM_SEL_TIMEOUT);
 				xpt_done(ccb);
@@ -2303,25 +2334,22 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
 #ifdef	ISP_TARGET_MODE
 	case XPT_EN_LUN:		/* Enable LUN as a target */
 	{
-		int seq, iok, i;
+		int seq, i;
 		CAMLOCK_2_ISPLOCK(isp);
-		iok = isp->isp_osinfo.intsok;
-		isp->isp_osinfo.intsok = 0;
 		seq = isp_en_lun(isp, ccb);
 		if (seq < 0) {
-			isp->isp_osinfo.intsok = iok;
 			ISPLOCK_2_CAMLOCK(isp);
 			xpt_done(ccb);
 			break;
 		}
 		for (i = 0; isp->isp_osinfo.leact[seq] && i < 30 * 1000; i++) {
-			uint16_t isr, sema, mbox;
+			uint32_t isr;
+			uint16_t sema, mbox;
 			if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
 				isp_intr(isp, isr, sema, mbox);
 			}
 			DELAY(1000);
 		}
-		isp->isp_osinfo.intsok = iok;
 		ISPLOCK_2_CAMLOCK(isp);
 		break;
 	}
@@ -2519,7 +2547,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
 			else
 				fc->bitrate = 100000;
 			if (tgt > 0 && tgt < MAX_FC_TARG) {
-				struct lportdb *lp = &fcp->portdb[tgt];
+				fcportdb_t *lp = &fcp->portdb[tgt];
 				fc->wwnn = lp->node_wwn;
 				fc->wwpn = lp->port_wwn;
 				fc->port = lp->portid;
@@ -2767,6 +2795,19 @@ int
 isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
 {
 	int bus, rv = 0;
+	static const char *roles[4] = {
+	    "(none)", "Target", "Initiator", "Target/Initiator"
+	};
+	static const char prom[] =
+	    "PortID 0x%06x handle 0x%x role %s %s\n"
+            "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
+	static const char prom2[] =
+	    "PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
+            "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
+	target_id_t tgt;
+	fcportdb_t *lp;
+	struct cam_path *tmppath;
+
 	switch (cmd) {
 	case ISPASYNC_NEW_TGT_PARAMS:
 	{
@@ -2775,7 +2816,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
 		int flags, tgt;
 		sdparam *sdp = isp->isp_param;
 		struct ccb_trans_settings cts;
-		struct cam_path *tmppath;
 
 		memset(&cts, 0, sizeof (struct ccb_trans_settings));
 
@@ -2876,59 +2916,127 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
 		 */
 		isp_prt(isp, ISP_LOGINFO, "Loop UP");
 		break;
-	case ISPASYNC_PROMENADE:
-	{
-		const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x "
-		    "(role %s) %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x";
-		static const char *roles[4] = {
-		    "(none)", "Target", "Initiator", "Target/Initiator"
-		};
-		fcparam *fcp = isp->isp_param;
-		int tgt = *((int *) arg);
-#if __FreeBSD_version >= 500000  
-		int is_tgt_mask = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
-		struct cam_path *tmppath;
-#endif
-		struct lportdb *lp = &fcp->portdb[tgt]; 
+	case ISPASYNC_DEV_ARRIVED:
+		lp = arg;
 
-		isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid,
-		    roles[lp->roles & 0x3],
-		    (lp->valid)? "Arrived" : "Departed",
-		    (uint32_t) (lp->port_wwn >> 32),
-		    (uint32_t) (lp->port_wwn & 0xffffffffLL),
-		    (uint32_t) (lp->node_wwn >> 32),
-		    (uint32_t) (lp->node_wwn & 0xffffffffLL));
-
-		ISPLOCK_2_CAMLOCK(isp);
+		if (lp->ini_map_idx) {
+			tgt = lp->ini_map_idx - 1;
+			isp_prt(isp, ISP_LOGCONFIG, prom2,
+			    lp->portid, lp->handle,
+		            roles[lp->roles & 0x3], "arrived at", tgt,
+		    	    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
 #if __FreeBSD_version >= 500000  
-		if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim),
-		    (target_id_t)tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
-			CAMLOCK_2_ISPLOCK(isp);
-                        break;
-                }
-		/*
-		 * Policy: only announce targets.
-		 */
-		if (lp->roles & is_tgt_mask) {
-			if (lp->valid) {
-				xpt_async(AC_FOUND_DEVICE, tmppath, NULL);
-			} else {
-				xpt_async(AC_LOST_DEVICE, tmppath, NULL);
+			ISPLOCK_2_CAMLOCK(isp);
+			if (xpt_create_path(&tmppath, NULL,
+			    cam_sim_path(isp->isp_sim), tgt,
+			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+				CAMLOCK_2_ISPLOCK(isp);
+				break;
 			}
-		}
-		xpt_free_path(tmppath);
+			xpt_async(AC_FOUND_DEVICE, tmppath, NULL);
+			xpt_free_path(tmppath);
+			CAMLOCK_2_ISPLOCK(isp);
 #endif
-		CAMLOCK_2_ISPLOCK(isp);
-		break;
-	}
-	case ISPASYNC_CHANGE_NOTIFY:
-		if (arg == ISPASYNC_CHANGE_PDB) {
-			isp_prt(isp, ISP_LOGINFO,
-			    "Port Database Changed");
-		} else if (arg == ISPASYNC_CHANGE_SNS) {
-			isp_prt(isp, ISP_LOGINFO,
-			    "Name Server Database Changed");
+		} else {
+			isp_prt(isp, ISP_LOGCONFIG, prom,
+			    lp->portid, lp->handle,
+		            roles[lp->roles & 0x3], "arrived",
+		    	    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
 		}
+		break;
+	case ISPASYNC_DEV_CHANGED:
+		lp = arg;
+		if (lp->ini_map_idx) {
+			tgt = lp->ini_map_idx - 1;
+			isp_prt(isp, ISP_LOGCONFIG, prom2,
+			    lp->portid, lp->handle,
+		    	    roles[lp->roles & 0x3], "changed at", tgt,
+			    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
+		} else {
+			isp_prt(isp, ISP_LOGCONFIG, prom,
+			    lp->portid, lp->handle,
+		    	    roles[lp->roles & 0x3], "changed",
+			    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
+		}
+		break;
+	case ISPASYNC_DEV_STAYED:
+		lp = arg;
+		if (lp->ini_map_idx) {
+			tgt = lp->ini_map_idx - 1;
+			isp_prt(isp, ISP_LOGCONFIG, prom2,
+			    lp->portid, lp->handle,
+		    	    roles[lp->roles & 0x3], "stayed at", tgt,
+			    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
+		} else {
+			isp_prt(isp, ISP_LOGCONFIG, prom,
+			    lp->portid, lp->handle,
+		    	    roles[lp->roles & 0x3], "stayed",
+			    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
+		}
+		break;
+	case ISPASYNC_DEV_GONE:
+		lp = arg;
+		if (lp->ini_map_idx) {
+			tgt = lp->ini_map_idx - 1;
+			isp_prt(isp, ISP_LOGCONFIG, prom2,
+			    lp->portid, lp->handle,
+		            roles[lp->roles & 0x3], "departed from", tgt,
+		    	    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
+#if __FreeBSD_version >= 500000  
+			ISPLOCK_2_CAMLOCK(isp);
+			if (xpt_create_path(&tmppath, NULL,
+			    cam_sim_path(isp->isp_sim), tgt,
+			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+				CAMLOCK_2_ISPLOCK(isp);
+				break;
+			}
+			xpt_async(AC_LOST_DEVICE, tmppath, NULL);
+			xpt_free_path(tmppath);
+			CAMLOCK_2_ISPLOCK(isp);
+#endif
+		} else {
+			isp_prt(isp, ISP_LOGCONFIG, prom,
+			    lp->portid, lp->handle,
+		            roles[lp->roles & 0x3], "departed",
+		    	    (uint32_t) (lp->node_wwn >> 32),
+			    (uint32_t) lp->node_wwn,
+		    	    (uint32_t) (lp->port_wwn >> 32),
+			    (uint32_t) lp->port_wwn);
+		}
+		break;
+	case ISPASYNC_CHANGE_NOTIFY:
+	{
+		char *msg;
+		if (arg == ISPASYNC_CHANGE_PDB) {
+			msg = "Port Database Changed";
+		} else if (arg == ISPASYNC_CHANGE_SNS) {
+			msg = "Name Server Database Changed";
+		} else {
+			msg = "Other Change Notify";
+		}
+		isp_prt(isp, ISP_LOGINFO, msg);
+		isp_freeze_loopdown(isp, msg);
 #if __FreeBSD_version < 500000  
 		wakeup(&isp->isp_osinfo.kproc);
 #else
@@ -2939,117 +3047,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
 #endif
 #endif
 		break;
-	case ISPASYNC_FABRIC_DEV:
-	{
-		int target, base, lim;
-		fcparam *fcp = isp->isp_param;
-		struct lportdb *lp = NULL;
-		struct lportdb *clp = (struct lportdb *) arg;
-		char *pt;
-
-		switch (clp->port_type) {
-		case 1:
-			pt = "   N_Port";
-			break;
-		case 2:
-			pt = "  NL_Port";
-			break;
-		case 3:
-			pt = "F/NL_Port";
-			break;
-		case 0x7f:
-			pt = "  Nx_Port";
-			break;
-		case 0x81:
-			pt = "  F_port";
-			break;
-		case 0x82:
-			pt = "  FL_Port";
-			break;
-		case 0x84:
-			pt = "   E_port";
-			break;
-		default:
-			pt = " ";
-			break;
-		}
-
-		isp_prt(isp, ISP_LOGINFO,
-		    "%s Fabric Device @ PortID 0x%x", pt, clp->portid);
-
-		/*
-		 * If we don't have an initiator role we bail.
-		 *
-		 * We just use ISPASYNC_FABRIC_DEV for announcement purposes.
-		 */
-
-		if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
-			break;
-		}
-
-		/*
-		 * Is this entry for us? If so, we bail.
-		 */
-
-		if (fcp->isp_portid == clp->portid) {
-			break;
-		}
-
-		/*
-		 * Else, the default policy is to find room for it in
-		 * our local port database. Later, when we execute
-		 * the call to isp_pdb_sync either this newly arrived
-		 * or already logged in device will be (re)announced.
-		 */
-
-		if (fcp->isp_topo == TOPO_FL_PORT)
-			base = FC_SNS_ID+1;
-		else
-			base = 0;
-
-		if (fcp->isp_topo == TOPO_N_PORT)
-			lim = 1;
-		else
-			lim = MAX_FC_TARG;
-
-		/*
-		 * Is it already in our list?
-		 */
-		for (target = base; target < lim; target++) {
-			if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
-				continue;
-			}
-			lp = &fcp->portdb[target];
-			if (lp->port_wwn == clp->port_wwn &&
-			    lp->node_wwn == clp->node_wwn) {
-				lp->fabric_dev = 1;
-				break;
-			}
-		}
-		if (target < lim) {
-			break;
-		}
-		for (target = base; target < lim; target++) {
-			if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
-				continue;
-			}
-			lp = &fcp->portdb[target];
-			if (lp->port_wwn == 0) {
-				break;
-			}
-		}
-		if (target == lim) {
-			isp_prt(isp, ISP_LOGWARN,
-			    "out of space for fabric devices");
-			break;
-		}
-		lp->port_type = clp->port_type;
-		lp->fc4_type = clp->fc4_type;
-		lp->node_wwn = clp->node_wwn;
-		lp->port_wwn = clp->port_wwn;
-		lp->portid = clp->portid;
-		lp->fabric_dev = 1;
-		break;
 	}
 #ifdef	ISP_TARGET_MODE
 	case ISPASYNC_TARGET_NOTIFY:
@@ -3136,8 +3133,12 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
 void
 isp_uninit(ispsoftc_t *isp)
 {
-	ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
-	DISABLE_INTS(isp);
+	if (IS_24XX(isp)) {
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
+	} else {
+		ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
+	}
+	ISP_DISABLE_INTS(isp);
 }
 
 void
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 6b8013707964..2a96d5d057df 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -149,13 +149,16 @@ struct isposinfo {
 	struct cam_sim		*sim2;
 	struct cam_path		*path2;
 	struct intr_config_hook	ehook;
-	uint8_t
+	uint16_t		loop_down_time;
+	uint16_t		loop_down_limit;
+	uint32_t		: 5,
+		simqfrozen	: 3,
+		hysteresis	: 8,
+				: 4,
 		disabled	: 1,
 		fcbsy		: 1,
-		ktmature	: 1,
-		mboxwaiting	: 1,
-		intsok		: 1,
-		simqfrozen	: 3;
+		mboxcmd_done	: 1,
+		mboxbsy		: 1;
 #if __FreeBSD_version >= 500000  
 	struct firmware *	fw;
 	struct mtx		lock;
@@ -211,18 +214,13 @@ struct isposinfo {
  * Required Macros/Defines
  */
 
-#define	ISP2100_SCRLEN		0x800
+#define	ISP2100_SCRLEN		0x1000
 
 #define	MEMZERO(a, b)		memset(a, 0, b)
 #define	MEMCPY			memcpy
 #define	SNPRINTF		snprintf
 #define	USEC_DELAY		DELAY
-#define	USEC_SLEEP(isp, x)		\
-	if (isp->isp_osinfo.intsok)	\
-		ISP_UNLOCK(isp);	\
-	DELAY(x);			\
-	if (isp->isp_osinfo.intsok)	\
-		ISP_LOCK(isp)
+#define	USEC_SLEEP(isp, x)	DELAY(x)
 
 #define	NANOTIME_T		struct timespec
 #define	GET_NANOTIME		nanotime
@@ -247,15 +245,10 @@ default:							\
 	break;							\
 }
 
-#define	MBOX_ACQUIRE(isp)
+#define	MBOX_ACQUIRE			isp_mbox_acquire
 #define	MBOX_WAIT_COMPLETE		isp_mbox_wait_complete
-#define	MBOX_NOTIFY_COMPLETE(isp)	\
-	if (isp->isp_osinfo.mboxwaiting) { \
-		isp->isp_osinfo.mboxwaiting = 0; \
-		wakeup(&isp->isp_mbxworkp); \
-	} \
-	isp->isp_mboxbsy = 0
-#define	MBOX_RELEASE(isp)
+#define	MBOX_NOTIFY_COMPLETE(isp)	isp->isp_osinfo.mboxcmd_done = 1
+#define	MBOX_RELEASE			isp_mbox_release
 
 #define	FC_SCRATCH_ACQUIRE(isp)						\
 	if (isp->isp_osinfo.fcbsy) {					\
@@ -361,7 +354,8 @@ default:							\
 #define	ISP_IOXGET_32(isp, s, d)				\
 	d = (isp->isp_bustype == ISP_BT_SBUS)?			\
 	*((uint32_t *)s) : bswap32(*((uint32_t *)s))
-#else
+
+#else	/* ISP_SBUS_SUPPORTED */
 #define	ISP_IOXPUT_8(isp, s, d)		*(d) = s
 #define	ISP_IOXPUT_16(isp, s, d)	*(d) = bswap16(s)
 #define	ISP_IOXPUT_32(isp, s, d)	*(d) = bswap32(s)
@@ -370,6 +364,15 @@ default:							\
 #define	ISP_IOXGET_32(isp, s, d)	d = bswap32(*((uint32_t *)s))
 #endif
 #define	ISP_SWIZZLE_NVRAM_WORD(isp, rp)	*rp = bswap16(*rp)
+
+#define	ISP_IOZGET_8(isp, s, d)		d = (*((uint8_t *)s))
+#define	ISP_IOZGET_16(isp, s, d)	d = (*((uint16_t *)s))
+#define	ISP_IOZGET_32(isp, s, d)	d = (*((uint32_t *)s))
+#define	ISP_IOZPUT_8(isp, s, d)		*(d) = s
+#define	ISP_IOZPUT_16(isp, s, d)	*(d) = s
+#define	ISP_IOZPUT_32(isp, s, d)	*(d) = s
+
+
 #else
 #define	ISP_IOXPUT_8(isp, s, d)		*(d) = s
 #define	ISP_IOXPUT_16(isp, s, d)	*(d) = s
@@ -378,6 +381,15 @@ default:							\
 #define	ISP_IOXGET_16(isp, s, d)	d = *(s)
 #define	ISP_IOXGET_32(isp, s, d)	d = *(s)
 #define	ISP_SWIZZLE_NVRAM_WORD(isp, rp)
+
+#define	ISP_IOZPUT_8(isp, s, d)		*(d) = s
+#define	ISP_IOZPUT_16(isp, s, d)	*(d) = bswap16(s)
+#define	ISP_IOZPUT_32(isp, s, d)	*(d) = bswap32(s)
+
+#define	ISP_IOZGET_8(isp, s, d)		d = (*((uint8_t *)(s)))
+#define	ISP_IOZGET_16(isp, s, d)	d = bswap16(*((uint16_t *)(s)))
+#define	ISP_IOZGET_32(isp, s, d)	d = bswap32(*((uint32_t *)(s)))
+
 #endif
 
 /*
@@ -417,6 +429,9 @@ extern void isp_uninit(ispsoftc_t *);
  * driver global data
  */
 extern int isp_announced;
+extern int isp_fabric_hysteresis;
+extern int isp_loop_down_limit;
+extern int isp_quickboot_time;
 
 /*
  * Platform private flags
@@ -444,49 +459,61 @@ extern int isp_announced;
  * Platform specific inline functions
  */
 
-static __inline void isp_mbox_wait_complete(ispsoftc_t *);
-static __inline void
-isp_mbox_wait_complete(ispsoftc_t *isp)
+static __inline int isp_mbox_acquire(ispsoftc_t *);
+static __inline void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *);
+static __inline void isp_mbox_release(ispsoftc_t *);
+
+static __inline int
+isp_mbox_acquire(ispsoftc_t *isp)
 {
-	if (isp->isp_osinfo.intsok) {
-		int lim = ((isp->isp_mbxwrk0)? 120 : 20) * hz;
-		isp->isp_osinfo.mboxwaiting = 1;
-#ifdef	ISP_SMPLOCK
-		(void) msleep(&isp->isp_mbxworkp,
-		    &isp->isp_lock, PRIBIO, "isp_mboxwaiting", lim);
-#else
-		(void) tsleep(&isp->isp_mbxworkp,
-		    PRIBIO, "isp_mboxwaiting", lim);
-#endif
-		if (isp->isp_mboxbsy != 0) {
-			isp_prt(isp, ISP_LOGWARN,
-			    "Interrupting Mailbox Command (0x%x) Timeout",
-			    isp->isp_lastmbxcmd);
-			isp->isp_mboxbsy = 0;
-		}
-		isp->isp_osinfo.mboxwaiting = 0;
+	if (isp->isp_osinfo.mboxbsy) {
+		return (1);
 	} else {
-		int lim = ((isp->isp_mbxwrk0)? 240 : 60) * 10000;
-		int j;
-		for (j = 0; j < lim; j++) {
-			uint16_t isr, sema, mbox;
-			if (isp->isp_mboxbsy == 0) {
+		isp->isp_osinfo.mboxcmd_done = 0;
+		isp->isp_osinfo.mboxbsy = 1;
+		return (0);
+	}
+}
+
+static __inline void
+isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
+{
+	int lim = mbp->timeout;
+	int j;
+
+	if (lim == 0) {
+		lim = MBCMD_DEFAULT_TIMEOUT;
+	}
+	if (isp->isp_mbxwrk0) {
+		lim *= isp->isp_mbxwrk0;
+	}
+	for (j = 0; j < lim; j += 100) {
+		uint32_t isr;
+		uint16_t sema, mbox;
+		if (isp->isp_osinfo.mboxcmd_done) {
+			break;
+		}
+		if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
+			isp_intr(isp, isr, sema, mbox);
+			if (isp->isp_osinfo.mboxcmd_done) {
 				break;
 			}
-			if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
-				isp_intr(isp, isr, sema, mbox);
-				if (isp->isp_mboxbsy == 0) {
-					break;
-				}
-			}
-			USEC_DELAY(500);
-		}
-		if (isp->isp_mboxbsy != 0) {
-			isp_prt(isp, ISP_LOGWARN,
-			    "Polled Mailbox Command (0x%x) Timeout",
-			    isp->isp_lastmbxcmd);
 		}
+		USEC_DELAY(100);
 	}
+	if (isp->isp_osinfo.mboxcmd_done == 0) {
+		isp_prt(isp, ISP_LOGWARN,
+		    "Polled Mailbox Command (0x%x) Timeout",
+		    isp->isp_lastmbxcmd);
+		mbp->param[0] = MBOX_TIMEOUT;
+		isp->isp_osinfo.mboxcmd_done = 1;
+	}
+}
+
+static __inline void
+isp_mbox_release(ispsoftc_t *isp)
+{
+	isp->isp_osinfo.mboxbsy = 0;
 }
 
 static __inline uint64_t nanotime_sub(struct timespec *, struct timespec *);
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index 298197f25b8a..072d7267aebf 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -46,11 +46,11 @@ __FBSDID("$FreeBSD$");
 #endif
 
 int
-isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint16_t *handlep)
+isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint32_t *handlep)
 {
-	int i, j;
+	uint16_t i, j;
 
-	for (j = isp->isp_lasthdls, i = 0; i < (int) isp->isp_maxcmds; i++) {
+	for (j = isp->isp_lasthdls, i = 0; i < isp->isp_maxcmds; i++) {
 		if (isp->isp_xflist[j] == NULL) {
 			break;
 		}
@@ -63,63 +63,58 @@ isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint16_t *handlep)
 	}
 	isp->isp_xflist[j] = xs;
 	*handlep = j+1;
-	if (++j == isp->isp_maxcmds)
+	if (++j == isp->isp_maxcmds) {
 		j = 0;
-	isp->isp_lasthdls = (uint16_t)j;
+	}
+	isp->isp_lasthdls = (uint32_t)j;
 	return (0);
 }
 
 XS_T *
-isp_find_xs(ispsoftc_t *isp, uint16_t handle)
+isp_find_xs(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle < 1 || handle > (uint16_t) isp->isp_maxcmds) {
+	if (handle < 1 || handle > (uint32_t) isp->isp_maxcmds) {
 		return (NULL);
 	} else {
 		return (isp->isp_xflist[handle - 1]);
 	}
 }
 
-uint16_t
+uint32_t
 isp_find_handle(ispsoftc_t *isp, XS_T *xs)
 {
-	int i;
+	uint16_t i;
 	if (xs != NULL) {
 		for (i = 0; i < isp->isp_maxcmds; i++) {
 			if (isp->isp_xflist[i] == xs) {
-				return ((uint16_t) i+1);
+				return ((uint32_t) (i+1));
 			}
 		}
 	}
 	return (0);
 }
 
-int
-isp_handle_index(uint16_t handle)
+uint32_t
+isp_handle_index(uint32_t handle)
 {
-	return (handle-1);
-}
-
-uint16_t
-isp_index_handle(int index)
-{
-	return (index+1);
+	return (handle - 1);
 }
 
 void
-isp_destroy_handle(ispsoftc_t *isp, uint16_t handle)
+isp_destroy_handle(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle > 0 && handle <= (uint16_t) isp->isp_maxcmds) {
+	if (handle > 0 && handle <= (uint32_t) isp->isp_maxcmds) {
 		isp->isp_xflist[handle - 1] = NULL;
 	}
 }
 
 int
-isp_getrqentry(ispsoftc_t *isp, uint16_t *iptrp,
-    uint16_t *optrp, void **resultp)
+isp_getrqentry(ispsoftc_t *isp, uint32_t *iptrp,
+    uint32_t *optrp, void **resultp)
 {
-	volatile uint16_t iptr, optr;
+	volatile uint32_t iptr, optr;
 
-	optr = isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp);
+	optr = isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
 	iptr = isp->isp_reqidx;
 	*resultp = ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
 	iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN(isp));
@@ -185,10 +180,6 @@ isp_print_bytes(ispsoftc_t *isp, char *msg, int amt, void *arg)
  * action because things may have changed while we were doing this.
  * Any failure or change of state causes us to return a nonzero value.
  *
- * We honor HBA roles in that if we're not in Initiator mode, we don't
- * attempt to sync up the database (that's for somebody else to do,
- * if ever).
- *
  * We assume we enter here with any locks held.
  */
 
@@ -198,34 +189,72 @@ isp_fc_runstate(ispsoftc_t *isp, int tval)
 	fcparam *fcp;
 	int *tptr;
 
-	if (IS_SCSI(isp))
+        if (isp->isp_role == ISP_ROLE_NONE) {
 		return (0);
-
-	tptr = &tval;
-	if (isp_control(isp, ISPCTL_FCLINK_TEST, tptr) != 0) {
-		return (-1);
 	}
 	fcp = FCPARAM(isp);
-	if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD)
-		return (-1);
-	if (isp_control(isp, ISPCTL_SCAN_FABRIC, NULL) != 0) {
-		return (-1);
-	}
-	if (isp_control(isp, ISPCTL_SCAN_LOOP, NULL) != 0) {
-		return (-1);
+	tptr = &tval;
+	if (fcp->isp_fwstate < FW_READY ||
+	    fcp->isp_loopstate < LOOP_PDB_RCVD) {
+		if (isp_control(isp, ISPCTL_FCLINK_TEST, tptr) != 0) {
+			isp_prt(isp, ISP_LOGINFO,
+			    "isp_fc_runstate: linktest failed");
+			return (-1);
+		}
+		if (fcp->isp_fwstate != FW_READY ||
+		    fcp->isp_loopstate < LOOP_PDB_RCVD) {
+			isp_prt(isp, ISP_LOGINFO,
+				"isp_fc_runstate: f/w not ready");
+			return (-1);
+		}
 	}
 	if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
 		return (0);
 	}
+	if (isp_control(isp, ISPCTL_SCAN_LOOP, NULL) != 0) {
+		isp_prt(isp, ISP_LOGINFO,
+		    "isp_fc_runstate: scan loop fails");
+		return (LOOP_PDB_RCVD);
+	}
+	if (isp_control(isp, ISPCTL_SCAN_FABRIC, NULL) != 0) {
+		isp_prt(isp, ISP_LOGINFO,
+		    "isp_fc_runstate: scan fabric fails");
+		return (LOOP_LSCAN_DONE);
+	}
 	if (isp_control(isp, ISPCTL_PDB_SYNC, NULL) != 0) {
-		return (-1);
+		isp_prt(isp, ISP_LOGINFO, "isp_fc_runstate: pdb_sync fails");
+		return (LOOP_FSCAN_DONE);
 	}
 	if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
+		isp_prt(isp, ISP_LOGINFO,
+		    "isp_fc_runstate: f/w not ready again");
 		return (-1);
 	}
 	return (0);
 }
 
+void
+isp_shutdown(ispsoftc_t *isp)
+{
+	if (IS_FC(isp)) {
+		if (IS_24XX(isp)) {
+			ISP_WRITE(isp, BIU2400_ICR, 0);
+			ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
+		} else {
+			ISP_WRITE(isp, BIU_ICR, 0);
+			ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
+			ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
+			ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
+			ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
+		}
+	} else {
+		ISP_WRITE(isp, BIU_ICR, 0);
+		ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
+	}
+}
+
 /*
  * Functions to move stuff to a form that the QLogic RISC engine understands
  * and functions to move stuff back to a form the processor understands.
@@ -240,11 +269,12 @@ isp_fc_runstate(ispsoftc_t *isp, int tval)
 #define	ISP_IS_SBUS(isp)	\
 	(ISP_SBUS_SUPPORTED && (isp)->isp_bustype == ISP_BT_SBUS)
 
+#define	ASIZE(x)	(sizeof (x) / sizeof (x[0]))
 /*
  * Swizzle/Copy Functions
  */
 void
-isp_copy_out_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst)
+isp_put_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst)
 {
 	if (ISP_IS_SBUS(isp)) {
 		ISP_IOXPUT_8(isp, hpsrc->rqs_entry_type,
@@ -268,7 +298,7 @@ isp_copy_out_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst)
 }
 
 void
-isp_copy_in_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst)
+isp_get_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst)
 {
 	if (ISP_IS_SBUS(isp)) {
 		ISP_IOXGET_8(isp, &hpsrc->rqs_entry_type,
@@ -307,7 +337,7 @@ void
 isp_put_request(ispsoftc_t *isp, ispreq_t *rqsrc, ispreq_t *rqdst)
 {
 	int i;
-	isp_copy_out_hdr(isp, &rqsrc->req_header, &rqdst->req_header);
+	isp_put_hdr(isp, &rqsrc->req_header, &rqdst->req_header);
 	ISP_IOXPUT_32(isp, rqsrc->req_handle, &rqdst->req_handle);
 	if (ISP_IS_SBUS(isp)) {
 		ISP_IOXPUT_8(isp, rqsrc->req_lun_trn, &rqdst->req_target);
@@ -320,7 +350,7 @@ isp_put_request(ispsoftc_t *isp, ispreq_t *rqsrc, ispreq_t *rqdst)
 	ISP_IOXPUT_16(isp, rqsrc->req_flags, &rqdst->req_flags);
 	ISP_IOXPUT_16(isp, rqsrc->req_time, &rqdst->req_time);
 	ISP_IOXPUT_16(isp, rqsrc->req_seg_count, &rqdst->req_seg_count);
-	for (i = 0; i < 12; i++) {
+	for (i = 0; i < ASIZE(rqsrc->req_cdb); i++) {
 		ISP_IOXPUT_8(isp, rqsrc->req_cdb[i], &rqdst->req_cdb[i]);
 	}
 	for (i = 0; i < ISP_RQDSEG; i++) {
@@ -332,203 +362,340 @@ isp_put_request(ispsoftc_t *isp, ispreq_t *rqsrc, ispreq_t *rqdst)
 }
 
 void
-isp_put_request_t2(ispsoftc_t *isp, ispreqt2_t *tqsrc, ispreqt2_t *tqdst)
+isp_put_marker(ispsoftc_t *isp, isp_marker_t *src, isp_marker_t *dst)
 {
 	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_8(isp, tqsrc->req_lun_trn, &tqdst->req_lun_trn);
-	ISP_IOXPUT_8(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);
-	}
-}
-
-void
-isp_put_request_t2e(ispsoftc_t *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);
-	}
-}
-
-void
-isp_put_request_t3(ispsoftc_t *isp, ispreqt3_t *tqsrc, ispreqt3_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_8(isp, tqsrc->req_lun_trn, &tqdst->req_lun_trn);
-	ISP_IOXPUT_8(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);
-	}
-}
-
-void
-isp_put_request_t3e(ispsoftc_t *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);
-	}
-}
-
-void
-isp_put_extended_request(ispsoftc_t *isp, ispextreq_t *xqsrc,
-    ispextreq_t *xqdst)
-{
-	int i;
-	isp_copy_out_hdr(isp, &xqsrc->req_header, &xqdst->req_header);
-	ISP_IOXPUT_32(isp, xqsrc->req_handle, &xqdst->req_handle);
+	isp_put_hdr(isp, &src->mrk_header, &dst->mrk_header);
+	ISP_IOXPUT_32(isp, src->mrk_handle, &dst->mrk_handle);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, xqsrc->req_lun_trn, &xqdst->req_target);
-		ISP_IOXPUT_8(isp, xqsrc->req_target, &xqdst->req_lun_trn);
+		ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_target);
+		ISP_IOXPUT_8(isp, src->mrk_target, &dst->mrk_reserved0);
 	} else {
-		ISP_IOXPUT_8(isp, xqsrc->req_lun_trn, &xqdst->req_lun_trn);
-		ISP_IOXPUT_8(isp, xqsrc->req_target, &xqdst->req_target);
+		ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_reserved0);
+		ISP_IOXPUT_8(isp, src->mrk_target, &dst->mrk_target);
 	}
-	ISP_IOXPUT_16(isp, xqsrc->req_cdblen, &xqdst->req_cdblen);
-	ISP_IOXPUT_16(isp, xqsrc->req_flags, &xqdst->req_flags);
-	ISP_IOXPUT_16(isp, xqsrc->req_time, &xqdst->req_time);
-	ISP_IOXPUT_16(isp, xqsrc->req_seg_count, &xqdst->req_seg_count);
-	for (i = 0; i < 44; i++) {
-		ISP_IOXPUT_8(isp, xqsrc->req_cdb[i], &xqdst->req_cdb[i]);
+	ISP_IOXPUT_16(isp, src->mrk_modifier, &dst->mrk_modifier);
+	ISP_IOXPUT_16(isp, src->mrk_flags, &dst->mrk_flags);
+	ISP_IOXPUT_16(isp, src->mrk_lun, &dst->mrk_lun);
+	for (i = 0; i < ASIZE(src->mrk_reserved1); i++) {
+		ISP_IOXPUT_8(isp, src->mrk_reserved1[i],
+		    &dst->mrk_reserved1[i]);
 	}
 }
 
 void
-isp_put_cont_req(ispsoftc_t *isp, ispcontreq_t *cqsrc, ispcontreq_t *cqdst)
+isp_put_marker_24xx(ispsoftc_t *isp,
+    isp_marker_24xx_t *src, isp_marker_24xx_t *dst)
 {
 	int i;
-	isp_copy_out_hdr(isp, &cqsrc->req_header, &cqdst->req_header);
+	isp_put_hdr(isp, &src->mrk_header, &dst->mrk_header);
+	ISP_IOXPUT_32(isp, src->mrk_handle, &dst->mrk_handle);
+	ISP_IOXPUT_16(isp, src->mrk_nphdl, &dst->mrk_nphdl);
+	ISP_IOXPUT_8(isp, src->mrk_modifier, &dst->mrk_modifier);
+	ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_reserved0);
+	ISP_IOXPUT_8(isp, src->mrk_reserved1, &dst->mrk_reserved1);
+	ISP_IOXPUT_8(isp, src->mrk_vphdl, &dst->mrk_vphdl);
+	ISP_IOXPUT_8(isp, src->mrk_reserved2, &dst->mrk_reserved2);
+	for (i = 0; i < ASIZE(src->mrk_lun); i++) {
+		ISP_IOXPUT_8(isp, src->mrk_lun[i], &dst->mrk_lun[i]);
+	}
+	for (i = 0; i < ASIZE(src->mrk_reserved3); i++) {
+		ISP_IOXPUT_8(isp, src->mrk_reserved3[i],
+		    &dst->mrk_reserved3[i]);
+	}
+}
+
+void
+isp_put_request_t2(ispsoftc_t *isp, ispreqt2_t *src, ispreqt2_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle);
+	ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn);
+	ISP_IOXPUT_8(isp, src->req_target, &dst->req_target);
+	ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun);
+	ISP_IOXPUT_16(isp, src->req_flags,  &dst->req_flags);
+	ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved);
+	ISP_IOXPUT_16(isp, src->req_time, &dst->req_time);
+	ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count);
+	for (i = 0; i < ASIZE(src->req_cdb); i++) {
+		ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]);
+	}
+	ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
+	for (i = 0; i < ISP_RQDSEG_T2; i++) {
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
+		    &dst->req_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
+		    &dst->req_dataseg[i].ds_count);
+	}
+}
+
+void
+isp_put_request_t2e(ispsoftc_t *isp, ispreqt2e_t *src, ispreqt2e_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle);
+	ISP_IOXPUT_16(isp, src->req_target, &dst->req_target);
+	ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun);
+	ISP_IOXPUT_16(isp, src->req_flags,  &dst->req_flags);
+	ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved);
+	ISP_IOXPUT_16(isp, src->req_time, &dst->req_time);
+	ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count);
+	for (i = 0; i < ASIZE(src->req_cdb); i++) {
+		ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]);
+	}
+	ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
+	for (i = 0; i < ISP_RQDSEG_T2; i++) {
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
+		    &dst->req_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
+		    &dst->req_dataseg[i].ds_count);
+	}
+}
+
+void
+isp_put_request_t3(ispsoftc_t *isp, ispreqt3_t *src, ispreqt3_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle);
+	ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn);
+	ISP_IOXPUT_8(isp, src->req_target, &dst->req_target);
+	ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun);
+	ISP_IOXPUT_16(isp, src->req_flags,  &dst->req_flags);
+	ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved);
+	ISP_IOXPUT_16(isp, src->req_time, &dst->req_time);
+	ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count);
+	for (i = 0; i < ASIZE(src->req_cdb); i++) {
+		ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]);
+	}
+	ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
+	for (i = 0; i < ISP_RQDSEG_T3; i++) {
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
+		    &dst->req_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi,
+		    &dst->req_dataseg[i].ds_basehi);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
+		    &dst->req_dataseg[i].ds_count);
+	}
+}
+
+void
+isp_put_request_t3e(ispsoftc_t *isp, ispreqt3e_t *src, ispreqt3e_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle);
+	ISP_IOXPUT_16(isp, src->req_target, &dst->req_target);
+	ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun);
+	ISP_IOXPUT_16(isp, src->req_flags,  &dst->req_flags);
+	ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved);
+	ISP_IOXPUT_16(isp, src->req_time, &dst->req_time);
+	ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count);
+	for (i = 0; i < ASIZE(src->req_cdb); i++) {
+		ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]);
+	}
+	ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
+	for (i = 0; i < ISP_RQDSEG_T3; i++) {
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
+		    &dst->req_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi,
+		    &dst->req_dataseg[i].ds_basehi);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
+		    &dst->req_dataseg[i].ds_count);
+	}
+}
+
+void
+isp_put_extended_request(ispsoftc_t *isp, ispextreq_t *src, ispextreq_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle);
+	if (ISP_IS_SBUS(isp)) {
+		ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_target);
+		ISP_IOXPUT_8(isp, src->req_target, &dst->req_lun_trn);
+	} else {
+		ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn);
+		ISP_IOXPUT_8(isp, src->req_target, &dst->req_target);
+	}
+	ISP_IOXPUT_16(isp, src->req_cdblen, &dst->req_cdblen);
+	ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags);
+	ISP_IOXPUT_16(isp, src->req_time, &dst->req_time);
+	ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count);
+	for (i = 0; i < ASIZE(src->req_cdb); i++) {
+		ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]);
+	}
+}
+
+void
+isp_put_request_t7(ispsoftc_t *isp, ispreqt7_t *src, ispreqt7_t *dst)
+{
+	int i;
+	uint32_t *a, *b;
+
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle);
+	ISP_IOXPUT_16(isp, src->req_nphdl, &dst->req_nphdl);
+	ISP_IOXPUT_16(isp, src->req_time, &dst->req_time);
+	ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count);
+	ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved);
+	a = (uint32_t *) src->req_lun;
+	b = (uint32_t *) dst->req_lun;
+	for (i = 0; i < (ASIZE(src->req_lun) >> 2); i++ ) {
+		ISP_IOZPUT_32(isp, *a++, b++);
+	}
+	ISP_IOXPUT_8(isp, src->req_alen_datadir, &dst->req_alen_datadir);
+	ISP_IOXPUT_8(isp, src->req_task_management, &dst->req_task_management);
+	ISP_IOXPUT_8(isp, src->req_task_attribute, &dst->req_task_attribute);
+	ISP_IOXPUT_8(isp, src->req_crn, &dst->req_crn);
+	a = (uint32_t *) src->req_cdb;
+	b = (uint32_t *) dst->req_cdb;
+	for (i = 0; i < (ASIZE(src->req_cdb) >> 2); i++ ) {
+		ISP_IOZPUT_32(isp, *a++, b++);
+	}
+	ISP_IOXPUT_32(isp, src->req_dl, &dst->req_dl);
+	ISP_IOXPUT_16(isp, src->req_tidlo, &dst->req_tidlo);
+	ISP_IOXPUT_8(isp, src->req_tidhi, &dst->req_tidhi);
+	ISP_IOXPUT_8(isp, src->req_vpidx, &dst->req_vpidx);
+	ISP_IOXPUT_32(isp, src->req_dataseg.ds_base,
+	    &dst->req_dataseg.ds_base);
+	ISP_IOXPUT_32(isp, src->req_dataseg.ds_basehi,
+	    &dst->req_dataseg.ds_basehi);
+	ISP_IOXPUT_32(isp, src->req_dataseg.ds_count,
+	    &dst->req_dataseg.ds_count);
+}
+
+void
+isp_put_24xx_abrt(ispsoftc_t *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->abrt_header, &dst->abrt_header);
+	ISP_IOXPUT_32(isp, src->abrt_handle, &dst->abrt_handle);
+	ISP_IOXPUT_16(isp, src->abrt_nphdl, &dst->abrt_nphdl);
+	ISP_IOXPUT_16(isp, src->abrt_options, &dst->abrt_options);
+	ISP_IOXPUT_32(isp, src->abrt_cmd_handle, &dst->abrt_cmd_handle);
+	for (i = 0; i < ASIZE(src->abrt_reserved); i++) {
+		ISP_IOXPUT_8(isp, src->abrt_reserved[i],
+		    &dst->abrt_reserved[i]);
+	}
+	ISP_IOXPUT_16(isp, src->abrt_tidlo, &dst->abrt_tidlo);
+	ISP_IOXPUT_8(isp, src->abrt_tidhi, &dst->abrt_tidhi);
+	ISP_IOXPUT_8(isp, src->abrt_vpidx, &dst->abrt_vpidx);
+	for (i = 0; i < ASIZE(src->abrt_reserved1); i++) {
+		ISP_IOXPUT_8(isp, src->abrt_reserved1[i],
+		    &dst->abrt_reserved1[i]);
+	}
+}
+
+void
+isp_put_cont_req(ispsoftc_t *isp, ispcontreq_t *src, ispcontreq_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
 	for (i = 0; i < ISP_CDSEG; i++) {
-		ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_base,
-		    &cqdst->req_dataseg[i].ds_base);
-		ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_count,
-		    &cqdst->req_dataseg[i].ds_count);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
+		    &dst->req_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
+		    &dst->req_dataseg[i].ds_count);
 	}
 }
 
 void
-isp_put_cont64_req(ispsoftc_t *isp, ispcontreq64_t *cqsrc,
-    ispcontreq64_t *cqdst)
+isp_put_cont64_req(ispsoftc_t *isp, ispcontreq64_t *src, ispcontreq64_t *dst)
 {
 	int i;
-	isp_copy_out_hdr(isp, &cqsrc->req_header, &cqdst->req_header);
+	isp_put_hdr(isp, &src->req_header, &dst->req_header);
 	for (i = 0; i < ISP_CDSEG64; i++) {
-		ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_base,
-		    &cqdst->req_dataseg[i].ds_base);
-		ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_basehi,
-		    &cqdst->req_dataseg[i].ds_basehi);
-		ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_count,
-		    &cqdst->req_dataseg[i].ds_count);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
+		    &dst->req_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi,
+		    &dst->req_dataseg[i].ds_basehi);
+		ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
+		    &dst->req_dataseg[i].ds_count);
 	}
 }
 
 void
-isp_get_response(ispsoftc_t *isp, ispstatusreq_t *spsrc,
-    ispstatusreq_t *spdst)
+isp_get_response(ispsoftc_t *isp, ispstatusreq_t *src, ispstatusreq_t *dst)
 {
 	int i;
-	isp_copy_in_hdr(isp, &spsrc->req_header, &spdst->req_header);
-	ISP_IOXGET_32(isp, &spsrc->req_handle, spdst->req_handle);
-	ISP_IOXGET_16(isp, &spsrc->req_scsi_status, spdst->req_scsi_status);
-	ISP_IOXGET_16(isp, &spsrc->req_completion_status,
-	    spdst->req_completion_status);
-	ISP_IOXGET_16(isp, &spsrc->req_state_flags, spdst->req_state_flags);
-	ISP_IOXGET_16(isp, &spsrc->req_status_flags, spdst->req_status_flags);
-	ISP_IOXGET_16(isp, &spsrc->req_time, spdst->req_time);
-	ISP_IOXGET_16(isp, &spsrc->req_sense_len, spdst->req_sense_len);
-	ISP_IOXGET_32(isp, &spsrc->req_resid, spdst->req_resid);
+	isp_get_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle);
+	ISP_IOXGET_16(isp, &src->req_scsi_status, dst->req_scsi_status);
+	ISP_IOXGET_16(isp, &src->req_completion_status,
+	    dst->req_completion_status);
+	ISP_IOXGET_16(isp, &src->req_state_flags, dst->req_state_flags);
+	ISP_IOXGET_16(isp, &src->req_status_flags, dst->req_status_flags);
+	ISP_IOXGET_16(isp, &src->req_time, dst->req_time);
+	ISP_IOXGET_16(isp, &src->req_sense_len, dst->req_sense_len);
+	ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid);
 	for (i = 0; i < 8; i++) {
-		ISP_IOXGET_8(isp, &spsrc->req_response[i],
-		    spdst->req_response[i]);
+		ISP_IOXGET_8(isp, &src->req_response[i],
+		    dst->req_response[i]);
 	}
 	for (i = 0; i < 32; i++) {
-		ISP_IOXGET_8(isp, &spsrc->req_sense_data[i],
-		    spdst->req_sense_data[i]);
+		ISP_IOXGET_8(isp, &src->req_sense_data[i],
+		    dst->req_sense_data[i]);
 	}
 }
 
 void
-isp_get_response_x(ispsoftc_t *isp, ispstatus_cont_t *cpsrc,
-    ispstatus_cont_t *cpdst)
+isp_get_24xx_response(ispsoftc_t *isp, isp24xx_statusreq_t *src,
+    isp24xx_statusreq_t *dst)
 {
 	int i;
-	isp_copy_in_hdr(isp, &cpsrc->req_header, &cpdst->req_header);
-	for (i = 0; i < 60; i++) {
-		ISP_IOXGET_8(isp, &cpsrc->req_sense_data[i],
-		    cpdst->req_sense_data[i]);
+	isp_get_hdr(isp, &src->req_header, &dst->req_header);
+	ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle);
+	ISP_IOXGET_16(isp, &src->req_completion_status,
+	    dst->req_completion_status);
+	ISP_IOXGET_16(isp, &src->req_oxid, dst->req_oxid);
+	ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid);
+	ISP_IOXGET_16(isp, &src->req_reserved0, dst->req_reserved0);
+	ISP_IOXGET_16(isp, &src->req_state_flags, dst->req_state_flags);
+	ISP_IOXGET_16(isp, &src->req_reserved1, dst->req_reserved1);
+	ISP_IOXGET_16(isp, &src->req_scsi_status, dst->req_scsi_status);
+	ISP_IOXGET_32(isp, &src->req_fcp_residual, dst->req_fcp_residual);
+	ISP_IOXGET_32(isp, &src->req_sense_len, dst->req_sense_len);
+	ISP_IOXGET_32(isp, &src->req_response_len, dst->req_response_len);
+	for (i = 0; i < 28; i++) {
+		ISP_IOXGET_8(isp, &src->req_rsp_sense[i],
+		    dst->req_rsp_sense[i]);
 	}
 }
 
+void
+isp_get_24xx_abrt(ispsoftc_t *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst)
+{
+	int i;
+	isp_get_hdr(isp, &src->abrt_header, &dst->abrt_header);
+	ISP_IOXGET_32(isp, &src->abrt_handle, dst->abrt_handle);
+	ISP_IOXGET_16(isp, &src->abrt_nphdl, dst->abrt_nphdl);
+	ISP_IOXGET_16(isp, &src->abrt_options, dst->abrt_options);
+	ISP_IOXGET_32(isp, &src->abrt_cmd_handle, dst->abrt_cmd_handle);
+	for (i = 0; i < ASIZE(&src->abrt_reserved); i++) {
+		ISP_IOXGET_8(isp, &src->abrt_reserved[i],
+		    dst->abrt_reserved[i]);
+	}
+	ISP_IOXGET_16(isp, &src->abrt_tidlo, dst->abrt_tidlo);
+	ISP_IOXGET_8(isp, &src->abrt_tidhi, dst->abrt_tidhi);
+	ISP_IOXGET_8(isp, &src->abrt_vpidx, dst->abrt_vpidx);
+	for (i = 0; i < ASIZE(&src->abrt_reserved1); i++) {
+		ISP_IOXGET_8(isp, &src->abrt_reserved1[i],
+		    dst->abrt_reserved1[i]);
+	}
+}
+
+
 void
 isp_get_rio2(ispsoftc_t *isp, isp_rio2_t *r2src, isp_rio2_t *r2dst)
 {
 	int i;
-	isp_copy_in_hdr(isp, &r2src->req_header, &r2dst->req_header);
-	if (r2dst->req_header.rqs_seqno > 30)
+	isp_get_hdr(isp, &r2src->req_header, &r2dst->req_header);
+	if (r2dst->req_header.rqs_seqno > 30) {
 		r2dst->req_header.rqs_seqno = 30;
+	}
 	for (i = 0; i < r2dst->req_header.rqs_seqno; i++) {
 		ISP_IOXGET_16(isp, &r2src->req_handles[i],
 		    r2dst->req_handles[i]);
@@ -539,73 +706,128 @@ isp_get_rio2(ispsoftc_t *isp, isp_rio2_t *r2src, isp_rio2_t *r2dst)
 }
 
 void
-isp_put_icb(ispsoftc_t *isp, isp_icb_t *Is, isp_icb_t *Id)
+isp_put_icb(ispsoftc_t *isp, isp_icb_t *src, isp_icb_t *dst)
 {
 	int i;
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, Is->icb_version, &Id->_reserved0);
-		ISP_IOXPUT_8(isp, Is->_reserved0, &Id->icb_version);
+		ISP_IOXPUT_8(isp, src->icb_version, &dst->icb_reserved0);
+		ISP_IOXPUT_8(isp, src->icb_reserved0, &dst->icb_version);
 	} else {
-		ISP_IOXPUT_8(isp, Is->icb_version, &Id->icb_version);
-		ISP_IOXPUT_8(isp, Is->_reserved0, &Id->_reserved0);
+		ISP_IOXPUT_8(isp, src->icb_version, &dst->icb_version);
+		ISP_IOXPUT_8(isp, src->icb_reserved0, &dst->icb_reserved0);
 	}
-	ISP_IOXPUT_16(isp, Is->icb_fwoptions, &Id->icb_fwoptions);
-	ISP_IOXPUT_16(isp, Is->icb_maxfrmlen, &Id->icb_maxfrmlen);
-	ISP_IOXPUT_16(isp, Is->icb_maxalloc, &Id->icb_maxalloc);
-	ISP_IOXPUT_16(isp, Is->icb_execthrottle, &Id->icb_execthrottle);
+	ISP_IOXPUT_16(isp, src->icb_fwoptions, &dst->icb_fwoptions);
+	ISP_IOXPUT_16(isp, src->icb_maxfrmlen, &dst->icb_maxfrmlen);
+	ISP_IOXPUT_16(isp, src->icb_maxalloc, &dst->icb_maxalloc);
+	ISP_IOXPUT_16(isp, src->icb_execthrottle, &dst->icb_execthrottle);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, Is->icb_retry_count, &Id->icb_retry_delay);
-		ISP_IOXPUT_8(isp, Is->icb_retry_delay, &Id->icb_retry_count);
+		ISP_IOXPUT_8(isp, src->icb_retry_count, &dst->icb_retry_delay);
+		ISP_IOXPUT_8(isp, src->icb_retry_delay, &dst->icb_retry_count);
 	} else {
-		ISP_IOXPUT_8(isp, Is->icb_retry_count, &Id->icb_retry_count);
-		ISP_IOXPUT_8(isp, Is->icb_retry_delay, &Id->icb_retry_delay);
+		ISP_IOXPUT_8(isp, src->icb_retry_count, &dst->icb_retry_count);
+		ISP_IOXPUT_8(isp, src->icb_retry_delay, &dst->icb_retry_delay);
 	}
 	for (i = 0; i < 8; i++) {
-		ISP_IOXPUT_8(isp, Is->icb_portname[i], &Id->icb_portname[i]);
+		ISP_IOXPUT_8(isp, src->icb_portname[i], &dst->icb_portname[i]);
 	}
-	ISP_IOXPUT_16(isp, Is->icb_hardaddr, &Id->icb_hardaddr);
+	ISP_IOXPUT_16(isp, src->icb_hardaddr, &dst->icb_hardaddr);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, Is->icb_iqdevtype, &Id->icb_logintime);
-		ISP_IOXPUT_8(isp, Is->icb_logintime, &Id->icb_iqdevtype);
+		ISP_IOXPUT_8(isp, src->icb_iqdevtype, &dst->icb_logintime);
+		ISP_IOXPUT_8(isp, src->icb_logintime, &dst->icb_iqdevtype);
 	} else {
-		ISP_IOXPUT_8(isp, Is->icb_iqdevtype, &Id->icb_iqdevtype);
-		ISP_IOXPUT_8(isp, Is->icb_logintime, &Id->icb_logintime);
+		ISP_IOXPUT_8(isp, src->icb_iqdevtype, &dst->icb_iqdevtype);
+		ISP_IOXPUT_8(isp, src->icb_logintime, &dst->icb_logintime);
 	}
 	for (i = 0; i < 8; i++) {
-		ISP_IOXPUT_8(isp, Is->icb_nodename[i], &Id->icb_nodename[i]);
+		ISP_IOXPUT_8(isp, src->icb_nodename[i], &dst->icb_nodename[i]);
 	}
-	ISP_IOXPUT_16(isp, Is->icb_rqstout, &Id->icb_rqstout);
-	ISP_IOXPUT_16(isp, Is->icb_rspnsin, &Id->icb_rspnsin);
-	ISP_IOXPUT_16(isp, Is->icb_rqstqlen, &Id->icb_rqstqlen);
-	ISP_IOXPUT_16(isp, Is->icb_rsltqlen, &Id->icb_rsltqlen);
+	ISP_IOXPUT_16(isp, src->icb_rqstout, &dst->icb_rqstout);
+	ISP_IOXPUT_16(isp, src->icb_rspnsin, &dst->icb_rspnsin);
+	ISP_IOXPUT_16(isp, src->icb_rqstqlen, &dst->icb_rqstqlen);
+	ISP_IOXPUT_16(isp, src->icb_rsltqlen, &dst->icb_rsltqlen);
 	for (i = 0; i < 4; i++) {
-		ISP_IOXPUT_16(isp, Is->icb_rqstaddr[i], &Id->icb_rqstaddr[i]);
+		ISP_IOXPUT_16(isp, src->icb_rqstaddr[i], &dst->icb_rqstaddr[i]);
 	}
 	for (i = 0; i < 4; i++) {
-		ISP_IOXPUT_16(isp, Is->icb_respaddr[i], &Id->icb_respaddr[i]);
+		ISP_IOXPUT_16(isp, src->icb_respaddr[i], &dst->icb_respaddr[i]);
 	}
-	ISP_IOXPUT_16(isp, Is->icb_lunenables, &Id->icb_lunenables);
+	ISP_IOXPUT_16(isp, src->icb_lunenables, &dst->icb_lunenables);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, Is->icb_ccnt, &Id->icb_icnt);
-		ISP_IOXPUT_8(isp, Is->icb_icnt, &Id->icb_ccnt);
+		ISP_IOXPUT_8(isp, src->icb_ccnt, &dst->icb_icnt);
+		ISP_IOXPUT_8(isp, src->icb_icnt, &dst->icb_ccnt);
 	} else {
-		ISP_IOXPUT_8(isp, Is->icb_ccnt, &Id->icb_ccnt);
-		ISP_IOXPUT_8(isp, Is->icb_icnt, &Id->icb_icnt);
+		ISP_IOXPUT_8(isp, src->icb_ccnt, &dst->icb_ccnt);
+		ISP_IOXPUT_8(isp, src->icb_icnt, &dst->icb_icnt);
 	}
-	ISP_IOXPUT_16(isp, Is->icb_lunetimeout, &Id->icb_lunetimeout);
-	ISP_IOXPUT_16(isp, Is->icb_xfwoptions, &Id->icb_xfwoptions);
+	ISP_IOXPUT_16(isp, src->icb_lunetimeout, &dst->icb_lunetimeout);
+	ISP_IOXPUT_16(isp, src->icb_reserved1, &dst->icb_reserved1);
+	ISP_IOXPUT_16(isp, src->icb_xfwoptions, &dst->icb_xfwoptions);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, Is->icb_racctimer, &Id->icb_idelaytimer);
-		ISP_IOXPUT_8(isp, Is->icb_idelaytimer, &Id->icb_racctimer);
+		ISP_IOXPUT_8(isp, src->icb_racctimer, &dst->icb_idelaytimer);
+		ISP_IOXPUT_8(isp, src->icb_idelaytimer, &dst->icb_racctimer);
 	} else {
-		ISP_IOXPUT_8(isp, Is->icb_racctimer, &Id->icb_racctimer);
-		ISP_IOXPUT_8(isp, Is->icb_idelaytimer, &Id->icb_idelaytimer);
+		ISP_IOXPUT_8(isp, src->icb_racctimer, &dst->icb_racctimer);
+		ISP_IOXPUT_8(isp, src->icb_idelaytimer, &dst->icb_idelaytimer);
 	}
-	ISP_IOXPUT_16(isp, Is->icb_zfwoptions, &Id->icb_zfwoptions);
+	ISP_IOXPUT_16(isp, src->icb_zfwoptions, &dst->icb_zfwoptions);
 }
 
 void
-isp_get_pdb(ispsoftc_t *isp, isp_pdb_t *src, isp_pdb_t *dst)
+isp_put_icb_2400(ispsoftc_t *isp, isp_icb_2400_t *src, isp_icb_2400_t *dst)
+{
+	int i;
+	ISP_IOXPUT_16(isp, src->icb_version, &dst->icb_version);
+	ISP_IOXPUT_16(isp, src->icb_reserved0, &dst->icb_reserved0);
+	ISP_IOXPUT_16(isp, src->icb_maxfrmlen, &dst->icb_maxfrmlen);
+	ISP_IOXPUT_16(isp, src->icb_execthrottle, &dst->icb_execthrottle);
+	ISP_IOXPUT_16(isp, src->icb_xchgcnt, &dst->icb_xchgcnt);
+	ISP_IOXPUT_16(isp, src->icb_hardaddr, &dst->icb_hardaddr);
+	for (i = 0; i < 8; i++) {
+		ISP_IOXPUT_8(isp, src->icb_portname[i], &dst->icb_portname[i]);
+	}
+	for (i = 0; i < 8; i++) {
+		ISP_IOXPUT_8(isp, src->icb_nodename[i], &dst->icb_nodename[i]);
+	}
+	ISP_IOXPUT_16(isp, src->icb_rspnsin, &dst->icb_rspnsin);
+	ISP_IOXPUT_16(isp, src->icb_rqstout, &dst->icb_rqstout);
+	ISP_IOXPUT_16(isp, src->icb_retry_count, &dst->icb_retry_count);
+	ISP_IOXPUT_16(isp, src->icb_priout, &dst->icb_priout);
+	ISP_IOXPUT_16(isp, src->icb_rsltqlen, &dst->icb_rsltqlen);
+	ISP_IOXPUT_16(isp, src->icb_rqstqlen, &dst->icb_rqstqlen);
+	ISP_IOXPUT_16(isp, src->icb_ldn_nols, &dst->icb_ldn_nols);
+	ISP_IOXPUT_16(isp, src->icb_prqstqlen, &dst->icb_prqstqlen);
+	for (i = 0; i < 4; i++) {
+		ISP_IOXPUT_16(isp, src->icb_rqstaddr[i], &dst->icb_rqstaddr[i]);
+	}
+	for (i = 0; i < 4; i++) {
+		ISP_IOXPUT_16(isp, src->icb_respaddr[i], &dst->icb_respaddr[i]);
+	}
+	for (i = 0; i < 4; i++) {
+		ISP_IOXPUT_16(isp, src->icb_priaddr[i], &dst->icb_priaddr[i]);
+	}
+	for (i = 0; i < 4; i++) {
+		ISP_IOXPUT_16(isp, src->icb_reserved1[i],
+		    &dst->icb_reserved1[i]);
+	}
+	ISP_IOXPUT_16(isp, src->icb_atio_in, &dst->icb_atio_in);
+	ISP_IOXPUT_16(isp, src->icb_atioqlen, &dst->icb_atioqlen);
+	for (i = 0; i < 4; i++) {
+		ISP_IOXPUT_16(isp, src->icb_atioqaddr[i],
+		    &dst->icb_atioqaddr[i]);
+	}
+	ISP_IOXPUT_16(isp, src->icb_idelaytimer, &dst->icb_idelaytimer);
+	ISP_IOXPUT_16(isp, src->icb_logintime, &dst->icb_logintime);
+	ISP_IOXPUT_32(isp, src->icb_fwoptions1, &dst->icb_fwoptions1);
+	ISP_IOXPUT_32(isp, src->icb_fwoptions2, &dst->icb_fwoptions2);
+	ISP_IOXPUT_32(isp, src->icb_fwoptions3, &dst->icb_fwoptions3);
+	for (i = 0; i < 12; i++) {
+		ISP_IOXPUT_16(isp, src->icb_reserved2[i],
+		    &dst->icb_reserved2[i]);
+	}
+}
+
+void
+isp_get_pdb_21xx(ispsoftc_t *isp, isp_pdb_21xx_t *src, isp_pdb_21xx_t *dst)
 {
 	int i;
 	ISP_IOXGET_16(isp, &src->pdb_options, dst->pdb_options);
@@ -658,29 +880,144 @@ isp_get_pdb(ispsoftc_t *isp, isp_pdb_t *src, isp_pdb_t *dst)
 	ISP_IOXGET_16(isp, &src->pdb_sl_ptr, dst->pdb_sl_ptr);
 }
 
+void
+isp_get_pdb_24xx(ispsoftc_t *isp, isp_pdb_24xx_t *src, isp_pdb_24xx_t *dst)
+{
+	int i;
+	ISP_IOXGET_16(isp, &src->pdb_flags, dst->pdb_flags);
+        ISP_IOXGET_8(isp, &src->pdb_curstate, dst->pdb_curstate);
+        ISP_IOXGET_8(isp, &src->pdb_laststate, dst->pdb_laststate);
+	for (i = 0; i < 4; i++) {
+		ISP_IOXGET_8(isp, &src->pdb_hardaddr_bits[i],
+		    dst->pdb_hardaddr_bits[i]);
+	}
+	for (i = 0; i < 4; i++) {
+		ISP_IOXGET_8(isp, &src->pdb_portid_bits[i],
+		    dst->pdb_portid_bits[i]);
+	}
+	ISP_IOXGET_16(isp, &src->pdb_retry_timer, dst->pdb_retry_timer);
+	ISP_IOXGET_16(isp, &src->pdb_handle, dst->pdb_handle);
+	ISP_IOXGET_16(isp, &src->pdb_rcv_dsize, dst->pdb_rcv_dsize);
+	ISP_IOXGET_16(isp, &src->pdb_reserved0, dst->pdb_reserved0);
+	ISP_IOXGET_16(isp, &src->pdb_prli_svc0, dst->pdb_prli_svc0);
+	ISP_IOXGET_16(isp, &src->pdb_prli_svc3, dst->pdb_prli_svc3);
+	for (i = 0; i < 8; i++) {
+		ISP_IOXGET_8(isp, &src->pdb_nodename[i], dst->pdb_nodename[i]);
+	}
+	for (i = 0; i < 8; i++) {
+		ISP_IOXGET_8(isp, &src->pdb_portname[i], dst->pdb_portname[i]);
+	}
+	for (i = 0; i < 24; i++) {
+		ISP_IOXGET_8(isp, &src->pdb_reserved1[i],
+		    dst->pdb_reserved1[i]);
+	}
+}
 
 /*
- * CT_HDR canonicalization- only needed for SNS responses
+ * PLOGI/LOGO IOCB canonicalization
+ */
+
+void
+isp_get_plogx(ispsoftc_t *isp, isp_plogx_t *src, isp_plogx_t *dst)
+{
+	int i;
+	isp_get_hdr(isp, &src->plogx_header, &dst->plogx_header);
+	ISP_IOXGET_32(isp, &src->plogx_handle, dst->plogx_handle);
+	ISP_IOXGET_16(isp, &src->plogx_status, dst->plogx_status);
+	ISP_IOXGET_16(isp, &src->plogx_nphdl, dst->plogx_nphdl);
+	ISP_IOXGET_16(isp, &src->plogx_flags, dst->plogx_flags);
+	ISP_IOXGET_16(isp, &src->plogx_vphdl, dst->plogx_vphdl);
+	ISP_IOXGET_16(isp, &src->plogx_portlo, dst->plogx_portlo);
+	ISP_IOXGET_16(isp, &src->plogx_rspsz_porthi, dst->plogx_rspsz_porthi);
+	for (i = 0; i < 11; i++) {
+		ISP_IOXGET_16(isp, &src->plogx_ioparm[i].lo16,
+		    dst->plogx_ioparm[i].lo16);
+		ISP_IOXGET_16(isp, &src->plogx_ioparm[i].hi16,
+		    dst->plogx_ioparm[i].hi16);
+	}
+}
+
+void
+isp_put_plogx(ispsoftc_t *isp, isp_plogx_t *src, isp_plogx_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->plogx_header, &dst->plogx_header);
+	ISP_IOXPUT_32(isp, src->plogx_handle, &dst->plogx_handle);
+	ISP_IOXPUT_16(isp, src->plogx_status, &dst->plogx_status);
+	ISP_IOXPUT_16(isp, src->plogx_nphdl, &dst->plogx_nphdl);
+	ISP_IOXPUT_16(isp, src->plogx_flags, &dst->plogx_flags);
+	ISP_IOXPUT_16(isp, src->plogx_vphdl, &dst->plogx_vphdl);
+	ISP_IOXPUT_16(isp, src->plogx_portlo, &dst->plogx_portlo);
+	ISP_IOXPUT_16(isp, src->plogx_rspsz_porthi, &dst->plogx_rspsz_porthi);
+	for (i = 0; i < 11; i++) {
+		ISP_IOXPUT_16(isp, src->plogx_ioparm[i].lo16,
+		    &dst->plogx_ioparm[i].lo16);
+		ISP_IOXPUT_16(isp, src->plogx_ioparm[i].hi16,
+		    &dst->plogx_ioparm[i].hi16);
+	}
+}
+
+/*
+ * CT Passthru canonicalization
  */
 void
-isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst)
+isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst)
 {
-	ISP_IOXGET_8(isp, &src->ct_revision, dst->ct_revision);
-	ISP_IOXGET_8(isp, &src->ct_portid[0], dst->ct_portid[0]);
-	ISP_IOXGET_8(isp, &src->ct_portid[1], dst->ct_portid[1]);
-	ISP_IOXGET_8(isp, &src->ct_portid[2], dst->ct_portid[2]);
-	ISP_IOXGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type);
-	ISP_IOXGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype);
-	ISP_IOXGET_8(isp, &src->ct_options, dst->ct_options);
-	ISP_IOXGET_8(isp, &src->ct_res0, dst->ct_res0);
-	ISP_IOXGET_16(isp, &src->ct_response, dst->ct_response);
-	dst->ct_response = (dst->ct_response << 8) | (dst->ct_response >> 8);
-	ISP_IOXGET_16(isp, &src->ct_resid, dst->ct_resid);
-	dst->ct_resid = (dst->ct_resid << 8) | (dst->ct_resid >> 8);
-	ISP_IOXGET_8(isp, &src->ct_res1, dst->ct_res1);
-	ISP_IOXGET_8(isp, &src->ct_reason, dst->ct_reason);
-	ISP_IOXGET_8(isp, &src->ct_explanation, dst->ct_explanation);
-	ISP_IOXGET_8(isp, &src->ct_vunique, dst->ct_vunique);
+	int i;
+
+	isp_get_hdr(isp, &src->ctp_header, &dst->ctp_header);
+	ISP_IOXGET_32(isp, &src->ctp_handle, dst->ctp_handle);
+	ISP_IOXGET_16(isp, &src->ctp_status, dst->ctp_status);
+	ISP_IOXGET_16(isp, &src->ctp_nphdl, dst->ctp_nphdl);
+	ISP_IOXGET_16(isp, &src->ctp_cmd_cnt, dst->ctp_cmd_cnt);
+	ISP_IOXGET_16(isp, &src->ctp_vpidx, dst->ctp_vpidx);
+	ISP_IOXGET_16(isp, &src->ctp_time, dst->ctp_time);
+	ISP_IOXGET_16(isp, &src->ctp_reserved0, dst->ctp_reserved0);
+	ISP_IOXGET_16(isp, &src->ctp_rsp_cnt, dst->ctp_rsp_cnt);
+	for (i = 0; i < 5; i++) {
+		ISP_IOXGET_16(isp, &src->ctp_reserved1[i],
+		    dst->ctp_reserved1[i]);
+	}
+	ISP_IOXGET_32(isp, &src->ctp_rsp_bcnt, dst->ctp_rsp_bcnt);
+	ISP_IOXGET_32(isp, &src->ctp_cmd_bcnt, dst->ctp_cmd_bcnt);
+	for (i = 0; i < 2; i++) {
+		ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_base,
+		    dst->ctp_dataseg[i].ds_base);
+		ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_basehi,
+		    dst->ctp_dataseg[i].ds_basehi);
+		ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_count,
+		    dst->ctp_dataseg[i].ds_count);
+	}
+}
+
+void
+isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst)
+{
+	int i;
+
+	isp_put_hdr(isp, &src->ctp_header, &dst->ctp_header);
+	ISP_IOXPUT_32(isp, src->ctp_handle, &dst->ctp_handle);
+	ISP_IOXPUT_16(isp, src->ctp_status, &dst->ctp_status);
+	ISP_IOXPUT_16(isp, src->ctp_nphdl, &dst->ctp_nphdl);
+	ISP_IOXPUT_16(isp, src->ctp_cmd_cnt, &dst->ctp_cmd_cnt);
+	ISP_IOXPUT_16(isp, src->ctp_vpidx, &dst->ctp_vpidx);
+	ISP_IOXPUT_16(isp, src->ctp_time, &dst->ctp_time);
+	ISP_IOXPUT_16(isp, src->ctp_reserved0, &dst->ctp_reserved0);
+	ISP_IOXPUT_16(isp, src->ctp_rsp_cnt, &dst->ctp_rsp_cnt);
+	for (i = 0; i < 5; i++) {
+		ISP_IOXPUT_16(isp, src->ctp_reserved1[i],
+		    &dst->ctp_reserved1[i]);
+	}
+	ISP_IOXPUT_32(isp, src->ctp_rsp_bcnt, &dst->ctp_rsp_bcnt);
+	ISP_IOXPUT_32(isp, src->ctp_cmd_bcnt, &dst->ctp_cmd_bcnt);
+	for (i = 0; i < 2; i++) {
+		ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_base,
+		    &dst->ctp_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_basehi,
+		    &dst->ctp_dataseg[i].ds_basehi);
+		ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_count,
+		    &dst->ctp_dataseg[i].ds_count);
+	}
 }
 
 /*
@@ -707,16 +1044,16 @@ isp_put_gid_ft_request(ispsoftc_t *isp, sns_gid_ft_req_t *src,
     sns_gid_ft_req_t *dst)
 {
 	ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
-	ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0);
+	ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0);
 	ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]);
 	ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]);
 	ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]);
 	ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]);
 	ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen);
-	ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1);
+	ISP_IOXPUT_16(isp, src->snscb_reserved1, &dst->snscb_reserved1);
 	ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd);
 	ISP_IOXPUT_16(isp, src->snscb_mword_div_2, &dst->snscb_mword_div_2);
-	ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3);
+	ISP_IOXPUT_32(isp, src->snscb_reserved3, &dst->snscb_reserved3);
 	ISP_IOXPUT_32(isp, src->snscb_fc4_type, &dst->snscb_fc4_type);
 }
 
@@ -725,16 +1062,16 @@ isp_put_gxn_id_request(ispsoftc_t *isp, sns_gxn_id_req_t *src,
     sns_gxn_id_req_t *dst)
 {
 	ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
-	ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0);
+	ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0);
 	ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]);
 	ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]);
 	ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]);
 	ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]);
 	ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen);
-	ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1);
+	ISP_IOXPUT_16(isp, src->snscb_reserved1, &dst->snscb_reserved1);
 	ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd);
-	ISP_IOXPUT_16(isp, src->snscb_res2, &dst->snscb_res2);
-	ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3);
+	ISP_IOXPUT_16(isp, src->snscb_reserved2, &dst->snscb_reserved2);
+	ISP_IOXPUT_32(isp, src->snscb_reserved3, &dst->snscb_reserved3);
 	ISP_IOXPUT_32(isp, src->snscb_portid, &dst->snscb_portid);
 }
 
@@ -858,10 +1195,182 @@ isp_get_ga_nxt_response(ispsoftc_t *isp, sns_ga_nxt_rsp_t *src,
 	}
 }
 
-#ifdef	ISP_TARGET_MODE
+void
+isp_get_els(ispsoftc_t *isp, els_t *src, els_t *dst)
+{
+	int i;
 
+	isp_get_hdr(isp, &src->els_hdr, &dst->els_hdr);
+	ISP_IOXGET_32(isp, &src->els_handle, dst->els_handle);
+	ISP_IOXGET_16(isp, &src->els_status, dst->els_status);
+	ISP_IOXGET_16(isp, &src->els_nphdl, dst->els_nphdl);
+	ISP_IOXGET_16(isp, &src->els_xmit_dsd_count, dst->els_xmit_dsd_count);
+	ISP_IOXGET_8(isp, &src->els_vphdl, dst->els_vphdl);
+	ISP_IOXGET_8(isp, &src->els_sof, dst->els_sof);
+	ISP_IOXGET_32(isp, &src->els_rxid, dst->els_rxid);
+	ISP_IOXGET_16(isp, &src->els_recv_dsd_count, dst->els_recv_dsd_count);
+	ISP_IOXGET_8(isp, &src->els_opcode, dst->els_opcode);
+	ISP_IOXGET_8(isp, &src->els_reserved2, dst->els_reserved1);
+	ISP_IOXGET_8(isp, &src->els_did_lo, dst->els_did_lo);
+	ISP_IOXGET_8(isp, &src->els_did_mid, dst->els_did_mid);
+	ISP_IOXGET_8(isp, &src->els_did_hi, dst->els_did_hi);
+	ISP_IOXGET_8(isp, &src->els_reserved2, dst->els_reserved2);
+	ISP_IOXGET_16(isp, &src->els_reserved3, dst->els_reserved3);
+	ISP_IOXGET_16(isp, &src->els_ctl_flags, dst->els_ctl_flags);
+	ISP_IOXGET_32(isp, &src->els_bytecnt, dst->els_bytecnt);
+	ISP_IOXGET_32(isp, &src->els_subcode1, dst->els_subcode1);
+	ISP_IOXGET_32(isp, &src->els_subcode2, dst->els_subcode2);
+	for (i = 0; i < 20; i++) {
+		ISP_IOXGET_8(isp, &src->els_reserved4[i],
+		    dst->els_reserved4[i]);
+	}
+}
+
+void
+isp_put_els(ispsoftc_t *isp, els_t *src, els_t *dst)
+{
+	isp_put_hdr(isp, &src->els_hdr, &dst->els_hdr);
+	ISP_IOXPUT_32(isp, src->els_handle, &dst->els_handle);
+	ISP_IOXPUT_16(isp, src->els_status, &dst->els_status);
+	ISP_IOXPUT_16(isp, src->els_nphdl, &dst->els_nphdl);
+	ISP_IOXPUT_16(isp, src->els_xmit_dsd_count, &dst->els_xmit_dsd_count);
+	ISP_IOXPUT_8(isp, src->els_vphdl, &dst->els_vphdl);
+	ISP_IOXPUT_8(isp, src->els_sof, &dst->els_sof);
+	ISP_IOXPUT_32(isp, src->els_rxid, &dst->els_rxid);
+	ISP_IOXPUT_16(isp, src->els_recv_dsd_count, &dst->els_recv_dsd_count);
+	ISP_IOXPUT_8(isp, src->els_opcode, &dst->els_opcode);
+	ISP_IOXPUT_8(isp, src->els_reserved2, &dst->els_reserved1);
+	ISP_IOXPUT_8(isp, src->els_did_lo, &dst->els_did_lo);
+	ISP_IOXPUT_8(isp, src->els_did_mid, &dst->els_did_mid);
+	ISP_IOXPUT_8(isp, src->els_did_hi, &dst->els_did_hi);
+	ISP_IOXPUT_8(isp, src->els_reserved2, &dst->els_reserved2);
+	ISP_IOXPUT_16(isp, src->els_reserved3, &dst->els_reserved3);
+	ISP_IOXPUT_16(isp, src->els_ctl_flags, &dst->els_ctl_flags);
+	ISP_IOXPUT_32(isp, src->els_recv_bytecnt, &dst->els_recv_bytecnt);
+	ISP_IOXPUT_32(isp, src->els_xmit_bytecnt, &dst->els_xmit_bytecnt);
+	ISP_IOXPUT_32(isp, src->els_xmit_dsd_length, &dst->els_xmit_dsd_length);
+	ISP_IOXPUT_16(isp, src->els_xmit_dsd_a1500, &dst->els_xmit_dsd_a1500);
+	ISP_IOXPUT_16(isp, src->els_xmit_dsd_a3116, &dst->els_xmit_dsd_a3116);
+	ISP_IOXPUT_16(isp, src->els_xmit_dsd_a4732, &dst->els_xmit_dsd_a4732);
+	ISP_IOXPUT_16(isp, src->els_xmit_dsd_a6348, &dst->els_xmit_dsd_a6348);
+	ISP_IOXPUT_32(isp, src->els_recv_dsd_length, &dst->els_recv_dsd_length);
+	ISP_IOXPUT_16(isp, src->els_recv_dsd_a1500, &dst->els_recv_dsd_a1500);
+	ISP_IOXPUT_16(isp, src->els_recv_dsd_a3116, &dst->els_recv_dsd_a3116);
+	ISP_IOXPUT_16(isp, src->els_recv_dsd_a4732, &dst->els_recv_dsd_a4732);
+	ISP_IOXPUT_16(isp, src->els_recv_dsd_a6348, &dst->els_recv_dsd_a6348);
+}
+
+/*
+ * FC Structure Canonicalization
+ */
+
+void
+isp_get_fc_hdr(ispsoftc_t *isp, fc_hdr_t *src, fc_hdr_t *dst)
+{
+        ISP_IOZGET_8(isp, &src->r_ctl, dst->r_ctl);
+        ISP_IOZGET_8(isp, &src->d_id[0], dst->d_id[0]);
+        ISP_IOZGET_8(isp, &src->d_id[1], dst->d_id[1]);
+        ISP_IOZGET_8(isp, &src->d_id[2], dst->d_id[2]);
+        ISP_IOZGET_8(isp, &src->cs_ctl, dst->cs_ctl);
+        ISP_IOZGET_8(isp, &src->s_id[0], dst->s_id[0]);
+        ISP_IOZGET_8(isp, &src->s_id[1], dst->s_id[1]);
+        ISP_IOZGET_8(isp, &src->s_id[2], dst->s_id[2]);
+        ISP_IOZGET_8(isp, &src->type, dst->type);
+        ISP_IOZGET_8(isp, &src->f_ctl, dst->f_ctl);
+        ISP_IOZGET_8(isp, &src->seq_id, dst->seq_id);
+        ISP_IOZGET_8(isp, &src->df_ctl, dst->df_ctl);
+        ISP_IOZGET_16(isp, &src->seq_cnt, dst->seq_cnt);
+	/* XXX SOMETHING WAS AND STILL CONTINUES WRONG HERE XXX */
+#if	0
+        ISP_IOZGET_16(isp, &src->ox_id, dst->ox_id);
+        ISP_IOZGET_16(isp, &src->rx_id, dst->rx_id);
+#else
+        ISP_IOZGET_32(isp, &src->ox_id, dst->parameter);
+        dst->ox_id = dst->parameter;
+        dst->rx_id = dst->parameter >> 16;
+#endif
+        ISP_IOZGET_32(isp, &src->parameter, dst->parameter);
+}
+
+void
+isp_get_fcp_cmnd_iu(ispsoftc_t *isp, fcp_cmnd_iu_t *src, fcp_cmnd_iu_t *dst)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		ISP_IOZGET_8(isp, &src->fcp_cmnd_lun[i], dst->fcp_cmnd_lun[i]);
+	}
+        ISP_IOZGET_8(isp, &src->fcp_cmnd_crn, dst->fcp_cmnd_crn);
+        ISP_IOZGET_8(isp, &src->fcp_cmnd_task_attribute,
+	    dst->fcp_cmnd_task_attribute);
+        ISP_IOZGET_8(isp, &src->fcp_cmnd_task_management,
+	    dst->fcp_cmnd_task_management);
+        ISP_IOZGET_8(isp, &src->fcp_cmnd_alen_datadir,
+	    dst->fcp_cmnd_alen_datadir);
+	for (i = 0; i < 16; i++) {
+		ISP_IOZGET_8(isp, &src->cdb_dl.sf.fcp_cmnd_cdb[i],
+		    dst->cdb_dl.sf.fcp_cmnd_cdb[i]);
+	}
+	ISP_IOZGET_32(isp, &src->cdb_dl.sf.fcp_cmnd_dl,
+	    dst->cdb_dl.sf.fcp_cmnd_dl);
+}
+
+void
+isp_put_rft_id(ispsoftc_t *isp, rft_id_t *src, rft_id_t *dst)
+{
+	int i;
+	isp_put_ct_hdr(isp, &src->rftid_hdr, &dst->rftid_hdr);
+	ISP_IOZPUT_8(isp, src->rftid_reserved, &dst->rftid_reserved);
+	for (i = 0; i < 3; i++) {
+		ISP_IOZPUT_8(isp, src->rftid_portid[i], &dst->rftid_portid[i]);
+	}
+	for (i = 0; i < 8; i++) {
+		ISP_IOZPUT_32(isp, src->rftid_fc4types[i],
+		    &dst->rftid_fc4types[i]);
+	}
+}
+
+void
+isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst)
+{
+	ISP_IOZGET_8(isp, &src->ct_revision, dst->ct_revision);
+	ISP_IOZGET_8(isp, &src->ct_in_id[0], dst->ct_in_id[0]);
+	ISP_IOZGET_8(isp, &src->ct_in_id[1], dst->ct_in_id[1]);
+	ISP_IOZGET_8(isp, &src->ct_in_id[2], dst->ct_in_id[2]);
+	ISP_IOZGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type);
+	ISP_IOZGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype);
+	ISP_IOZGET_8(isp, &src->ct_options, dst->ct_options);
+	ISP_IOZGET_8(isp, &src->ct_reserved0, dst->ct_reserved0);
+	ISP_IOZGET_16(isp, &src->ct_cmd_resp, dst->ct_cmd_resp);
+	ISP_IOZGET_16(isp, &src->ct_bcnt_resid, dst->ct_bcnt_resid);
+	ISP_IOZGET_8(isp, &src->ct_reserved1, dst->ct_reserved1);
+	ISP_IOZGET_8(isp, &src->ct_reason, dst->ct_reason);
+	ISP_IOZGET_8(isp, &src->ct_explanation, dst->ct_explanation);
+	ISP_IOZGET_8(isp, &src->ct_vunique, dst->ct_vunique);
+}
+
+void
+isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst)
+{
+	ISP_IOZPUT_8(isp, src->ct_revision, &dst->ct_revision);
+	ISP_IOZPUT_8(isp, src->ct_in_id[0], &dst->ct_in_id[0]);
+	ISP_IOZPUT_8(isp, src->ct_in_id[1], &dst->ct_in_id[1]);
+	ISP_IOZPUT_8(isp, src->ct_in_id[2], &dst->ct_in_id[2]);
+	ISP_IOZPUT_8(isp, src->ct_fcs_type, &dst->ct_fcs_type);
+	ISP_IOZPUT_8(isp, src->ct_fcs_subtype, &dst->ct_fcs_subtype);
+	ISP_IOZPUT_8(isp, src->ct_options, &dst->ct_options);
+	ISP_IOZPUT_8(isp, src->ct_reserved0, &dst->ct_reserved0);
+	ISP_IOZPUT_16(isp, src->ct_cmd_resp, &dst->ct_cmd_resp);
+	ISP_IOZPUT_16(isp, src->ct_bcnt_resid, &dst->ct_bcnt_resid);
+	ISP_IOZPUT_8(isp, src->ct_reserved1, &dst->ct_reserved1);
+	ISP_IOZPUT_8(isp, src->ct_reason, &dst->ct_reason);
+	ISP_IOZPUT_8(isp, src->ct_explanation, &dst->ct_explanation);
+	ISP_IOZPUT_8(isp, src->ct_vunique, &dst->ct_vunique);
+}
+
+#ifdef	ISP_TARGET_MODE
 int
-isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint16_t *handlep)
+isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep)
 {
 	int i;
 
@@ -874,28 +1383,30 @@ isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint16_t *handlep)
 		return (-1);
 	}
 	isp->isp_tgtlist[i] = xs;
-	*handlep = i+1;
+	*handlep = (i+1) | 0x8000;
 	return (0);
 }
 
 void *
-isp_find_xs_tgt(ispsoftc_t *isp, uint16_t handle)
+isp_find_xs_tgt(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle < 1 || handle > (uint16_t) isp->isp_maxcmds) {
+	if (handle == 0 || (handle & 0x8000) == 0 ||
+	    (handle & 0x7fff) > isp->isp_maxcmds) {
+		isp_prt(isp, ISP_LOGERR, "bad handle in isp_find_xs_tgt");
 		return (NULL);
 	} else {
-		return (isp->isp_tgtlist[handle - 1]);
+		return (isp->isp_tgtlist[(handle & 0x7fff) - 1]);
 	}
 }
 
-uint16_t
+uint32_t
 isp_find_tgt_handle(ispsoftc_t *isp, void *xs)
 {
 	int i;
 	if (xs != NULL) {
 		for (i = 0; i < isp->isp_maxcmds; i++) {
 			if (isp->isp_tgtlist[i] == xs) {
-				return ((uint16_t) i+1);
+				return ((i+1) & 0x7fff);
 			}
 		}
 	}
@@ -903,489 +1414,758 @@ isp_find_tgt_handle(ispsoftc_t *isp, void *xs)
 }
 
 void
-isp_destroy_tgt_handle(ispsoftc_t *isp, uint16_t handle)
+isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle > 0 && handle <= (uint16_t) isp->isp_maxcmds) {
-		isp->isp_tgtlist[handle - 1] = NULL;
+	if (handle == 0 || (handle & 0x8000) == 0 ||
+	    (handle & 0x7fff) > isp->isp_maxcmds) {
+		isp_prt(isp, ISP_LOGERR,
+		    "bad handle in isp_destroy_tgt_handle");
+	} else {
+		isp->isp_tgtlist[(handle & 0x7fff) - 1] = NULL;
 	}
 }
+
 void
-isp_put_atio(ispsoftc_t *isp, at_entry_t *atsrc, at_entry_t *atdst)
+isp_put_atio(ispsoftc_t *isp, at_entry_t *src, at_entry_t *dst)
 {
 	int i;
-	isp_copy_out_hdr(isp, &atsrc->at_header, &atdst->at_header);
-	ISP_IOXPUT_16(isp, atsrc->at_reserved, &atdst->at_reserved);
-	ISP_IOXPUT_16(isp, atsrc->at_handle, &atdst->at_handle);
+	isp_put_hdr(isp, &src->at_header, &dst->at_header);
+	ISP_IOXPUT_16(isp, src->at_reserved, &dst->at_reserved);
+	ISP_IOXPUT_16(isp, src->at_handle, &dst->at_handle);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_iid);
-		ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_lun);
-		ISP_IOXPUT_8(isp, atsrc->at_cdblen, &atdst->at_tgt);
-		ISP_IOXPUT_8(isp, atsrc->at_tgt, &atdst->at_cdblen);
-		ISP_IOXPUT_8(isp, atsrc->at_status, &atdst->at_scsi_status);
-		ISP_IOXPUT_8(isp, atsrc->at_scsi_status, &atdst->at_status);
-		ISP_IOXPUT_8(isp, atsrc->at_tag_val, &atdst->at_tag_type);
-		ISP_IOXPUT_8(isp, atsrc->at_tag_type, &atdst->at_tag_val);
+		ISP_IOXPUT_8(isp, src->at_lun, &dst->at_iid);
+		ISP_IOXPUT_8(isp, src->at_iid, &dst->at_lun);
+		ISP_IOXPUT_8(isp, src->at_cdblen, &dst->at_tgt);
+		ISP_IOXPUT_8(isp, src->at_tgt, &dst->at_cdblen);
+		ISP_IOXPUT_8(isp, src->at_status, &dst->at_scsi_status);
+		ISP_IOXPUT_8(isp, src->at_scsi_status, &dst->at_status);
+		ISP_IOXPUT_8(isp, src->at_tag_val, &dst->at_tag_type);
+		ISP_IOXPUT_8(isp, src->at_tag_type, &dst->at_tag_val);
 	} else {
-		ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_lun);
-		ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_iid);
-		ISP_IOXPUT_8(isp, atsrc->at_cdblen, &atdst->at_cdblen);
-		ISP_IOXPUT_8(isp, atsrc->at_tgt, &atdst->at_tgt);
-		ISP_IOXPUT_8(isp, atsrc->at_status, &atdst->at_status);
-		ISP_IOXPUT_8(isp, atsrc->at_scsi_status,
-		    &atdst->at_scsi_status);
-		ISP_IOXPUT_8(isp, atsrc->at_tag_val, &atdst->at_tag_val);
-		ISP_IOXPUT_8(isp, atsrc->at_tag_type, &atdst->at_tag_type);
+		ISP_IOXPUT_8(isp, src->at_lun, &dst->at_lun);
+		ISP_IOXPUT_8(isp, src->at_iid, &dst->at_iid);
+		ISP_IOXPUT_8(isp, src->at_cdblen, &dst->at_cdblen);
+		ISP_IOXPUT_8(isp, src->at_tgt, &dst->at_tgt);
+		ISP_IOXPUT_8(isp, src->at_status, &dst->at_status);
+		ISP_IOXPUT_8(isp, src->at_scsi_status,
+		    &dst->at_scsi_status);
+		ISP_IOXPUT_8(isp, src->at_tag_val, &dst->at_tag_val);
+		ISP_IOXPUT_8(isp, src->at_tag_type, &dst->at_tag_type);
 	}
-	ISP_IOXPUT_32(isp, atsrc->at_flags, &atdst->at_flags);
+	ISP_IOXPUT_32(isp, src->at_flags, &dst->at_flags);
 	for (i = 0; i < ATIO_CDBLEN; i++) {
-		ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]);
+		ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]);
 	}
 	for (i = 0; i < QLTM_SENSELEN; i++) {
-		ISP_IOXPUT_8(isp, atsrc->at_sense[i], &atdst->at_sense[i]);
+		ISP_IOXPUT_8(isp, src->at_sense[i], &dst->at_sense[i]);
 	}
 }
 
 void
-isp_get_atio(ispsoftc_t *isp, at_entry_t *atsrc, at_entry_t *atdst)
+isp_get_atio(ispsoftc_t *isp, at_entry_t *src, at_entry_t *dst)
 {
 	int i;
-	isp_copy_in_hdr(isp, &atsrc->at_header, &atdst->at_header);
-	ISP_IOXGET_16(isp, &atsrc->at_reserved, atdst->at_reserved);
-	ISP_IOXGET_16(isp, &atsrc->at_handle, atdst->at_handle);
+	isp_get_hdr(isp, &src->at_header, &dst->at_header);
+	ISP_IOXGET_16(isp, &src->at_reserved, dst->at_reserved);
+	ISP_IOXGET_16(isp, &src->at_handle, dst->at_handle);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_iid);
-		ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_lun);
-		ISP_IOXGET_8(isp, &atsrc->at_cdblen, atdst->at_tgt);
-		ISP_IOXGET_8(isp, &atsrc->at_tgt, atdst->at_cdblen);
-		ISP_IOXGET_8(isp, &atsrc->at_status, atdst->at_scsi_status);
-		ISP_IOXGET_8(isp, &atsrc->at_scsi_status, atdst->at_status);
-		ISP_IOXGET_8(isp, &atsrc->at_tag_val, atdst->at_tag_type);
-		ISP_IOXGET_8(isp, &atsrc->at_tag_type, atdst->at_tag_val);
+		ISP_IOXGET_8(isp, &src->at_lun, dst->at_iid);
+		ISP_IOXGET_8(isp, &src->at_iid, dst->at_lun);
+		ISP_IOXGET_8(isp, &src->at_cdblen, dst->at_tgt);
+		ISP_IOXGET_8(isp, &src->at_tgt, dst->at_cdblen);
+		ISP_IOXGET_8(isp, &src->at_status, dst->at_scsi_status);
+		ISP_IOXGET_8(isp, &src->at_scsi_status, dst->at_status);
+		ISP_IOXGET_8(isp, &src->at_tag_val, dst->at_tag_type);
+		ISP_IOXGET_8(isp, &src->at_tag_type, dst->at_tag_val);
 	} else {
-		ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_lun);
-		ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_iid);
-		ISP_IOXGET_8(isp, &atsrc->at_cdblen, atdst->at_cdblen);
-		ISP_IOXGET_8(isp, &atsrc->at_tgt, atdst->at_tgt);
-		ISP_IOXGET_8(isp, &atsrc->at_status, atdst->at_status);
-		ISP_IOXGET_8(isp, &atsrc->at_scsi_status,
-		    atdst->at_scsi_status);
-		ISP_IOXGET_8(isp, &atsrc->at_tag_val, atdst->at_tag_val);
-		ISP_IOXGET_8(isp, &atsrc->at_tag_type, atdst->at_tag_type);
+		ISP_IOXGET_8(isp, &src->at_lun, dst->at_lun);
+		ISP_IOXGET_8(isp, &src->at_iid, dst->at_iid);
+		ISP_IOXGET_8(isp, &src->at_cdblen, dst->at_cdblen);
+		ISP_IOXGET_8(isp, &src->at_tgt, dst->at_tgt);
+		ISP_IOXGET_8(isp, &src->at_status, dst->at_status);
+		ISP_IOXGET_8(isp, &src->at_scsi_status,
+		    dst->at_scsi_status);
+		ISP_IOXGET_8(isp, &src->at_tag_val, dst->at_tag_val);
+		ISP_IOXGET_8(isp, &src->at_tag_type, dst->at_tag_type);
 	}
-	ISP_IOXGET_32(isp, &atsrc->at_flags, atdst->at_flags);
+	ISP_IOXGET_32(isp, &src->at_flags, dst->at_flags);
 	for (i = 0; i < ATIO_CDBLEN; i++) {
-		ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]);
+		ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]);
 	}
 	for (i = 0; i < QLTM_SENSELEN; i++) {
-		ISP_IOXGET_8(isp, &atsrc->at_sense[i], atdst->at_sense[i]);
+		ISP_IOXGET_8(isp, &src->at_sense[i], dst->at_sense[i]);
 	}
 }
 
 void
-isp_put_atio2(ispsoftc_t *isp, at2_entry_t *atsrc, at2_entry_t *atdst)
+isp_put_atio2(ispsoftc_t *isp, at2_entry_t *src, at2_entry_t *dst)
 {
 	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_8(isp, atsrc->at_lun, &atdst->at_lun);
-	ISP_IOXPUT_8(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);
+	isp_put_hdr(isp, &src->at_header, &dst->at_header);
+	ISP_IOXPUT_32(isp, src->at_reserved, &dst->at_reserved);
+	ISP_IOXPUT_8(isp, src->at_lun, &dst->at_lun);
+	ISP_IOXPUT_8(isp, src->at_iid, &dst->at_iid);
+	ISP_IOXPUT_16(isp, src->at_rxid, &dst->at_rxid);
+	ISP_IOXPUT_16(isp, src->at_flags, &dst->at_flags);
+	ISP_IOXPUT_16(isp, src->at_status, &dst->at_status);
+	ISP_IOXPUT_8(isp, src->at_crn, &dst->at_crn);
+	ISP_IOXPUT_8(isp, src->at_taskcodes, &dst->at_taskcodes);
+	ISP_IOXPUT_8(isp, src->at_taskflags, &dst->at_taskflags);
+	ISP_IOXPUT_8(isp, src->at_execodes, &dst->at_execodes);
 	for (i = 0; i < ATIO2_CDBLEN; i++) {
-		ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]);
+		ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]);
 	}
-	ISP_IOXPUT_32(isp, atsrc->at_datalen, &atdst->at_datalen);
-	ISP_IOXPUT_16(isp, atsrc->at_scclun, &atdst->at_scclun);
+	ISP_IOXPUT_32(isp, src->at_datalen, &dst->at_datalen);
+	ISP_IOXPUT_16(isp, src->at_scclun, &dst->at_scclun);
 	for (i = 0; i < 4; i++) {
-		ISP_IOXPUT_16(isp, atsrc->at_wwpn[i], &atdst->at_wwpn[i]);
+		ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->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, src->at_reserved2[i],
+		    &dst->at_reserved2[i]);
 	}
-	ISP_IOXPUT_16(isp, atsrc->at_oxid, &atdst->at_oxid);
+	ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid);
 }
 
 void
-isp_put_atio2e(ispsoftc_t *isp, at2e_entry_t *atsrc, at2e_entry_t *atdst)
+isp_put_atio2e(ispsoftc_t *isp, at2e_entry_t *src, at2e_entry_t *dst)
 {
 	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);
+	isp_put_hdr(isp, &src->at_header, &dst->at_header);
+	ISP_IOXPUT_32(isp, src->at_reserved, &dst->at_reserved);
+	ISP_IOXPUT_16(isp, src->at_iid, &dst->at_iid);
+	ISP_IOXPUT_16(isp, src->at_rxid, &dst->at_rxid);
+	ISP_IOXPUT_16(isp, src->at_flags, &dst->at_flags);
+	ISP_IOXPUT_16(isp, src->at_status, &dst->at_status);
+	ISP_IOXPUT_8(isp, src->at_crn, &dst->at_crn);
+	ISP_IOXPUT_8(isp, src->at_taskcodes, &dst->at_taskcodes);
+	ISP_IOXPUT_8(isp, src->at_taskflags, &dst->at_taskflags);
+	ISP_IOXPUT_8(isp, src->at_execodes, &dst->at_execodes);
 	for (i = 0; i < ATIO2_CDBLEN; i++) {
-		ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]);
+		ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]);
 	}
-	ISP_IOXPUT_32(isp, atsrc->at_datalen, &atdst->at_datalen);
-	ISP_IOXPUT_16(isp, atsrc->at_scclun, &atdst->at_scclun);
+	ISP_IOXPUT_32(isp, src->at_datalen, &dst->at_datalen);
+	ISP_IOXPUT_16(isp, src->at_scclun, &dst->at_scclun);
 	for (i = 0; i < 4; i++) {
-		ISP_IOXPUT_16(isp, atsrc->at_wwpn[i], &atdst->at_wwpn[i]);
+		ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->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, src->at_reserved2[i],
+		    &dst->at_reserved2[i]);
 	}
-	ISP_IOXPUT_16(isp, atsrc->at_oxid, &atdst->at_oxid);
+	ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid);
 }
 
 void
-isp_get_atio2(ispsoftc_t *isp, at2_entry_t *atsrc, at2_entry_t *atdst)
+isp_get_atio2(ispsoftc_t *isp, at2_entry_t *src, at2_entry_t *dst)
 {
 	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_8(isp, &atsrc->at_lun, atdst->at_lun);
-	ISP_IOXGET_8(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);
+	isp_get_hdr(isp, &src->at_header, &dst->at_header);
+	ISP_IOXGET_32(isp, &src->at_reserved, dst->at_reserved);
+	ISP_IOXGET_8(isp, &src->at_lun, dst->at_lun);
+	ISP_IOXGET_8(isp, &src->at_iid, dst->at_iid);
+	ISP_IOXGET_16(isp, &src->at_rxid, dst->at_rxid);
+	ISP_IOXGET_16(isp, &src->at_flags, dst->at_flags);
+	ISP_IOXGET_16(isp, &src->at_status, dst->at_status);
+	ISP_IOXGET_8(isp, &src->at_crn, dst->at_crn);
+	ISP_IOXGET_8(isp, &src->at_taskcodes, dst->at_taskcodes);
+	ISP_IOXGET_8(isp, &src->at_taskflags, dst->at_taskflags);
+	ISP_IOXGET_8(isp, &src->at_execodes, dst->at_execodes);
 	for (i = 0; i < ATIO2_CDBLEN; i++) {
-		ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]);
+		ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]);
 	}
-	ISP_IOXGET_32(isp, &atsrc->at_datalen, atdst->at_datalen);
-	ISP_IOXGET_16(isp, &atsrc->at_scclun, atdst->at_scclun);
+	ISP_IOXGET_32(isp, &src->at_datalen, dst->at_datalen);
+	ISP_IOXGET_16(isp, &src->at_scclun, dst->at_scclun);
 	for (i = 0; i < 4; i++) {
-		ISP_IOXGET_16(isp, &atsrc->at_wwpn[i], atdst->at_wwpn[i]);
+		ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->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, &src->at_reserved2[i],
+		    dst->at_reserved2[i]);
 	}
-	ISP_IOXGET_16(isp, &atsrc->at_oxid, atdst->at_oxid);
+	ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid);
 }
 
 void
-isp_get_atio2e(ispsoftc_t *isp, at2e_entry_t *atsrc, at2e_entry_t *atdst)
+isp_get_atio2e(ispsoftc_t *isp, at2e_entry_t *src, at2e_entry_t *dst)
 {
 	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);
+	isp_get_hdr(isp, &src->at_header, &dst->at_header);
+	ISP_IOXGET_32(isp, &src->at_reserved, dst->at_reserved);
+	ISP_IOXGET_16(isp, &src->at_iid, dst->at_iid);
+	ISP_IOXGET_16(isp, &src->at_rxid, dst->at_rxid);
+	ISP_IOXGET_16(isp, &src->at_flags, dst->at_flags);
+	ISP_IOXGET_16(isp, &src->at_status, dst->at_status);
+	ISP_IOXGET_8(isp, &src->at_crn, dst->at_crn);
+	ISP_IOXGET_8(isp, &src->at_taskcodes, dst->at_taskcodes);
+	ISP_IOXGET_8(isp, &src->at_taskflags, dst->at_taskflags);
+	ISP_IOXGET_8(isp, &src->at_execodes, dst->at_execodes);
 	for (i = 0; i < ATIO2_CDBLEN; i++) {
-		ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]);
+		ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]);
 	}
-	ISP_IOXGET_32(isp, &atsrc->at_datalen, atdst->at_datalen);
-	ISP_IOXGET_16(isp, &atsrc->at_scclun, atdst->at_scclun);
+	ISP_IOXGET_32(isp, &src->at_datalen, dst->at_datalen);
+	ISP_IOXGET_16(isp, &src->at_scclun, dst->at_scclun);
 	for (i = 0; i < 4; i++) {
-		ISP_IOXGET_16(isp, &atsrc->at_wwpn[i], atdst->at_wwpn[i]);
+		ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->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, &src->at_reserved2[i],
+		    dst->at_reserved2[i]);
 	}
-	ISP_IOXGET_16(isp, &atsrc->at_oxid, atdst->at_oxid);
+	ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid);
 }
 
 void
-isp_put_ctio(ispsoftc_t *isp, ct_entry_t *ctsrc, ct_entry_t *ctdst)
+isp_get_atio7(ispsoftc_t *isp, at7_entry_t *src, at7_entry_t *dst)
+{
+	ISP_IOXGET_8(isp, &src->at_type, dst->at_type);
+	ISP_IOXGET_8(isp, &src->at_count, dst->at_count);
+	ISP_IOXGET_16(isp, &src->at_ta_len, dst->at_ta_len);
+	ISP_IOXGET_32(isp, &src->at_rxid, dst->at_rxid);
+	isp_get_fc_hdr(isp, &src->at_hdr, &dst->at_hdr);
+	isp_get_fcp_cmnd_iu(isp, &src->at_cmnd, &dst->at_cmnd);
+}
+
+void
+isp_put_ctio(ispsoftc_t *isp, ct_entry_t *src, ct_entry_t *dst)
 {
 	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_put_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXPUT_16(isp, src->ct_syshandle, &dst->ct_syshandle);
+	ISP_IOXPUT_16(isp, src->ct_fwhandle, &dst->ct_fwhandle);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_lun);
-		ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_iid);
-		ISP_IOXPUT_8(isp, ctsrc->ct_tgt, &ctdst->ct_reserved2);
-		ISP_IOXPUT_8(isp, ctsrc->ct_reserved2, &ctdst->ct_tgt);
-		ISP_IOXPUT_8(isp, ctsrc->ct_status, &ctdst->ct_scsi_status);
-		ISP_IOXPUT_8(isp, ctsrc->ct_scsi_status, &ctdst->ct_status);
-		ISP_IOXPUT_8(isp, ctsrc->ct_tag_type, &ctdst->ct_tag_val);
-		ISP_IOXPUT_8(isp, ctsrc->ct_tag_val, &ctdst->ct_tag_type);
+		ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_lun);
+		ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_iid);
+		ISP_IOXPUT_8(isp, src->ct_tgt, &dst->ct_reserved2);
+		ISP_IOXPUT_8(isp, src->ct_reserved2, &dst->ct_tgt);
+		ISP_IOXPUT_8(isp, src->ct_status, &dst->ct_scsi_status);
+		ISP_IOXPUT_8(isp, src->ct_scsi_status, &dst->ct_status);
+		ISP_IOXPUT_8(isp, src->ct_tag_type, &dst->ct_tag_val);
+		ISP_IOXPUT_8(isp, src->ct_tag_val, &dst->ct_tag_type);
 	} else {
-		ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_iid);
-		ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_lun);
-		ISP_IOXPUT_8(isp, ctsrc->ct_tgt, &ctdst->ct_tgt);
-		ISP_IOXPUT_8(isp, ctsrc->ct_reserved2, &ctdst->ct_reserved2);
-		ISP_IOXPUT_8(isp, ctsrc->ct_scsi_status,
-		    &ctdst->ct_scsi_status);
-		ISP_IOXPUT_8(isp, ctsrc->ct_status, &ctdst->ct_status);
-		ISP_IOXPUT_8(isp, ctsrc->ct_tag_type, &ctdst->ct_tag_type);
-		ISP_IOXPUT_8(isp, ctsrc->ct_tag_val, &ctdst->ct_tag_val);
+		ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_iid);
+		ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_lun);
+		ISP_IOXPUT_8(isp, src->ct_tgt, &dst->ct_tgt);
+		ISP_IOXPUT_8(isp, src->ct_reserved2, &dst->ct_reserved2);
+		ISP_IOXPUT_8(isp, src->ct_scsi_status,
+		    &dst->ct_scsi_status);
+		ISP_IOXPUT_8(isp, src->ct_status, &dst->ct_status);
+		ISP_IOXPUT_8(isp, src->ct_tag_type, &dst->ct_tag_type);
+		ISP_IOXPUT_8(isp, src->ct_tag_val, &dst->ct_tag_val);
 	}
-	ISP_IOXPUT_32(isp, ctsrc->ct_flags, &ctdst->ct_flags);
-	ISP_IOXPUT_32(isp, ctsrc->ct_xfrlen, &ctdst->ct_xfrlen);
-	ISP_IOXPUT_32(isp, ctsrc->ct_resid, &ctdst->ct_resid);
-	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, src->ct_flags, &dst->ct_flags);
+	ISP_IOXPUT_32(isp, src->ct_xfrlen, &dst->ct_xfrlen);
+	ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid);
+	ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout);
+	ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count);
 	for (i = 0; i < ISP_RQDSEG; i++) {
-		ISP_IOXPUT_32(isp, ctsrc->ct_dataseg[i].ds_base,
-		    &ctdst->ct_dataseg[i].ds_base);
-		ISP_IOXPUT_32(isp, ctsrc->ct_dataseg[i].ds_count,
-		    &ctdst->ct_dataseg[i].ds_count);
+		ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_base,
+		    &dst->ct_dataseg[i].ds_base);
+		ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_count,
+		    &dst->ct_dataseg[i].ds_count);
 	}
 }
 
 void
-isp_get_ctio(ispsoftc_t *isp, ct_entry_t *ctsrc, ct_entry_t *ctdst)
+isp_get_ctio(ispsoftc_t *isp, ct_entry_t *src, ct_entry_t *dst)
 {
 	int i;
-	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_get_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXGET_16(isp, &src->ct_syshandle, dst->ct_syshandle);
+	ISP_IOXGET_16(isp, &src->ct_fwhandle, dst->ct_fwhandle);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_iid);
-		ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_lun);
-		ISP_IOXGET_8(isp, &ctsrc->ct_reserved2, ctdst->ct_tgt);
-		ISP_IOXGET_8(isp, &ctsrc->ct_tgt, ctdst->ct_reserved2);
-		ISP_IOXGET_8(isp, &ctsrc->ct_status, ctdst->ct_scsi_status);
-		ISP_IOXGET_8(isp, &ctsrc->ct_scsi_status, ctdst->ct_status);
-		ISP_IOXGET_8(isp, &ctsrc->ct_tag_val, ctdst->ct_tag_type);
-		ISP_IOXGET_8(isp, &ctsrc->ct_tag_type, ctdst->ct_tag_val);
+		ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_iid);
+		ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_lun);
+		ISP_IOXGET_8(isp, &src->ct_reserved2, dst->ct_tgt);
+		ISP_IOXGET_8(isp, &src->ct_tgt, dst->ct_reserved2);
+		ISP_IOXGET_8(isp, &src->ct_status, dst->ct_scsi_status);
+		ISP_IOXGET_8(isp, &src->ct_scsi_status, dst->ct_status);
+		ISP_IOXGET_8(isp, &src->ct_tag_val, dst->ct_tag_type);
+		ISP_IOXGET_8(isp, &src->ct_tag_type, dst->ct_tag_val);
 	} else {
-		ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_lun);
-		ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_iid);
-		ISP_IOXGET_8(isp, &ctsrc->ct_reserved2, ctdst->ct_reserved2);
-		ISP_IOXGET_8(isp, &ctsrc->ct_tgt, ctdst->ct_tgt);
-		ISP_IOXGET_8(isp, &ctsrc->ct_status, ctdst->ct_status);
-		ISP_IOXGET_8(isp, &ctsrc->ct_scsi_status,
-		    ctdst->ct_scsi_status);
-		ISP_IOXGET_8(isp, &ctsrc->ct_tag_val, ctdst->ct_tag_val);
-		ISP_IOXGET_8(isp, &ctsrc->ct_tag_type, ctdst->ct_tag_type);
+		ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_lun);
+		ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_iid);
+		ISP_IOXGET_8(isp, &src->ct_reserved2, dst->ct_reserved2);
+		ISP_IOXGET_8(isp, &src->ct_tgt, dst->ct_tgt);
+		ISP_IOXGET_8(isp, &src->ct_status, dst->ct_status);
+		ISP_IOXGET_8(isp, &src->ct_scsi_status,
+		    dst->ct_scsi_status);
+		ISP_IOXGET_8(isp, &src->ct_tag_val, dst->ct_tag_val);
+		ISP_IOXGET_8(isp, &src->ct_tag_type, dst->ct_tag_type);
 	}
-	ISP_IOXGET_32(isp, &ctsrc->ct_flags, ctdst->ct_flags);
-	ISP_IOXGET_32(isp, &ctsrc->ct_xfrlen, ctdst->ct_xfrlen);
-	ISP_IOXGET_32(isp, &ctsrc->ct_resid, ctdst->ct_resid);
-	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, &src->ct_flags, dst->ct_flags);
+	ISP_IOXGET_32(isp, &src->ct_xfrlen, dst->ct_xfrlen);
+	ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid);
+	ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout);
+	ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count);
 	for (i = 0; i < ISP_RQDSEG; i++) {
 		ISP_IOXGET_32(isp,
-		    &ctsrc->ct_dataseg[i].ds_base,
-		    ctdst->ct_dataseg[i].ds_base);
+		    &src->ct_dataseg[i].ds_base,
+		    dst->ct_dataseg[i].ds_base);
 		ISP_IOXGET_32(isp,
-		    &ctsrc->ct_dataseg[i].ds_count,
-		    ctdst->ct_dataseg[i].ds_count);
+		    &src->ct_dataseg[i].ds_count,
+		    dst->ct_dataseg[i].ds_count);
 	}
 }
 
 void
-isp_put_ctio2(ispsoftc_t *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst)
+isp_put_ctio2(ispsoftc_t *isp, ct2_entry_t *src, ct2_entry_t *dst)
 {
 	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_8(isp, ctsrc->ct_lun, &ctdst->ct_lun);
-	ISP_IOXPUT_8(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) {
+	isp_put_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle);
+	ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_lun);
+	ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_iid);
+	ISP_IOXPUT_16(isp, src->ct_rxid, &dst->ct_rxid);
+	ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags);
+	ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout);
+	ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count);
+	ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid);
+	ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff);
+	if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
+		ISP_IOXPUT_32(isp, src->rsp.m0._reserved,
+		    &dst->rsp.m0._reserved);
+		ISP_IOXPUT_16(isp, src->rsp.m0._reserved2,
+		    &dst->rsp.m0._reserved2);
+		ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status,
+		    &dst->rsp.m0.ct_scsi_status);
+		ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen,
+		    &dst->rsp.m0.ct_xfrlen);
+		if (src->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);
+				    src->rsp.m0.u.ct_dataseg[i].ds_base,
+				    &dst->rsp.m0.u.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);
+				    src->rsp.m0.u.ct_dataseg[i].ds_count,
+				    &dst->rsp.m0.u.ct_dataseg[i].ds_count);
 			}
-		} else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
+		} else if (src->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);
+				    src->rsp.m0.u.ct_dataseg64[i].ds_base,
+				    &dst->rsp.m0.u.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);
+				    src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
+				    &dst->rsp.m0.u.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);
+				    src->rsp.m0.u.ct_dataseg64[i].ds_count,
+				    &dst->rsp.m0.u.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 (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
+			ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type,
+			    &dst->rsp.m0.u.ct_dslist.ds_type);
+			ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment,
+			    &dst->rsp.m0.u.ct_dslist.ds_segment);
+			ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base,
+			    &dst->rsp.m0.u.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);
+	} else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
+		ISP_IOXPUT_16(isp, src->rsp.m1._reserved,
+		    &dst->rsp.m1._reserved);
+		ISP_IOXPUT_16(isp, src->rsp.m1._reserved2,
+		    &dst->rsp.m1._reserved2);
+		ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen,
+		    &dst->rsp.m1.ct_senselen);
+		ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status,
+		    &dst->rsp.m1.ct_scsi_status);
+		ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen,
+		    &dst->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]);
+			ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i],
+			    &dst->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);
+		ISP_IOXPUT_32(isp, src->rsp.m2._reserved,
+		    &dst->rsp.m2._reserved);
+		ISP_IOXPUT_16(isp, src->rsp.m2._reserved2,
+		    &dst->rsp.m2._reserved2);
+		ISP_IOXPUT_16(isp, src->rsp.m2._reserved3,
+		    &dst->rsp.m2._reserved3);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen,
+		    &dst->rsp.m2.ct_datalen);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
+		    &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
+		    &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
 	}
 }
 
 void
-isp_put_ctio2e(ispsoftc_t *isp, ct2e_entry_t *ctsrc, ct2e_entry_t *ctdst)
+isp_put_ctio2e(ispsoftc_t *isp, ct2e_entry_t *src, ct2e_entry_t *dst)
 {
 	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) {
+	isp_put_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle);
+	ISP_IOXPUT_16(isp, src->ct_iid, &dst->ct_iid);
+	ISP_IOXPUT_16(isp, src->ct_rxid, &dst->ct_rxid);
+	ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags);
+	ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout);
+	ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count);
+	ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid);
+	ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff);
+	if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
+		ISP_IOXPUT_32(isp, src->rsp.m0._reserved,
+		    &dst->rsp.m0._reserved);
+		ISP_IOXPUT_16(isp, src->rsp.m0._reserved2,
+		    &dst->rsp.m0._reserved2);
+		ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status,
+		    &dst->rsp.m0.ct_scsi_status);
+		ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen,
+		    &dst->rsp.m0.ct_xfrlen);
+		if (src->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);
+				    src->rsp.m0.u.ct_dataseg[i].ds_base,
+				    &dst->rsp.m0.u.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);
+				    src->rsp.m0.u.ct_dataseg[i].ds_count,
+				    &dst->rsp.m0.u.ct_dataseg[i].ds_count);
 			}
-		} else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
+		} else if (src->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);
+				    src->rsp.m0.u.ct_dataseg64[i].ds_base,
+				    &dst->rsp.m0.u.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);
+				    src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
+				    &dst->rsp.m0.u.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);
+				    src->rsp.m0.u.ct_dataseg64[i].ds_count,
+				    &dst->rsp.m0.u.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 (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
+			ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type,
+			    &dst->rsp.m0.u.ct_dslist.ds_type);
+			ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment,
+			    &dst->rsp.m0.u.ct_dslist.ds_segment);
+			ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base,
+			    &dst->rsp.m0.u.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);
+	} else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
+		ISP_IOXPUT_16(isp, src->rsp.m1._reserved,
+		    &dst->rsp.m1._reserved);
+		ISP_IOXPUT_16(isp, src->rsp.m1._reserved2,
+		    &dst->rsp.m1._reserved2);
+		ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen,
+		    &dst->rsp.m1.ct_senselen);
+		ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status,
+		    &dst->rsp.m1.ct_scsi_status);
+		ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen,
+		    &dst->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]);
+			ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i],
+			    &dst->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);
+		ISP_IOXPUT_32(isp, src->rsp.m2._reserved,
+		    &dst->rsp.m2._reserved);
+		ISP_IOXPUT_16(isp, src->rsp.m2._reserved2,
+		    &dst->rsp.m2._reserved2);
+		ISP_IOXPUT_16(isp, src->rsp.m2._reserved3,
+		    &dst->rsp.m2._reserved3);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen,
+		    &dst->rsp.m2.ct_datalen);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
+		    &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
+		    &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
 	}
 }
 
 void
-isp_get_ctio2(ispsoftc_t *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst)
+isp_put_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst)
 {
-	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_8(isp, &ctsrc->ct_lun, ctdst->ct_lun);
-	ISP_IOXGET_8(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);
+	int i;
+
+	isp_put_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle);
+	ISP_IOXPUT_16(isp, src->ct_nphdl, &dst->ct_nphdl);
+	ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout);
+	ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count);
+	ISP_IOXPUT_8(isp, src->ct_vpindex, &dst->ct_vpindex);
+	ISP_IOXPUT_8(isp, src->ct_xflags, &dst->ct_xflags);
+	ISP_IOXPUT_16(isp, src->ct_iid_lo, &dst->ct_iid_lo);
+	ISP_IOXPUT_8(isp, src->ct_iid_hi, &dst->ct_iid_hi);
+	ISP_IOXPUT_8(isp, src->ct_reserved, &dst->ct_reserved);
+	ISP_IOXPUT_32(isp, src->ct_rxid, &dst->ct_rxid);
+	ISP_IOXPUT_16(isp, src->ct_senselen, &dst->ct_senselen);
+	ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags);
+	ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid);
+	ISP_IOXPUT_16(isp, src->ct_oxid, &dst->ct_oxid);
+	ISP_IOXPUT_16(isp, src->ct_scsi_status, &dst->ct_scsi_status);
+	if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) {
+		ISP_IOXPUT_32(isp, src->rsp.m0.reloff, &dst->rsp.m0.reloff);
+		ISP_IOXPUT_32(isp, src->rsp.m0.reserved0,
+		    &dst->rsp.m0.reserved0);
+		ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen,
+		    &dst->rsp.m0.ct_xfrlen);
+		ISP_IOXPUT_32(isp, src->rsp.m0.reserved1,
+		    &dst->rsp.m0.reserved1);
+		ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_base,
+		    &dst->rsp.m0.ds.ds_base);
+		ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_basehi,
+		    &dst->rsp.m0.ds.ds_basehi);
+		ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_count,
+		    &dst->rsp.m0.ds.ds_count);
+	} else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) {
+		ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen,
+		    &dst->rsp.m1.ct_resplen);
+		ISP_IOXPUT_16(isp, src->rsp.m1.reserved, &dst->rsp.m1.reserved);
+		for (i = 0; i < MAXRESPLEN_24XX; i++) {
+			ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i],
+			    &dst->rsp.m1.ct_resp[i]);
+		}
+	} else {
+		ISP_IOXPUT_32(isp, src->rsp.m2.reserved0,
+		    &dst->rsp.m2.reserved0);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen,
+		    &dst->rsp.m2.ct_datalen);
+		ISP_IOXPUT_32(isp, src->rsp.m2.reserved1,
+		    &dst->rsp.m2.reserved1);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
+		    &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi,
+		    &dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi);
+		ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
+		    &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+	}
+}
+
+
+void
+isp_get_ctio2(ispsoftc_t *isp, ct2_entry_t *src, ct2_entry_t *dst)
+{
+	int i;
+
+	isp_get_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle);
+	ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_lun);
+	ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_iid);
+	ISP_IOXGET_16(isp, &src->ct_rxid, dst->ct_rxid);
+	ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags);
+	ISP_IOXGET_16(isp, &src->ct_status, dst->ct_status);
+	ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout);
+	ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count);
+	ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff);
+	ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid);
+	if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
+		ISP_IOXGET_32(isp, &src->rsp.m0._reserved,
+		    dst->rsp.m0._reserved);
+		ISP_IOXGET_16(isp, &src->rsp.m0._reserved2,
+		    dst->rsp.m0._reserved2);
+		ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status,
+		    dst->rsp.m0.ct_scsi_status);
+		ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen,
+		    dst->rsp.m0.ct_xfrlen);
+		if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO2) {
+			for (i = 0; i < ISP_RQDSEG_T2; i++) {
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg[i].ds_base,
+				    dst->rsp.m0.u.ct_dataseg[i].ds_base);
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg[i].ds_count,
+				    dst->rsp.m0.u.ct_dataseg[i].ds_count);
+			}
+		} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
+			for (i = 0; i < ISP_RQDSEG_T3; i++) {
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg64[i].ds_base,
+				    dst->rsp.m0.u.ct_dataseg64[i].ds_base);
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
+				    dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg64[i].ds_count,
+				    dst->rsp.m0.u.ct_dataseg64[i].ds_count);
+			}
+		} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
+			ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type,
+			    dst->rsp.m0.u.ct_dslist.ds_type);
+			ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment,
+			    dst->rsp.m0.u.ct_dslist.ds_segment);
+			ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base,
+			    dst->rsp.m0.u.ct_dslist.ds_base);
+		}
+	} else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
+		ISP_IOXGET_16(isp, &src->rsp.m1._reserved,
+		    dst->rsp.m1._reserved);
+		ISP_IOXGET_16(isp, &src->rsp.m1._reserved2,
+		    dst->rsp.m1._reserved2);
+		ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen,
+		    dst->rsp.m1.ct_senselen);
+		ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status,
+		    dst->rsp.m1.ct_scsi_status);
+		ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen,
+		    dst->rsp.m1.ct_resplen);
+		for (i = 0; i < MAXRESPLEN; i++) {
+			ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i],
+			    dst->rsp.m1.ct_resp[i]);
+		}
+	} else {
+		ISP_IOXGET_32(isp, &src->rsp.m2._reserved,
+		    dst->rsp.m2._reserved);
+		ISP_IOXGET_16(isp, &src->rsp.m2._reserved2,
+		    dst->rsp.m2._reserved2);
+		ISP_IOXGET_16(isp, &src->rsp.m2._reserved3,
+		    dst->rsp.m2._reserved3);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen,
+		    dst->rsp.m2.ct_datalen);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
+		    dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
+		    dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+	}
 }
 
 void
-isp_get_ctio2e(ispsoftc_t *isp, ct2e_entry_t *ctsrc, ct2e_entry_t *ctdst)
+isp_get_ctio2e(ispsoftc_t *isp, ct2e_entry_t *src, ct2e_entry_t *dst)
 {
-	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);
+	int i;
+
+	isp_get_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle);
+	ISP_IOXGET_16(isp, &src->ct_iid, dst->ct_iid);
+	ISP_IOXGET_16(isp, &src->ct_rxid, dst->ct_rxid);
+	ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags);
+	ISP_IOXGET_16(isp, &src->ct_status, dst->ct_status);
+	ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout);
+	ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count);
+	ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff);
+	ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid);
+	if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
+		ISP_IOXGET_32(isp, &src->rsp.m0._reserved,
+		    dst->rsp.m0._reserved);
+		ISP_IOXGET_16(isp, &src->rsp.m0._reserved2,
+		    dst->rsp.m0._reserved2);
+		ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status,
+		    dst->rsp.m0.ct_scsi_status);
+		ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen,
+		    dst->rsp.m0.ct_xfrlen);
+		if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) {
+			for (i = 0; i < ISP_RQDSEG_T2; i++) {
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg[i].ds_base,
+				    dst->rsp.m0.u.ct_dataseg[i].ds_base);
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg[i].ds_count,
+				    dst->rsp.m0.u.ct_dataseg[i].ds_count);
+			}
+		} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
+			for (i = 0; i < ISP_RQDSEG_T3; i++) {
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg64[i].ds_base,
+				    dst->rsp.m0.u.ct_dataseg64[i].ds_base);
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
+				    dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
+				ISP_IOXGET_32(isp,
+				    &src->rsp.m0.u.ct_dataseg64[i].ds_count,
+				    dst->rsp.m0.u.ct_dataseg64[i].ds_count);
+			}
+		} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
+			ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type,
+			    dst->rsp.m0.u.ct_dslist.ds_type);
+			ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment,
+			    dst->rsp.m0.u.ct_dslist.ds_segment);
+			ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base,
+			    dst->rsp.m0.u.ct_dslist.ds_base);
+		}
+	} else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
+		ISP_IOXGET_16(isp, &src->rsp.m1._reserved,
+		    dst->rsp.m1._reserved);
+		ISP_IOXGET_16(isp, &src->rsp.m1._reserved2,
+		    dst->rsp.m1._reserved2);
+		ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen,
+		    dst->rsp.m1.ct_senselen);
+		ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status,
+		    dst->rsp.m1.ct_scsi_status);
+		ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen,
+		    dst->rsp.m1.ct_resplen);
+		for (i = 0; i < MAXRESPLEN; i++) {
+			ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i],
+			    dst->rsp.m1.ct_resp[i]);
+		}
+	} else {
+		ISP_IOXGET_32(isp, &src->rsp.m2._reserved,
+		    dst->rsp.m2._reserved);
+		ISP_IOXGET_16(isp, &src->rsp.m2._reserved2,
+		    dst->rsp.m2._reserved2);
+		ISP_IOXGET_16(isp, &src->rsp.m2._reserved3,
+		    dst->rsp.m2._reserved3);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen,
+		    dst->rsp.m2.ct_datalen);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
+		    dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
+		    dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+	}
+}
+
+void
+isp_get_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst)
+{
+	int i;
+
+	isp_get_hdr(isp, &src->ct_header, &dst->ct_header);
+	ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle);
+	ISP_IOXGET_16(isp, &src->ct_nphdl, dst->ct_nphdl);
+	ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout);
+	ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count);
+	ISP_IOXGET_8(isp, &src->ct_vpindex, dst->ct_vpindex);
+	ISP_IOXGET_8(isp, &src->ct_xflags, dst->ct_xflags);
+	ISP_IOXGET_16(isp, &src->ct_iid_lo, dst->ct_iid_lo);
+	ISP_IOXGET_8(isp, &src->ct_iid_hi, dst->ct_iid_hi);
+	ISP_IOXGET_8(isp, &src->ct_reserved, dst->ct_reserved);
+	ISP_IOXGET_32(isp, &src->ct_rxid, dst->ct_rxid);
+	ISP_IOXGET_16(isp, &src->ct_senselen, dst->ct_senselen);
+	ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags);
+	ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid);
+	ISP_IOXGET_16(isp, &src->ct_oxid, dst->ct_oxid);
+	ISP_IOXGET_16(isp, &src->ct_scsi_status, dst->ct_scsi_status);
+	if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) {
+		ISP_IOXGET_32(isp, &src->rsp.m0.reloff, dst->rsp.m0.reloff);
+		ISP_IOXGET_32(isp, &src->rsp.m0.reserved0,
+		    dst->rsp.m0.reserved0);
+		ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen,
+		    dst->rsp.m0.ct_xfrlen);
+		ISP_IOXGET_32(isp, &src->rsp.m0.reserved1,
+		    dst->rsp.m0.reserved1);
+		ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_base,
+		    dst->rsp.m0.ds.ds_base);
+		ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_basehi,
+		    dst->rsp.m0.ds.ds_basehi);
+		ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_count,
+		    dst->rsp.m0.ds.ds_count);
+	} else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) {
+		ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen,
+		    dst->rsp.m1.ct_resplen);
+		ISP_IOXGET_16(isp, &src->rsp.m1.reserved, dst->rsp.m1.reserved);
+		for (i = 0; i < MAXRESPLEN_24XX; i++) {
+			ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i],
+			    dst->rsp.m1.ct_resp[i]);
+		}
+	} else {
+		ISP_IOXGET_32(isp, &src->rsp.m2.reserved0,
+		    dst->rsp.m2.reserved0);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen,
+		    dst->rsp.m2.ct_datalen);
+		ISP_IOXGET_32(isp, &src->rsp.m2.reserved1,
+		    dst->rsp.m2.reserved1);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
+		    dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi,
+		    dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi);
+		ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
+		    dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+	}
 }
 
 void
 isp_put_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst)
 {
 	int i;
-	isp_copy_out_hdr(isp, &lesrc->le_header, &ledst->le_header);
+	isp_put_hdr(isp, &lesrc->le_header, &ledst->le_header);
 	ISP_IOXPUT_32(isp, lesrc->le_reserved, &ledst->le_reserved);
 	if (ISP_IS_SBUS(isp)) {
 		ISP_IOXPUT_8(isp, lesrc->le_lun, &ledst->le_rsvd);
@@ -1422,7 +2202,7 @@ void
 isp_get_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst)
 {
 	int i;
-	isp_copy_in_hdr(isp, &lesrc->le_header, &ledst->le_header);
+	isp_get_hdr(isp, &lesrc->le_header, &ledst->le_header);
 	ISP_IOXGET_32(isp, &lesrc->le_reserved, ledst->le_reserved);
 	if (ISP_IS_SBUS(isp)) {
 		ISP_IOXGET_8(isp, &lesrc->le_lun, ledst->le_rsvd);
@@ -1456,270 +2236,557 @@ isp_get_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst)
 }
 
 void
-isp_put_notify(ispsoftc_t *isp, in_entry_t *insrc, in_entry_t *indst)
+isp_put_notify(ispsoftc_t *isp, in_entry_t *src, in_entry_t *dst)
 {
 	int i;
-	isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header);
-	ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved);
+	isp_put_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_iid);
-		ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_lun);
-		ISP_IOXPUT_8(isp, insrc->in_reserved2, &indst->in_tgt);
-		ISP_IOXPUT_8(isp, insrc->in_tgt, &indst->in_reserved2);
-		ISP_IOXPUT_8(isp, insrc->in_status, &indst->in_rsvd2);
-		ISP_IOXPUT_8(isp, insrc->in_rsvd2, &indst->in_status);
-		ISP_IOXPUT_8(isp, insrc->in_tag_val, &indst->in_tag_type);
-		ISP_IOXPUT_8(isp, insrc->in_tag_type, &indst->in_tag_val);
+		ISP_IOXPUT_8(isp, src->in_lun, &dst->in_iid);
+		ISP_IOXPUT_8(isp, src->in_iid, &dst->in_lun);
+		ISP_IOXPUT_8(isp, src->in_reserved2, &dst->in_tgt);
+		ISP_IOXPUT_8(isp, src->in_tgt, &dst->in_reserved2);
+		ISP_IOXPUT_8(isp, src->in_status, &dst->in_rsvd2);
+		ISP_IOXPUT_8(isp, src->in_rsvd2, &dst->in_status);
+		ISP_IOXPUT_8(isp, src->in_tag_val, &dst->in_tag_type);
+		ISP_IOXPUT_8(isp, src->in_tag_type, &dst->in_tag_val);
 	} else {
-		ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_lun);
-		ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_iid);
-		ISP_IOXPUT_8(isp, insrc->in_reserved2, &indst->in_reserved2);
-		ISP_IOXPUT_8(isp, insrc->in_tgt, &indst->in_tgt);
-		ISP_IOXPUT_8(isp, insrc->in_status, &indst->in_status);
-		ISP_IOXPUT_8(isp, insrc->in_rsvd2, &indst->in_rsvd2);
-		ISP_IOXPUT_8(isp, insrc->in_tag_val, &indst->in_tag_val);
-		ISP_IOXPUT_8(isp, insrc->in_tag_type, &indst->in_tag_type);
+		ISP_IOXPUT_8(isp, src->in_lun, &dst->in_lun);
+		ISP_IOXPUT_8(isp, src->in_iid, &dst->in_iid);
+		ISP_IOXPUT_8(isp, src->in_reserved2, &dst->in_reserved2);
+		ISP_IOXPUT_8(isp, src->in_tgt, &dst->in_tgt);
+		ISP_IOXPUT_8(isp, src->in_status, &dst->in_status);
+		ISP_IOXPUT_8(isp, src->in_rsvd2, &dst->in_rsvd2);
+		ISP_IOXPUT_8(isp, src->in_tag_val, &dst->in_tag_val);
+		ISP_IOXPUT_8(isp, src->in_tag_type, &dst->in_tag_type);
 	}
-	ISP_IOXPUT_32(isp, insrc->in_flags, &indst->in_flags);
-	ISP_IOXPUT_16(isp, insrc->in_seqid, &indst->in_seqid);
+	ISP_IOXPUT_32(isp, src->in_flags, &dst->in_flags);
+	ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid);
 	for (i = 0; i < IN_MSGLEN; i++) {
-		ISP_IOXPUT_8(isp, insrc->in_msg[i], &indst->in_msg[i]);
+		ISP_IOXPUT_8(isp, src->in_msg[i], &dst->in_msg[i]);
 	}
 	for (i = 0; i < IN_RSVDLEN; i++) {
-		ISP_IOXPUT_8(isp, insrc->in_reserved3[i],
-		    &indst->in_reserved3[i]);
+		ISP_IOXPUT_8(isp, src->in_reserved3[i],
+		    &dst->in_reserved3[i]);
 	}
 	for (i = 0; i < QLTM_SENSELEN; i++) {
-		ISP_IOXPUT_8(isp, insrc->in_sense[i],
-		    &indst->in_sense[i]);
+		ISP_IOXPUT_8(isp, src->in_sense[i],
+		    &dst->in_sense[i]);
 	}
 }
 
 void
-isp_get_notify(ispsoftc_t *isp, in_entry_t *insrc, in_entry_t *indst)
+isp_get_notify(ispsoftc_t *isp, in_entry_t *src, in_entry_t *dst)
 {
 	int i;
-	isp_copy_in_hdr(isp, &insrc->in_header, &indst->in_header);
-	ISP_IOXGET_32(isp, &insrc->in_reserved, indst->in_reserved);
+	isp_get_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_iid);
-		ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_lun);
-		ISP_IOXGET_8(isp, &insrc->in_reserved2, indst->in_tgt);
-		ISP_IOXGET_8(isp, &insrc->in_tgt, indst->in_reserved2);
-		ISP_IOXGET_8(isp, &insrc->in_status, indst->in_rsvd2);
-		ISP_IOXGET_8(isp, &insrc->in_rsvd2, indst->in_status);
-		ISP_IOXGET_8(isp, &insrc->in_tag_val, indst->in_tag_type);
-		ISP_IOXGET_8(isp, &insrc->in_tag_type, indst->in_tag_val);
+		ISP_IOXGET_8(isp, &src->in_lun, dst->in_iid);
+		ISP_IOXGET_8(isp, &src->in_iid, dst->in_lun);
+		ISP_IOXGET_8(isp, &src->in_reserved2, dst->in_tgt);
+		ISP_IOXGET_8(isp, &src->in_tgt, dst->in_reserved2);
+		ISP_IOXGET_8(isp, &src->in_status, dst->in_rsvd2);
+		ISP_IOXGET_8(isp, &src->in_rsvd2, dst->in_status);
+		ISP_IOXGET_8(isp, &src->in_tag_val, dst->in_tag_type);
+		ISP_IOXGET_8(isp, &src->in_tag_type, dst->in_tag_val);
 	} else {
-		ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_lun);
-		ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_iid);
-		ISP_IOXGET_8(isp, &insrc->in_reserved2, indst->in_reserved2);
-		ISP_IOXGET_8(isp, &insrc->in_tgt, indst->in_tgt);
-		ISP_IOXGET_8(isp, &insrc->in_status, indst->in_status);
-		ISP_IOXGET_8(isp, &insrc->in_rsvd2, indst->in_rsvd2);
-		ISP_IOXGET_8(isp, &insrc->in_tag_val, indst->in_tag_val);
-		ISP_IOXGET_8(isp, &insrc->in_tag_type, indst->in_tag_type);
+		ISP_IOXGET_8(isp, &src->in_lun, dst->in_lun);
+		ISP_IOXGET_8(isp, &src->in_iid, dst->in_iid);
+		ISP_IOXGET_8(isp, &src->in_reserved2, dst->in_reserved2);
+		ISP_IOXGET_8(isp, &src->in_tgt, dst->in_tgt);
+		ISP_IOXGET_8(isp, &src->in_status, dst->in_status);
+		ISP_IOXGET_8(isp, &src->in_rsvd2, dst->in_rsvd2);
+		ISP_IOXGET_8(isp, &src->in_tag_val, dst->in_tag_val);
+		ISP_IOXGET_8(isp, &src->in_tag_type, dst->in_tag_type);
 	}
-	ISP_IOXGET_32(isp, &insrc->in_flags, indst->in_flags);
-	ISP_IOXGET_16(isp, &insrc->in_seqid, indst->in_seqid);
+	ISP_IOXGET_32(isp, &src->in_flags, dst->in_flags);
+	ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid);
 	for (i = 0; i < IN_MSGLEN; i++) {
-		ISP_IOXGET_8(isp, &insrc->in_msg[i], indst->in_msg[i]);
+		ISP_IOXGET_8(isp, &src->in_msg[i], dst->in_msg[i]);
 	}
 	for (i = 0; i < IN_RSVDLEN; i++) {
-		ISP_IOXGET_8(isp, &insrc->in_reserved3[i],
-		    indst->in_reserved3[i]);
+		ISP_IOXGET_8(isp, &src->in_reserved3[i],
+		    dst->in_reserved3[i]);
 	}
 	for (i = 0; i < QLTM_SENSELEN; i++) {
-		ISP_IOXGET_8(isp, &insrc->in_sense[i],
-		    indst->in_sense[i]);
+		ISP_IOXGET_8(isp, &src->in_sense[i],
+		    dst->in_sense[i]);
 	}
 }
 
 void
-isp_put_notify_fc(ispsoftc_t *isp, in_fcentry_t *insrc,
-    in_fcentry_t *indst)
+isp_put_notify_fc(ispsoftc_t *isp, in_fcentry_t *src,
+    in_fcentry_t *dst)
 {
-	isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header);
-	ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved);
-	ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_lun);
-	ISP_IOXPUT_8(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);
+	isp_put_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved);
+	ISP_IOXPUT_8(isp, src->in_lun, &dst->in_lun);
+	ISP_IOXPUT_8(isp, src->in_iid, &dst->in_iid);
+	ISP_IOXPUT_16(isp, src->in_scclun, &dst->in_scclun);
+	ISP_IOXPUT_32(isp, src->in_reserved2, &dst->in_reserved2);
+	ISP_IOXPUT_16(isp, src->in_status, &dst->in_status);
+	ISP_IOXPUT_16(isp, src->in_task_flags, &dst->in_task_flags);
+	ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid);
 }
 
 void
-isp_put_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *insrc,
-    in_fcentry_e_t *indst)
+isp_put_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src,
+    in_fcentry_e_t *dst)
 {
-	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);
+	isp_put_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved);
+	ISP_IOXPUT_16(isp, src->in_iid, &dst->in_iid);
+	ISP_IOXPUT_16(isp, src->in_scclun, &dst->in_scclun);
+	ISP_IOXPUT_32(isp, src->in_reserved2, &dst->in_reserved2);
+	ISP_IOXPUT_16(isp, src->in_status, &dst->in_status);
+	ISP_IOXPUT_16(isp, src->in_task_flags, &dst->in_task_flags);
+	ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid);
 }
 
 void
-isp_get_notify_fc(ispsoftc_t *isp, in_fcentry_t *insrc,
-    in_fcentry_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_8(isp, &insrc->in_lun, indst->in_lun);
-	ISP_IOXGET_8(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);
-}
-
-void
-isp_get_notify_fc_e(ispsoftc_t *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);
-}
-
-void
-isp_put_notify_ack(ispsoftc_t *isp, na_entry_t *nasrc,  na_entry_t *nadst)
+isp_put_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src,
+    in_fcentry_24xx_t *dst)
 {
 	int i;
-	isp_copy_out_hdr(isp, &nasrc->na_header, &nadst->na_header);
-	ISP_IOXPUT_32(isp, nasrc->na_reserved, &nadst->na_reserved);
+
+	isp_put_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved);
+	ISP_IOXPUT_16(isp, src->in_nphdl, &dst->in_nphdl);
+	ISP_IOXPUT_16(isp, src->in_reserved1, &dst->in_reserved1);
+	ISP_IOXPUT_16(isp, src->in_flags, &dst->in_flags);
+	ISP_IOXPUT_16(isp, src->in_srr_rxid, &dst->in_srr_rxid);
+	ISP_IOXPUT_16(isp, src->in_status, &dst->in_status);
+	ISP_IOXPUT_8(isp, src->in_status_subcode, &dst->in_status_subcode);
+	ISP_IOXPUT_16(isp, src->in_reserved2, &dst->in_reserved2);
+	ISP_IOXPUT_32(isp, src->in_rxid, &dst->in_rxid);
+	ISP_IOXPUT_16(isp, src->in_srr_reloff_hi, &dst->in_srr_reloff_hi);
+	ISP_IOXPUT_16(isp, src->in_srr_reloff_lo, &dst->in_srr_reloff_lo);
+	ISP_IOXPUT_16(isp, src->in_srr_iu, &dst->in_srr_iu);
+	ISP_IOXPUT_16(isp, src->in_srr_oxid, &dst->in_srr_oxid);
+	for (i = 0; i < 18; i++) {
+		ISP_IOXPUT_8(isp, src->in_reserved3[i], &dst->in_reserved3[i]);
+	}
+	ISP_IOXPUT_8(isp, src->in_reserved4, &dst->in_reserved4);
+	ISP_IOXPUT_8(isp, src->in_vpindex, &dst->in_vpindex);
+	ISP_IOXPUT_32(isp, src->in_reserved5, &dst->in_reserved5);
+	ISP_IOXPUT_16(isp, src->in_portid_lo, &dst->in_portid_lo);
+	ISP_IOXPUT_8(isp, src->in_portid_hi, &dst->in_portid_hi);
+	ISP_IOXPUT_8(isp, src->in_reserved6, &dst->in_reserved6);
+	ISP_IOXPUT_16(isp, src->in_reserved7, &dst->in_reserved7);
+	ISP_IOXPUT_16(isp, src->in_oxid, &dst->in_oxid);
+}
+
+void
+isp_get_notify_fc(ispsoftc_t *isp, in_fcentry_t *src,
+    in_fcentry_t *dst)
+{
+	isp_get_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved);
+	ISP_IOXGET_8(isp, &src->in_lun, dst->in_lun);
+	ISP_IOXGET_8(isp, &src->in_iid, dst->in_iid);
+	ISP_IOXGET_16(isp, &src->in_scclun, dst->in_scclun);
+	ISP_IOXGET_32(isp, &src->in_reserved2, dst->in_reserved2);
+	ISP_IOXGET_16(isp, &src->in_status, dst->in_status);
+	ISP_IOXGET_16(isp, &src->in_task_flags, dst->in_task_flags);
+	ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid);
+}
+
+void
+isp_get_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src,
+    in_fcentry_e_t *dst)
+{
+	isp_get_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved);
+	ISP_IOXGET_16(isp, &src->in_iid, dst->in_iid);
+	ISP_IOXGET_16(isp, &src->in_scclun, dst->in_scclun);
+	ISP_IOXGET_32(isp, &src->in_reserved2, dst->in_reserved2);
+	ISP_IOXGET_16(isp, &src->in_status, dst->in_status);
+	ISP_IOXGET_16(isp, &src->in_task_flags, dst->in_task_flags);
+	ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid);
+}
+
+void
+isp_get_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src,
+    in_fcentry_24xx_t *dst)
+{
+	int i;
+
+	isp_get_hdr(isp, &src->in_header, &dst->in_header);
+	ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved);
+	ISP_IOXGET_16(isp, &src->in_nphdl, dst->in_nphdl);
+	ISP_IOXGET_16(isp, &src->in_reserved1, dst->in_reserved1);
+	ISP_IOXGET_16(isp, &src->in_flags, dst->in_flags);
+	ISP_IOXGET_16(isp, &src->in_srr_rxid, dst->in_srr_rxid);
+	ISP_IOXGET_16(isp, &src->in_status, dst->in_status);
+	ISP_IOXGET_8(isp, &src->in_status_subcode, dst->in_status_subcode);
+	ISP_IOXGET_16(isp, &src->in_reserved2, dst->in_reserved2);
+	ISP_IOXGET_32(isp, &src->in_rxid, dst->in_rxid);
+	ISP_IOXGET_16(isp, &src->in_srr_reloff_hi, dst->in_srr_reloff_hi);
+	ISP_IOXGET_16(isp, &src->in_srr_reloff_lo, dst->in_srr_reloff_lo);
+	ISP_IOXGET_16(isp, &src->in_srr_iu, dst->in_srr_iu);
+	ISP_IOXGET_16(isp, &src->in_srr_oxid, dst->in_srr_oxid);
+	for (i = 0; i < 18; i++) {
+		ISP_IOXGET_8(isp, &src->in_reserved3[i], dst->in_reserved3[i]);
+	}
+	ISP_IOXGET_8(isp, &src->in_reserved4, dst->in_reserved4);
+	ISP_IOXGET_8(isp, &src->in_vpindex, dst->in_vpindex);
+	ISP_IOXGET_32(isp, &src->in_reserved5, dst->in_reserved5);
+	ISP_IOXGET_16(isp, &src->in_portid_lo, dst->in_portid_lo);
+	ISP_IOXGET_8(isp, &src->in_portid_hi, dst->in_portid_hi);
+	ISP_IOXGET_8(isp, &src->in_reserved6, dst->in_reserved6);
+	ISP_IOXGET_16(isp, &src->in_reserved7, dst->in_reserved7);
+	ISP_IOXGET_16(isp, &src->in_oxid, dst->in_oxid);
+}
+
+void
+isp_put_notify_ack(ispsoftc_t *isp, na_entry_t *src,  na_entry_t *dst)
+{
+	int i;
+	isp_put_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXPUT_8(isp, nasrc->na_lun, &nadst->na_iid);
-		ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_lun);
-		ISP_IOXPUT_8(isp, nasrc->na_status, &nadst->na_event);
-		ISP_IOXPUT_8(isp, nasrc->na_event, &nadst->na_status);
+		ISP_IOXPUT_8(isp, src->na_lun, &dst->na_iid);
+		ISP_IOXPUT_8(isp, src->na_iid, &dst->na_lun);
+		ISP_IOXPUT_8(isp, src->na_status, &dst->na_event);
+		ISP_IOXPUT_8(isp, src->na_event, &dst->na_status);
 	} else {
-		ISP_IOXPUT_8(isp, nasrc->na_lun, &nadst->na_lun);
-		ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_iid);
-		ISP_IOXPUT_8(isp, nasrc->na_status, &nadst->na_status);
-		ISP_IOXPUT_8(isp, nasrc->na_event, &nadst->na_event);
+		ISP_IOXPUT_8(isp, src->na_lun, &dst->na_lun);
+		ISP_IOXPUT_8(isp, src->na_iid, &dst->na_iid);
+		ISP_IOXPUT_8(isp, src->na_status, &dst->na_status);
+		ISP_IOXPUT_8(isp, src->na_event, &dst->na_event);
 	}
-	ISP_IOXPUT_32(isp, nasrc->na_flags, &nadst->na_flags);
+	ISP_IOXPUT_32(isp, src->na_flags, &dst->na_flags);
 	for (i = 0; i < NA_RSVDLEN; i++) {
-		ISP_IOXPUT_16(isp, nasrc->na_reserved3[i],
-		    &nadst->na_reserved3[i]);
+		ISP_IOXPUT_16(isp, src->na_reserved3[i],
+		    &dst->na_reserved3[i]);
 	}
 }
 
 void
-isp_get_notify_ack(ispsoftc_t *isp, na_entry_t *nasrc, na_entry_t *nadst)
+isp_get_notify_ack(ispsoftc_t *isp, na_entry_t *src, na_entry_t *dst)
 {
 	int i;
-	isp_copy_in_hdr(isp, &nasrc->na_header, &nadst->na_header);
-	ISP_IOXGET_32(isp, &nasrc->na_reserved, nadst->na_reserved);
+	isp_get_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved);
 	if (ISP_IS_SBUS(isp)) {
-		ISP_IOXGET_8(isp, &nasrc->na_lun, nadst->na_iid);
-		ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_lun);
-		ISP_IOXGET_8(isp, &nasrc->na_status, nadst->na_event);
-		ISP_IOXGET_8(isp, &nasrc->na_event, nadst->na_status);
+		ISP_IOXGET_8(isp, &src->na_lun, dst->na_iid);
+		ISP_IOXGET_8(isp, &src->na_iid, dst->na_lun);
+		ISP_IOXGET_8(isp, &src->na_status, dst->na_event);
+		ISP_IOXGET_8(isp, &src->na_event, dst->na_status);
 	} else {
-		ISP_IOXGET_8(isp, &nasrc->na_lun, nadst->na_lun);
-		ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_iid);
-		ISP_IOXGET_8(isp, &nasrc->na_status, nadst->na_status);
-		ISP_IOXGET_8(isp, &nasrc->na_event, nadst->na_event);
+		ISP_IOXGET_8(isp, &src->na_lun, dst->na_lun);
+		ISP_IOXGET_8(isp, &src->na_iid, dst->na_iid);
+		ISP_IOXGET_8(isp, &src->na_status, dst->na_status);
+		ISP_IOXGET_8(isp, &src->na_event, dst->na_event);
 	}
-	ISP_IOXGET_32(isp, &nasrc->na_flags, nadst->na_flags);
+	ISP_IOXGET_32(isp, &src->na_flags, dst->na_flags);
 	for (i = 0; i < NA_RSVDLEN; i++) {
-		ISP_IOXGET_16(isp, &nasrc->na_reserved3[i],
-		    nadst->na_reserved3[i]);
+		ISP_IOXGET_16(isp, &src->na_reserved3[i],
+		    dst->na_reserved3[i]);
 	}
 }
 
 void
-isp_put_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *nasrc,
-    na_fcentry_t *nadst)
+isp_put_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src,
+    na_fcentry_t *dst)
 {
 	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_8(isp, nasrc->na_reserved1, &nadst->na_reserved1);
-	ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_iid);
-	ISP_IOXPUT_16(isp, nasrc->na_response, &nadst->na_response);
-	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);
+	isp_put_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved);
+	ISP_IOXPUT_8(isp, src->na_reserved1, &dst->na_reserved1);
+	ISP_IOXPUT_8(isp, src->na_iid, &dst->na_iid);
+	ISP_IOXPUT_16(isp, src->na_response, &dst->na_response);
+	ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags);
+	ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2);
+	ISP_IOXPUT_16(isp, src->na_status, &dst->na_status);
+	ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags);
+	ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid);
 	for (i = 0; i < NA2_RSVDLEN; i++) {
-		ISP_IOXPUT_16(isp, nasrc->na_reserved3[i],
-		    &nadst->na_reserved3[i]);
+		ISP_IOXPUT_16(isp, src->na_reserved3[i],
+		    &dst->na_reserved3[i]);
 	}
 }
 
 void
-isp_put_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *nasrc,
-    na_fcentry_e_t *nadst)
+isp_put_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src,
+    na_fcentry_e_t *dst)
 {
 	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_response, &nadst->na_response);
-	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);
+	isp_put_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved);
+	ISP_IOXPUT_16(isp, src->na_iid, &dst->na_iid);
+	ISP_IOXPUT_16(isp, src->na_response, &dst->na_response);
+	ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags);
+	ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2);
+	ISP_IOXPUT_16(isp, src->na_status, &dst->na_status);
+	ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags);
+	ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid);
 	for (i = 0; i < NA2_RSVDLEN; i++) {
-		ISP_IOXPUT_16(isp, nasrc->na_reserved3[i],
-		    &nadst->na_reserved3[i]);
+		ISP_IOXPUT_16(isp, src->na_reserved3[i],
+		    &dst->na_reserved3[i]);
 	}
 }
 
 void
-isp_get_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *nasrc,
-    na_fcentry_t *nadst)
+isp_put_notify_24xx_ack(ispsoftc_t *isp, na_fcentry_24xx_t *src,
+    na_fcentry_24xx_t *dst)
 {
 	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_8(isp, &nasrc->na_reserved1, nadst->na_reserved1);
-	ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_iid);
-	ISP_IOXGET_16(isp, &nasrc->na_response, nadst->na_response);
-	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);
+
+	isp_put_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXPUT_32(isp, src->na_handle, &dst->na_handle);
+	ISP_IOXPUT_16(isp, src->na_nphdl, &dst->na_nphdl);
+	ISP_IOXPUT_16(isp, src->na_reserved1, &dst->na_reserved1);
+	ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags);
+	ISP_IOXPUT_16(isp, src->na_srr_rxid, &dst->na_srr_rxid);
+	ISP_IOXPUT_16(isp, src->na_status, &dst->na_status);
+	ISP_IOXPUT_8(isp, src->na_status_subcode, &dst->na_status_subcode);
+	ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2);
+	ISP_IOXPUT_32(isp, src->na_rxid, &dst->na_rxid);
+	ISP_IOXPUT_16(isp, src->na_srr_reloff_hi, &dst->na_srr_reloff_hi);
+	ISP_IOXPUT_16(isp, src->na_srr_reloff_lo, &dst->na_srr_reloff_lo);
+	ISP_IOXPUT_16(isp, src->na_srr_iu, &dst->na_srr_iu);
+	ISP_IOXPUT_16(isp, src->na_srr_flags, &dst->na_srr_flags);
+	for (i = 0; i < 18; i++) {
+		ISP_IOXPUT_8(isp, src->na_reserved3[i], &dst->na_reserved3[i]);
+	}
+	ISP_IOXPUT_8(isp, src->na_reserved4, &dst->na_reserved4);
+	ISP_IOXPUT_8(isp, src->na_vpindex, &dst->na_vpindex);
+	ISP_IOXPUT_8(isp, src->na_srr_reject_vunique,
+	    &dst->na_srr_reject_vunique);
+	ISP_IOXPUT_8(isp, src->na_srr_reject_explanation,
+	    &dst->na_srr_reject_explanation);
+	ISP_IOXPUT_8(isp, src->na_srr_reject_code, &dst->na_srr_reject_code);
+	ISP_IOXPUT_8(isp, src->na_reserved5, &dst->na_reserved5);
+	for (i = 0; i < 6; i++) {
+		ISP_IOXPUT_8(isp, src->na_reserved6[i], &dst->na_reserved6[i]);
+	}
+	ISP_IOXPUT_16(isp, src->na_oxid, &dst->na_oxid);
+}
+
+void
+isp_get_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src,
+    na_fcentry_t *dst)
+{
+	int i;
+	isp_get_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved);
+	ISP_IOXGET_8(isp, &src->na_reserved1, dst->na_reserved1);
+	ISP_IOXGET_8(isp, &src->na_iid, dst->na_iid);
+	ISP_IOXGET_16(isp, &src->na_response, dst->na_response);
+	ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags);
+	ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2);
+	ISP_IOXGET_16(isp, &src->na_status, dst->na_status);
+	ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags);
+	ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid);
 	for (i = 0; i < NA2_RSVDLEN; i++) {
-		ISP_IOXGET_16(isp, &nasrc->na_reserved3[i],
-		    nadst->na_reserved3[i]);
+		ISP_IOXGET_16(isp, &src->na_reserved3[i],
+		    dst->na_reserved3[i]);
 	}
 }
 
 void
-isp_get_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *nasrc,
-    na_fcentry_e_t *nadst)
+isp_get_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src,
+    na_fcentry_e_t *dst)
 {
 	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_response, nadst->na_response);
-	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);
+	isp_get_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved);
+	ISP_IOXGET_16(isp, &src->na_iid, dst->na_iid);
+	ISP_IOXGET_16(isp, &src->na_response, dst->na_response);
+	ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags);
+	ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2);
+	ISP_IOXGET_16(isp, &src->na_status, dst->na_status);
+	ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags);
+	ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid);
 	for (i = 0; i < NA2_RSVDLEN; i++) {
-		ISP_IOXGET_16(isp, &nasrc->na_reserved3[i],
-		    nadst->na_reserved3[i]);
+		ISP_IOXGET_16(isp, &src->na_reserved3[i],
+		    dst->na_reserved3[i]);
 	}
 }
+
+void
+isp_get_notify_ack_24xx(ispsoftc_t *isp, na_fcentry_24xx_t *src,
+    na_fcentry_24xx_t *dst)
+{
+	int i;
+
+	isp_get_hdr(isp, &src->na_header, &dst->na_header);
+	ISP_IOXGET_32(isp, &src->na_handle, dst->na_handle);
+	ISP_IOXGET_16(isp, &src->na_nphdl, dst->na_nphdl);
+	ISP_IOXGET_16(isp, &src->na_reserved1, dst->na_reserved1);
+	ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags);
+	ISP_IOXGET_16(isp, &src->na_srr_rxid, dst->na_srr_rxid);
+	ISP_IOXGET_16(isp, &src->na_status, dst->na_status);
+	ISP_IOXGET_8(isp, &src->na_status_subcode, dst->na_status_subcode);
+	ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2);
+	ISP_IOXGET_32(isp, &src->na_rxid, dst->na_rxid);
+	ISP_IOXGET_16(isp, &src->na_srr_reloff_hi, dst->na_srr_reloff_hi);
+	ISP_IOXGET_16(isp, &src->na_srr_reloff_lo, dst->na_srr_reloff_lo);
+	ISP_IOXGET_16(isp, &src->na_srr_iu, dst->na_srr_iu);
+	ISP_IOXGET_16(isp, &src->na_srr_flags, dst->na_srr_flags);
+	for (i = 0; i < 18; i++) {
+		ISP_IOXGET_8(isp, &src->na_reserved3[i], dst->na_reserved3[i]);
+	}
+	ISP_IOXGET_8(isp, &src->na_reserved4, dst->na_reserved4);
+	ISP_IOXGET_8(isp, &src->na_vpindex, dst->na_vpindex);
+	ISP_IOXGET_8(isp, &src->na_srr_reject_vunique,
+	    dst->na_srr_reject_vunique);
+	ISP_IOXGET_8(isp, &src->na_srr_reject_explanation,
+	    dst->na_srr_reject_explanation);
+	ISP_IOXGET_8(isp, &src->na_srr_reject_code, dst->na_srr_reject_code);
+	ISP_IOXGET_8(isp, &src->na_reserved5, dst->na_reserved5);
+	for (i = 0; i < 6; i++) {
+		ISP_IOXGET_8(isp, &src->na_reserved6[i], dst->na_reserved6[i]);
+	}
+	ISP_IOXGET_16(isp, &src->na_oxid, dst->na_oxid);
+}
+
+void
+isp_get_abts(ispsoftc_t *isp, abts_t *src, abts_t *dst)
+{
+	int i;
+
+	isp_get_hdr(isp, &src->abts_header, &dst->abts_header);
+	for (i = 0; i < 6; i++) {
+		ISP_IOXGET_8(isp, &src->abts_reserved0[i],
+		    dst->abts_reserved0[i]);
+	}
+	ISP_IOXGET_16(isp, &src->abts_nphdl, dst->abts_nphdl);
+	ISP_IOXGET_16(isp, &src->abts_reserved1, dst->abts_reserved1);
+	ISP_IOXGET_16(isp, &src->abts_sof, dst->abts_sof);
+	ISP_IOXGET_32(isp, &src->abts_rxid_abts, dst->abts_rxid_abts);
+	ISP_IOXGET_16(isp, &src->abts_did_lo, dst->abts_did_lo);
+	ISP_IOXGET_8(isp, &src->abts_did_hi, dst->abts_did_hi);
+	ISP_IOXGET_8(isp, &src->abts_r_ctl, dst->abts_r_ctl);
+	ISP_IOXGET_16(isp, &src->abts_sid_lo, dst->abts_sid_lo);
+	ISP_IOXGET_8(isp, &src->abts_sid_hi, dst->abts_sid_hi);
+	ISP_IOXGET_8(isp, &src->abts_cs_ctl, dst->abts_cs_ctl);
+	ISP_IOXGET_16(isp, &src->abts_fs_ctl, dst->abts_fs_ctl);
+	ISP_IOXGET_8(isp, &src->abts_f_ctl, dst->abts_f_ctl);
+	ISP_IOXGET_8(isp, &src->abts_type, dst->abts_type);
+	ISP_IOXGET_16(isp, &src->abts_seq_cnt, dst->abts_seq_cnt);
+	ISP_IOXGET_8(isp, &src->abts_df_ctl, dst->abts_df_ctl);
+	ISP_IOXGET_8(isp, &src->abts_seq_id, dst->abts_seq_id);
+	ISP_IOXGET_16(isp, &src->abts_rx_id, dst->abts_rx_id);
+	ISP_IOXGET_16(isp, &src->abts_ox_id, dst->abts_ox_id);
+	ISP_IOXGET_32(isp, &src->abts_param, dst->abts_param);
+	for (i = 0; i < 16; i++) {
+	ISP_IOXGET_8(isp, &src->abts_reserved2[i],
+		    dst->abts_reserved2[i]);
+	}
+	ISP_IOXGET_32(isp, &src->abts_rxid_task, dst->abts_rxid_task);
+}
+
+void
+isp_put_abts_rsp(ispsoftc_t *isp, abts_rsp_t *src, abts_rsp_t *dst)
+{
+	int i;
+
+	isp_put_hdr(isp, &src->abts_rsp_header, &dst->abts_rsp_header);
+	ISP_IOXPUT_32(isp, src->abts_rsp_handle, &dst->abts_rsp_handle);
+	ISP_IOXPUT_16(isp, src->abts_rsp_status, &dst->abts_rsp_status);
+	ISP_IOXPUT_16(isp, src->abts_rsp_nphdl, &dst->abts_rsp_nphdl);
+	ISP_IOXPUT_16(isp, src->abts_rsp_ctl_flags, &dst->abts_rsp_ctl_flags);
+	ISP_IOXPUT_16(isp, src->abts_rsp_sof, &dst->abts_rsp_sof);
+	ISP_IOXPUT_32(isp, src->abts_rsp_rxid_abts, &dst->abts_rsp_rxid_abts);
+	ISP_IOXPUT_16(isp, src->abts_rsp_did_lo, &dst->abts_rsp_did_lo);
+	ISP_IOXPUT_8(isp, src->abts_rsp_did_hi, &dst->abts_rsp_did_hi);
+	ISP_IOXPUT_8(isp, src->abts_rsp_r_ctl, &dst->abts_rsp_r_ctl);
+	ISP_IOXPUT_16(isp, src->abts_rsp_sid_lo, &dst->abts_rsp_sid_lo);
+	ISP_IOXPUT_8(isp, src->abts_rsp_sid_hi, &dst->abts_rsp_sid_hi);
+	ISP_IOXPUT_8(isp, src->abts_rsp_cs_ctl, &dst->abts_rsp_cs_ctl);
+	ISP_IOXPUT_16(isp, src->abts_rsp_f_ctl_lo, &dst->abts_rsp_f_ctl_lo);
+	ISP_IOXPUT_8(isp, src->abts_rsp_f_ctl_hi, &dst->abts_rsp_f_ctl_hi);
+	ISP_IOXPUT_8(isp, src->abts_rsp_type, &dst->abts_rsp_type);
+	ISP_IOXPUT_16(isp, src->abts_rsp_seq_cnt, &dst->abts_rsp_seq_cnt);
+	ISP_IOXPUT_8(isp, src->abts_rsp_df_ctl, &dst->abts_rsp_df_ctl);
+	ISP_IOXPUT_8(isp, src->abts_rsp_seq_id, &dst->abts_rsp_seq_id);
+	ISP_IOXPUT_16(isp, src->abts_rsp_rx_id, &dst->abts_rsp_rx_id);
+	ISP_IOXPUT_16(isp, src->abts_rsp_ox_id, &dst->abts_rsp_ox_id);
+	ISP_IOXPUT_32(isp, src->abts_rsp_param, &dst->abts_rsp_param);
+	if (src->abts_rsp_r_ctl == BA_ACC) {
+		ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.reserved,
+		    &dst->abts_rsp_payload.ba_acc.reserved);
+		ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.last_seq_id,
+		    &dst->abts_rsp_payload.ba_acc.last_seq_id);
+		ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.seq_id_valid,
+		    &dst->abts_rsp_payload.ba_acc.seq_id_valid);
+		ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_rx_id,
+		    &dst->abts_rsp_payload.ba_acc.aborted_rx_id);
+		ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_ox_id,
+		    &dst->abts_rsp_payload.ba_acc.aborted_ox_id);
+		ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.high_seq_cnt,
+		    &dst->abts_rsp_payload.ba_acc.high_seq_cnt);
+		ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.low_seq_cnt,
+		    &dst->abts_rsp_payload.ba_acc.low_seq_cnt);
+		for (i = 0; i < 4; i++) {
+			ISP_IOXPUT_16(isp,
+			    src->abts_rsp_payload.ba_acc.reserved2[i],
+			    &dst->abts_rsp_payload.ba_acc.reserved2[i]);
+		}
+	} else if (src->abts_rsp_r_ctl == BA_RJT) {
+		ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.vendor_unique,
+		    &dst->abts_rsp_payload.ba_rjt.vendor_unique);
+		ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.explanation,
+		    &dst->abts_rsp_payload.ba_rjt.explanation);
+		ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reason,
+		    &dst->abts_rsp_payload.ba_rjt.reason);
+		ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reserved,
+		    &dst->abts_rsp_payload.ba_rjt.reserved);
+		for (i = 0; i < 12; i++) {
+			ISP_IOXPUT_16(isp,
+			    src->abts_rsp_payload.ba_rjt.reserved2[i],
+			    &dst->abts_rsp_payload.ba_rjt.reserved2[i]);
+		}
+	} else {
+		for (i = 0; i < 16; i++) {
+			ISP_IOXPUT_8(isp, src->abts_rsp_payload.reserved[i],
+			    &dst->abts_rsp_payload.reserved[i]);
+		}
+	}
+	ISP_IOXPUT_32(isp, src->abts_rsp_rxid_task, &dst->abts_rsp_rxid_task);
+}
+
+void
+isp_get_abts_rsp(ispsoftc_t *isp, abts_rsp_t *src, abts_rsp_t *dst)
+{
+	int i;
+
+	isp_get_hdr(isp, &src->abts_rsp_header, &dst->abts_rsp_header);
+	ISP_IOXGET_32(isp, &src->abts_rsp_handle, dst->abts_rsp_handle);
+	ISP_IOXGET_16(isp, &src->abts_rsp_status, dst->abts_rsp_status);
+	ISP_IOXGET_16(isp, &src->abts_rsp_nphdl, dst->abts_rsp_nphdl);
+	ISP_IOXGET_16(isp, &src->abts_rsp_ctl_flags, dst->abts_rsp_ctl_flags);
+	ISP_IOXGET_16(isp, &src->abts_rsp_sof, dst->abts_rsp_sof);
+	ISP_IOXGET_32(isp, &src->abts_rsp_rxid_abts, dst->abts_rsp_rxid_abts);
+	ISP_IOXGET_16(isp, &src->abts_rsp_did_lo, dst->abts_rsp_did_lo);
+	ISP_IOXGET_8(isp, &src->abts_rsp_did_hi, dst->abts_rsp_did_hi);
+	ISP_IOXGET_8(isp, &src->abts_rsp_r_ctl, dst->abts_rsp_r_ctl);
+	ISP_IOXGET_16(isp, &src->abts_rsp_sid_lo, dst->abts_rsp_sid_lo);
+	ISP_IOXGET_8(isp, &src->abts_rsp_sid_hi, dst->abts_rsp_sid_hi);
+	ISP_IOXGET_8(isp, &src->abts_rsp_cs_ctl, dst->abts_rsp_cs_ctl);
+	ISP_IOXGET_16(isp, &src->abts_rsp_f_ctl_lo, dst->abts_rsp_f_ctl_lo);
+	ISP_IOXGET_8(isp, &src->abts_rsp_f_ctl_hi, dst->abts_rsp_f_ctl_hi);
+	ISP_IOXGET_8(isp, &src->abts_rsp_type, dst->abts_rsp_type);
+	ISP_IOXGET_16(isp, &src->abts_rsp_seq_cnt, dst->abts_rsp_seq_cnt);
+	ISP_IOXGET_8(isp, &src->abts_rsp_df_ctl, dst->abts_rsp_df_ctl);
+	ISP_IOXGET_8(isp, &src->abts_rsp_seq_id, dst->abts_rsp_seq_id);
+	ISP_IOXGET_16(isp, &src->abts_rsp_rx_id, dst->abts_rsp_rx_id);
+	ISP_IOXGET_16(isp, &src->abts_rsp_ox_id, dst->abts_rsp_ox_id);
+	ISP_IOXGET_32(isp, &src->abts_rsp_param, dst->abts_rsp_param);
+	for (i = 0; i < 8; i++) {
+		ISP_IOXGET_8(isp, &src->abts_rsp_payload.rsp.reserved[i],
+		    dst->abts_rsp_payload.rsp.reserved[i]);
+	}
+	ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode1,
+	    dst->abts_rsp_payload.rsp.subcode1);
+	ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode2,
+	    dst->abts_rsp_payload.rsp.subcode2);
+	ISP_IOXGET_32(isp, &src->abts_rsp_rxid_task, dst->abts_rsp_rxid_task);
+}
 #endif	/* ISP_TARGET_MODE */
+/*
+ * vim:ts=8:sw=8
+ */
diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h
index 4faa320e3bd6..944774131211 100644
--- a/sys/dev/isp/isp_library.h
+++ b/sys/dev/isp/isp_library.h
@@ -30,22 +30,26 @@
 #ifndef	_ISP_LIBRARY_H
 #define	_ISP_LIBRARY_H
 
-extern int isp_save_xs(ispsoftc_t *, XS_T *, uint16_t *);
-extern XS_T *isp_find_xs(ispsoftc_t *, uint16_t);
-extern uint16_t isp_find_handle(ispsoftc_t *, XS_T *);
-extern int isp_handle_index(uint16_t);
-extern uint16_t isp_index_handle(int);
-extern void isp_destroy_handle(ispsoftc_t *, uint16_t);
-extern int isp_getrqentry(ispsoftc_t *, uint16_t *, uint16_t *, void **);
+extern int isp_save_xs(ispsoftc_t *, XS_T *, uint32_t *);
+extern XS_T *isp_find_xs(ispsoftc_t *, uint32_t);
+extern uint32_t isp_find_handle(ispsoftc_t *, XS_T *);
+extern uint32_t isp_handle_index(uint32_t);
+extern void isp_destroy_handle(ispsoftc_t *, uint32_t);
+extern int isp_getrqentry(ispsoftc_t *, uint32_t *, uint32_t *, void **);
 extern void isp_print_qentry (ispsoftc_t *, char *, int, void *);
 extern void isp_print_bytes(ispsoftc_t *, char *, int, void *);
 extern int isp_fc_runstate(ispsoftc_t *, int);
-extern void isp_copy_out_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
-extern void isp_copy_in_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
+extern void isp_shutdown(ispsoftc_t *);
+extern void isp_put_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
+extern void isp_get_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
 extern int isp_get_response_type(ispsoftc_t *, isphdr_t *);
 extern void
 isp_put_request(ispsoftc_t *, ispreq_t *, ispreq_t *);
 extern void
+isp_put_marker(ispsoftc_t *, isp_marker_t *, isp_marker_t *);
+extern void
+isp_put_marker_24xx(ispsoftc_t *, isp_marker_24xx_t *, isp_marker_24xx_t *);
+extern void
 isp_put_request_t2(ispsoftc_t *, ispreqt2_t *, ispreqt2_t *);
 extern void
 isp_put_request_t2e(ispsoftc_t *, ispreqt2e_t *, ispreqt2e_t *);
@@ -56,21 +60,37 @@ isp_put_request_t3e(ispsoftc_t *, ispreqt3e_t *, ispreqt3e_t *);
 extern void
 isp_put_extended_request(ispsoftc_t *, ispextreq_t *, ispextreq_t *);
 extern void
+isp_put_request_t7(ispsoftc_t *, ispreqt7_t *, ispreqt7_t *);
+extern void
+isp_put_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
+extern void
 isp_put_cont_req(ispsoftc_t *, ispcontreq_t *, ispcontreq_t *);
 extern void
 isp_put_cont64_req(ispsoftc_t *, ispcontreq64_t *, ispcontreq64_t *);
 extern void
 isp_get_response(ispsoftc_t *, ispstatusreq_t *, ispstatusreq_t *);
-extern void
-isp_get_response_x(ispsoftc_t *, ispstatus_cont_t *, ispstatus_cont_t *);
+extern void isp_get_24xx_response(ispsoftc_t *, isp24xx_statusreq_t *,
+    isp24xx_statusreq_t *);
+void
+isp_get_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
 extern void
 isp_get_rio2(ispsoftc_t *, isp_rio2_t *, isp_rio2_t *);
 extern void
 isp_put_icb(ispsoftc_t *, isp_icb_t *, isp_icb_t *);
 extern void
-isp_get_pdb(ispsoftc_t *, isp_pdb_t *, isp_pdb_t *);
+isp_put_icb_2400(ispsoftc_t *, isp_icb_2400_t *, isp_icb_2400_t *);
 extern void
-isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
+isp_get_pdb_21xx(ispsoftc_t *, isp_pdb_21xx_t *, isp_pdb_21xx_t *);
+extern void
+isp_get_pdb_24xx(ispsoftc_t *, isp_pdb_24xx_t *, isp_pdb_24xx_t *);
+extern void
+isp_get_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
+extern void
+isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
+extern void
+isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
+extern void
+isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
 extern void
 isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *);
 extern void
@@ -93,6 +113,17 @@ isp_get_gff_id_response(ispsoftc_t *, sns_gff_id_rsp_t *,
 extern void
 isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *,
     sns_ga_nxt_rsp_t *);
+extern void
+isp_get_els(ispsoftc_t *, els_t *, els_t *);
+extern void
+isp_put_els(ispsoftc_t *, els_t *, els_t *);
+extern void
+isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
+extern void
+isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *);
+extern void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *);
+extern void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
+extern void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
 
 #ifdef	ISP_TARGET_MODE
 #if	defined(__NetBSD__) || defined(__OpenBSD__)
@@ -103,10 +134,12 @@ isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *,
 #include "isp_target.h"
 #endif
 
-extern int isp_save_xs_tgt(ispsoftc_t *, void *, uint16_t *);
-extern void *isp_find_xs_tgt(ispsoftc_t *, uint16_t);
-extern uint16_t isp_find_tgt_handle(ispsoftc_t *, void *);
-extern void isp_destroy_tgt_handle(ispsoftc_t *, uint16_t);
+#define	IS_TARGET_HANDLE(x)     ((x) & 0x8000)
+
+extern int isp_save_xs_tgt(ispsoftc_t *, void *, uint32_t *);
+extern void *isp_find_xs_tgt(ispsoftc_t *, uint32_t);
+extern uint32_t isp_find_tgt_handle(ispsoftc_t *, void *);
+extern void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t);
 
 extern void
 isp_put_atio(ispsoftc_t *, at_entry_t *, at_entry_t *);
@@ -121,6 +154,8 @@ isp_get_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *);
 extern void
 isp_get_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *);
 extern void
+isp_get_atio7(ispsoftc_t *isp, at7_entry_t *, at7_entry_t *);
+extern void
 isp_put_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
 extern void
 isp_get_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
@@ -129,10 +164,14 @@ isp_put_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
 extern void
 isp_put_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
 extern void
+isp_put_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
+extern void
 isp_get_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
 extern void
 isp_get_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
 extern void
+isp_get_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
+extern void
 isp_put_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
 extern void
 isp_get_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
@@ -145,20 +184,36 @@ isp_put_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
 extern void
 isp_put_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
 extern void
+isp_put_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
+extern void
 isp_get_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
 extern void
 isp_get_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
 extern void
+isp_get_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
+extern void
 isp_put_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
 extern void
 isp_get_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
 extern void
+isp_put_notify_24xx_ack(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *);
+extern void
 isp_put_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
 extern void
 isp_put_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
+extern void isp_put_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *,
+    na_fcentry_24xx_t *);
 extern void
 isp_get_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
 extern void
 isp_get_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
+extern void isp_get_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *,
+    na_fcentry_24xx_t *);
+extern void
+isp_get_abts(ispsoftc_t *, abts_t *, abts_t *);
+extern void
+isp_put_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
+extern void
+isp_get_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
 #endif	/* ISP_TARGET_MODE */
 #endif	/* _ISP_LIBRARY_H */
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 6bb695627d2d..db17cc73da86 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -62,19 +62,23 @@ __FBSDID("$FreeBSD$");
 #define	BUS_PROBE_DEFAULT	0
 #endif
 
-static uint16_t isp_pci_rd_reg(ispsoftc_t *, int);
-static void isp_pci_wr_reg(ispsoftc_t *, int, uint16_t);
-static uint16_t isp_pci_rd_reg_1080(ispsoftc_t *, int);
-static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint16_t);
+static uint32_t isp_pci_rd_reg(ispsoftc_t *, int);
+static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t);
+static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int);
+static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t);
+static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int);
+static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t);
 static int
-isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
+isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
 static int
-isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
+isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
+static int
+isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
 static int isp_pci_mbxdma(ispsoftc_t *);
 static int
-isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t);
+isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
 static void
-isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint16_t);
+isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint32_t);
 
 
 static void isp_pci_reset1(ispsoftc_t *);
@@ -158,6 +162,18 @@ static struct ispmdvec mdvec_2300 = {
 	isp_pci_dumpregs
 };
 
+static struct ispmdvec mdvec_2400 = {
+	isp_pci_rd_isr_2400,
+	isp_pci_rd_reg_2400,
+	isp_pci_wr_reg_2400,
+	isp_pci_mbxdma,
+	isp_pci_dmasetup,
+	isp_pci_dmateardown,
+	NULL,
+	isp_pci_reset1,
+	NULL
+};
+
 #ifndef	PCIM_CMD_INVEN
 #define	PCIM_CMD_INVEN			0x10
 #endif
@@ -306,6 +322,7 @@ static struct ispmdvec mdvec_2300 = {
 
 static int isp_pci_probe (device_t);
 static int isp_pci_attach (device_t);
+static int isp_pci_detach (device_t);
 
 
 struct isp_pcisoftc {
@@ -320,10 +337,12 @@ struct isp_pcisoftc {
 	bus_dmamap_t			*dmaps;
 };
 
+
 static device_method_t isp_pci_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		isp_pci_probe),
 	DEVMETHOD(device_attach,	isp_pci_attach),
+	DEVMETHOD(device_detach,	isp_pci_detach),
 	{ 0, 0 }
 };
 static void isp_pci_intr(void *);
@@ -380,11 +399,9 @@ isp_pci_probe(device_t dev)
 	case PCI_QLOGIC_ISP2322:
 		device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter");
 		break;
-#if	0
 	case PCI_QLOGIC_ISP2422:
 		device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter");
 		break;
-#endif
 	case PCI_QLOGIC_ISP6312:
 		device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter");
 		break;
@@ -487,6 +504,23 @@ isp_get_options(device_t dev, ispsoftc_t *isp)
 		isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
 	}
 
+	bitmap = 0;
+	(void) getenv_int("isp_fabric_hysteresis", &bitmap);
+	if (bitmap >= 0 && bitmap < 256) {
+		isp->isp_osinfo.hysteresis = bitmap;
+	} else {
+		isp->isp_osinfo.hysteresis = isp_fabric_hysteresis;
+	}
+
+	bitmap = 0;
+	(void) getenv_int("isp_loop_down_limit", &bitmap);
+	if (bitmap >= 0 && bitmap < 0xffff) {
+		isp->isp_osinfo.loop_down_limit = bitmap;
+	} else {
+		isp->isp_osinfo.loop_down_limit = isp_loop_down_limit;
+	}
+
+
 #ifdef	ISP_FW_CRASH_DUMP
 	bitmap = 0;
 	if (getenv_int("isp_fw_dump_enable", &bitmap)) {
@@ -690,6 +724,24 @@ isp_get_options(device_t dev, ispsoftc_t *isp)
 		isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
 	}
 
+	tval = 0;
+	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
+	    "hysteresis", &tval);
+	if (tval >= 0 && tval < 256) {
+		isp->isp_osinfo.hysteresis = tval;
+	} else {
+		isp->isp_osinfo.hysteresis = isp_fabric_hysteresis;
+	}
+
+	tval = 0;
+	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
+	    "loop_down_limit", &tval);
+	if (tval >= 0 && tval < 0xffff) {
+		isp->isp_osinfo.loop_down_limit = tval;
+	} else {
+		isp->isp_osinfo.loop_down_limit = isp_loop_down_limit;
+	}
+
 }
 
 static void
@@ -886,11 +938,11 @@ isp_pci_attach(device_t dev)
 		    PCI_MBOX_REGS2300_OFF;
 	}
 	if (pci_get_devid(dev) == PCI_QLOGIC_ISP2422) {
-		mdvp = &mdvec_2300;
-		basetype = ISP_HA_FC_2422;
+		mdvp = &mdvec_2400;
+		basetype = ISP_HA_FC_2400;
 		psize = sizeof (fcparam);
 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
-		    PCI_MBOX_REGS2300_OFF;
+		    PCI_MBOX_REGS2400_OFF;
 	}
 	isp = &pcs->pci_isp;
 	isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -932,6 +984,9 @@ isp_pci_attach(device_t dev)
 		case PCI_PRODUCT_QLOGIC_ISP6322:
 			did = 0x2322;
 			break;
+		case PCI_PRODUCT_QLOGIC_ISP2422:
+			did = 0x2400;
+			break;
 		default:
 			break;
 		}
@@ -976,18 +1031,42 @@ isp_pci_attach(device_t dev)
 		cmd &= ~PCIM_CMD_INVEN;
 	}
 
-	if (IS_23XX(isp)) {
-		/*
-		 * Can't tell if ROM will hang on 'ABOUT FIRMWARE' command.
-		 */
-		isp->isp_touched = 1;
-		
-	}
-
 	if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) {
 		cmd &= ~PCIM_CMD_INTX_DISABLE;
 	}
 
+	if (IS_24XX(isp)) {
+		int reg;
+
+		cmd &= ~PCIM_CMD_INTX_DISABLE;
+
+		/*
+		 * Is this a PCI-X card? If so, set max read byte count.
+		 */
+		if (pci_find_extcap(dev, PCIY_PCIX, &reg) == 0) {
+			uint16_t pxcmd;
+			reg += 2;
+
+			pxcmd = pci_read_config(dev, reg, 2);
+			pxcmd &= ~0xc;
+			pxcmd |= 0x8;
+			pci_write_config(dev, reg, 2, pxcmd);
+		}
+
+		/*
+		 * Is this a PCI Express card? If so, set max read byte count.
+		 */
+		if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
+			uint16_t pectl;
+
+			reg += 0x8;
+			pectl = pci_read_config(dev, reg, 2);
+			pectl &= ~0x7000;
+			pectl |= 0x4000;
+			pci_write_config(dev, reg, 2, pectl);
+		}
+	}
+
 	pci_write_config(dev, PCIR_COMMAND, cmd, 2);
 
 	/*
@@ -1039,10 +1118,17 @@ isp_pci_attach(device_t dev)
 	/*
 	 * Last minute checks...
 	 */
-	if (IS_23XX(isp)) {
+	if (IS_23XX(isp) || IS_24XX(isp)) {
 		isp->isp_port = pci_get_function(dev);
 	}
 
+	if (IS_23XX(isp)) {
+		/*
+		 * Can't tell if ROM will hang on 'ABOUT FIRMWARE' command.
+		 */
+		isp->isp_touched = 1;
+	}
+
 	/*
 	 * Make sure we're in reset state.
 	 */
@@ -1069,6 +1155,7 @@ isp_pci_attach(device_t dev)
 	 * XXXX: (or decrease the reference count to it).
 	 */
 	ISP_UNLOCK(isp);
+
 	return (0);
 
 bad:
@@ -1110,21 +1197,34 @@ isp_pci_attach(device_t dev)
 	return (ENXIO);
 }
 
+static int
+isp_pci_detach(device_t dev)
+{
+	struct isp_pcisoftc *pcs;
+	ispsoftc_t *isp;
+
+	pcs = device_get_softc(dev);
+	if (pcs == NULL) {
+		return (ENXIO);
+	}
+	isp = (ispsoftc_t *) pcs;
+	ISP_DISABLE_INTS(isp);
+	return (0);
+}
+
 static void
 isp_pci_intr(void *arg)
 {
 	ispsoftc_t *isp = arg;
-	uint16_t isr, sema, mbox;
+	uint32_t isr;
+	uint16_t sema, mbox;
 
 	ISP_LOCK(isp);
 	isp->isp_intcnt++;
 	if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
 		isp->isp_intbogus++;
 	} else {
-		int iok = isp->isp_osinfo.intsok;
-		isp->isp_osinfo.intsok = 0;
 		isp_intr(isp, isr, sema, mbox);
-		isp->isp_osinfo.intsok = iok;
 	}
 	ISP_UNLOCK(isp);
 }
@@ -1138,13 +1238,17 @@ isp_pci_intr(void *arg)
 	bus_space_read_2(pcs->pci_st, pcs->pci_sh, off)
 #define	BXW2(pcs, off, v)	\
 	bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v)
+#define	BXR4(pcs, off)		\
+	bus_space_read_4(pcs->pci_st, pcs->pci_sh, off)
+#define	BXW4(pcs, off, v)	\
+	bus_space_write_4(pcs->pci_st, pcs->pci_sh, off, v)
 
 
 static __inline int
 isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
 {
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
-	uint16_t val0, val1;
+	uint32_t val0, val1;
 	int i = 0;
 
 	do {
@@ -1159,7 +1263,7 @@ isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
 }
 
 static int
-isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
+isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp,
     uint16_t *semap, uint16_t *mbp)
 {
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
@@ -1196,19 +1300,18 @@ isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
 }
 
 static int
-isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp,
+isp_pci_rd_isr_2300(ispsoftc_t *isp, uint32_t *isrp,
     uint16_t *semap, uint16_t *mbox0p)
 {
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
-	uint16_t hccr;
+	uint32_t hccr;
 	uint32_t r2hisr;
 
 	if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) {
 		*isrp = 0;
 		return (0);
 	}
-	r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh,
-	    IspVirt2Off(pcs, BIU_R2HSTSLO));
+	r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU_R2HSTSLO));
 	isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
 	if ((r2hisr & BIU_R2HST_INTR) == 0) {
 		*isrp = 0;
@@ -1252,17 +1355,54 @@ isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp,
 			    "RISC paused at interrupt (%x->%x\n", hccr,
 			    ISP_READ(isp, HCCR));
 		} else {
-			isp_prt(isp, ISP_LOGERR, "unknown interrerupt 0x%x\n",
+			isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n",
 			    r2hisr);
 		}
 		return (0);
 	}
 }
 
-static uint16_t
+static int
+isp_pci_rd_isr_2400(ispsoftc_t *isp, uint32_t *isrp,
+    uint16_t *semap, uint16_t *mbox0p)
+{
+	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
+	uint32_t r2hisr;
+
+	r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU2400_R2HSTSLO));
+	isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
+	if ((r2hisr & BIU2400_R2HST_INTR) == 0) {
+		*isrp = 0;
+		return (0);
+	}
+	switch (r2hisr & BIU2400_R2HST_ISTAT_MASK) {
+	case ISP2400R2HST_ROM_MBX_OK:
+	case ISP2400R2HST_ROM_MBX_FAIL:
+	case ISP2400R2HST_MBX_OK:
+	case ISP2400R2HST_MBX_FAIL:
+	case ISP2400R2HST_ASYNC_EVENT:
+		*isrp = r2hisr & 0xffff;
+		*mbox0p = (r2hisr >> 16);
+		*semap = 1;
+		return (1);
+	case ISP2400R2HST_RSPQ_UPDATE:
+	case ISP2400R2HST_ATIO_RSPQ_UPDATE:
+	case ISP2400R2HST_ATIO_RQST_UPDATE:
+		*isrp = r2hisr & 0xffff;
+		*mbox0p = 0;
+		*semap = 0;
+		return (1);
+	default:
+		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
+		isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr);
+		return (0);
+	}
+}
+
+static uint32_t
 isp_pci_rd_reg(ispsoftc_t *isp, int regoff)
 {
-	uint16_t rv;
+	uint32_t rv;
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
 	int oldconf = 0;
 
@@ -1282,10 +1422,11 @@ isp_pci_rd_reg(ispsoftc_t *isp, int regoff)
 }
 
 static void
-isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val)
+isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
 {
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
 	int oldconf = 0;
+	volatile int junk;
 
 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
 		/*
@@ -1294,22 +1435,25 @@ isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val)
 		oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
 		BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
 		    oldconf | BIU_PCI_CONF1_SXP);
+		junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
 	}
 	BXW2(pcs, IspVirt2Off(isp, regoff), val);
+	junk = BXR2(pcs, IspVirt2Off(isp, regoff));
 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
 		BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
+		junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
 	}
 }
 
-static uint16_t
+static uint32_t
 isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff)
 {
-	uint16_t rv, oc = 0;
+	uint32_t rv, oc = 0;
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
 
 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
 	    (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
-		uint16_t tc;
+		uint32_t tc;
 		/*
 		 * We will assume that someone has paused the RISC processor.
 		 */
@@ -1333,14 +1477,15 @@ isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff)
 }
 
 static void
-isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint16_t val)
+isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val)
 {
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
 	int oc = 0;
+	volatile int junk;
 
 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
 	    (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
-		uint16_t tc;
+		uint32_t tc;
 		/*
 		 * We will assume that someone has paused the RISC processor.
 		 */
@@ -1351,14 +1496,137 @@ isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint16_t val)
 		else
 			tc |= BIU_PCI1080_CONF1_SXP0;
 		BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
+		junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
 	} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
 		oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
 		BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 
 		    oc | BIU_PCI1080_CONF1_DMA);
+		junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
 	}
 	BXW2(pcs, IspVirt2Off(isp, regoff), val);
+	junk = BXR2(pcs, IspVirt2Off(isp, regoff));
 	if (oc) {
 		BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
+		junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
+	}
+}
+
+static uint32_t
+isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff)
+{
+	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
+	uint32_t rv;
+	int block = regoff & _BLK_REG_MASK;
+
+	switch (block) {
+	case BIU_BLOCK:
+		break;
+	case MBOX_BLOCK:
+		return (BXR2(pcs, IspVirt2Off(pcs, regoff)));
+	case SXP_BLOCK:
+		isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff);
+		return (0xffffffff);
+	case RISC_BLOCK:
+		isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff);
+		return (0xffffffff);
+	case DMA_BLOCK:
+		isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff);
+		return (0xffffffff);
+	default:
+		isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff);
+		return (0xffffffff);
+	}
+
+
+	switch (regoff) {
+	case BIU2400_FLASH_ADDR:
+	case BIU2400_FLASH_DATA:
+	case BIU2400_ICR:
+	case BIU2400_ISR:
+	case BIU2400_CSR:
+	case BIU2400_REQINP:
+	case BIU2400_REQOUTP:
+	case BIU2400_RSPINP:
+	case BIU2400_RSPOUTP:
+	case BIU2400_PRI_RQINP:
+	case BIU2400_PRI_RSPINP:
+	case BIU2400_ATIO_RSPINP:
+	case BIU2400_ATIO_REQINP:
+	case BIU2400_HCCR:
+	case BIU2400_GPIOD:
+	case BIU2400_GPIOE:
+	case BIU2400_HSEMA:
+		rv = BXR4(pcs, IspVirt2Off(pcs, regoff));
+		break;
+	case BIU2400_R2HSTSLO:
+		rv = BXR4(pcs, IspVirt2Off(pcs, regoff));
+		break;
+	case BIU2400_R2HSTSHI:
+		rv = BXR4(pcs, IspVirt2Off(pcs, regoff)) >> 16;
+		break;
+	default:
+		isp_prt(isp, ISP_LOGERR,
+		    "isp_pci_rd_reg_2400: unknown offset %x", regoff);
+		rv = 0xffffffff;
+		break;
+	}
+	return (rv);
+}
+
+static void
+isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
+{
+	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
+	int block = regoff & _BLK_REG_MASK;
+	volatile int junk;
+
+	switch (block) {
+	case BIU_BLOCK:
+		break;
+	case MBOX_BLOCK:
+		BXW2(pcs, IspVirt2Off(pcs, regoff), val);
+		junk = BXR2(pcs, IspVirt2Off(pcs, regoff));
+		return;
+	case SXP_BLOCK:
+		isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff);
+		return;
+	case RISC_BLOCK:
+		isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff);
+		return;
+	case DMA_BLOCK:
+		isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff);
+		return;
+	default:
+		isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x",
+		    regoff);
+		break;
+	}
+
+	switch (regoff) {
+	case BIU2400_FLASH_ADDR:
+	case BIU2400_FLASH_DATA:
+	case BIU2400_ICR:
+	case BIU2400_ISR:
+	case BIU2400_CSR:
+	case BIU2400_REQINP:
+	case BIU2400_REQOUTP:
+	case BIU2400_RSPINP:
+	case BIU2400_RSPOUTP:
+	case BIU2400_PRI_RQINP:
+	case BIU2400_PRI_RSPINP:
+	case BIU2400_ATIO_RSPINP:
+	case BIU2400_ATIO_REQINP:
+	case BIU2400_HCCR:
+	case BIU2400_GPIOD:
+	case BIU2400_GPIOE:
+	case BIU2400_HSEMA:
+		BXW4(pcs, IspVirt2Off(pcs, regoff), val);
+		junk = BXR4(pcs, IspVirt2Off(pcs, regoff));
+		break;
+	default:
+		isp_prt(isp, ISP_LOGERR,
+		    "isp_pci_wr_reg_2400: bad offset 0x%x", regoff);
+		break;
 	}
 }
 
@@ -1430,6 +1698,11 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 		return (0);
 	}
 
+	if (isp->isp_maxcmds == 0) {
+		isp_prt(isp, ISP_LOGERR, "maxcmds not set");
+		return (1);
+	}
+
 	hlim = BUS_SPACE_MAXADDR;
 	if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) {
 		slim = (bus_size_t) (1ULL << 32);
@@ -1576,8 +1849,8 @@ typedef struct {
 	ispsoftc_t *isp;
 	void *cmd_token;
 	void *rq;
-	uint16_t *nxtip;
-	uint16_t optr;
+	uint32_t *nxtip;
+	uint32_t optr;
 	int error;
 } mush_t;
 
@@ -1615,7 +1888,7 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	bus_dmamap_t *dp;
 	ct_entry_t *cto, *qe;
 	uint8_t scsi_status;
-	uint16_t curi, nxti, handle;
+	uint32_t curi, nxti, handle;
 	uint32_t sflags;
 	int32_t resid;
 	int nth_ctio, nctios, send_status;
@@ -1855,7 +2128,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	struct ccb_scsiio *csio;
 	ispsoftc_t *isp;
 	ct2_entry_t *cto, *qe;
-	uint16_t curi, nxti;
+	uint32_t curi, nxti;
 	ispds_t *ds;
 	ispds64_t *ds64;
 	int segcnt, seglim;
@@ -1894,7 +2167,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 		    "0x%x res %d", cto->ct_rxid, csio->ccb_h.target_lun,
 		    cto->ct_iid, cto->ct_flags, cto->ct_status,
 		    cto->rsp.m1.ct_scsi_status, cto->ct_resid);
-		if (IS_2KLOGIN(isp)) {
+		if (FCPARAM(isp)->isp_2klogin) {
 			isp_put_ctio2e(isp,
 			    (ct2e_entry_t *)cto, (ct2e_entry_t *)qe);
 		} else {
@@ -1933,12 +2206,12 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	if (segcnt != nseg) {
 		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3;
 		seglim = ISP_RQDSEG_T3;
-		ds64 = &cto->rsp.m0.ct_dataseg64[0];
+		ds64 = &cto->rsp.m0.u.ct_dataseg64[0];
 		ds = NULL;
 	} else {
 		seglim = ISP_RQDSEG_T2;
 		ds64 = NULL;
-		ds = &cto->rsp.m0.ct_dataseg[0];
+		ds = &cto->rsp.m0.u.ct_dataseg[0];
 	}
 	cto->ct_seg_count = 0;
 
@@ -1973,7 +2246,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	}
 
 	while (segcnt < nseg) {
-		uint16_t curip;
+		uint32_t curip;
 		int seg;
 		ispcontreq_t local, *crq = &local, *qep;
 
@@ -2044,18 +2317,127 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	    cto->ct_rxid, csio->ccb_h.target_lun, (int) cto->ct_iid,
 	    cto->ct_flags, cto->ct_status, cto->rsp.m1.ct_scsi_status,
 	    cto->ct_resid);
-	if (IS_2KLOGIN(isp))
+	if (FCPARAM(isp)->isp_2klogin) {
 		isp_put_ctio2e(isp, (ct2e_entry_t *)cto, (ct2e_entry_t *)qe);
-	else
+	} else {
 		isp_put_ctio2(isp, cto, qe);
+	}
 	ISP_TDQE(isp, "last dma2_tgt_fc", curi, qe);
 	*mp->nxtip = nxti;
 }
 #endif
 
+static void dma_2400(void *, bus_dma_segment_t *, int, int);
 static void dma2_a64(void *, bus_dma_segment_t *, int, int);
 static void dma2(void *, bus_dma_segment_t *, int, int);
 
+static void
+dma_2400(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
+{
+	mush_t *mp;
+	ispsoftc_t *isp;
+	struct ccb_scsiio *csio;
+	struct isp_pcisoftc *pcs;
+	bus_dmamap_t *dp;
+	bus_dma_segment_t *eseg;
+	ispreqt7_t *rq;
+	int seglim, datalen;
+	uint32_t nxti;
+
+	mp = (mush_t *) arg;
+	if (error) {
+		mp->error = error;
+		return;
+	}
+
+	if (nseg < 1) {
+		isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
+		mp->error = EFAULT;
+		return;
+	}
+
+	csio = mp->cmd_token;
+	isp = mp->isp;
+	rq = mp->rq;
+	pcs = (struct isp_pcisoftc *)mp->isp;
+	dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
+	nxti = *mp->nxtip;
+
+	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+	} else {
+		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+	}
+	datalen = XS_XFRLEN(csio);
+
+	/*
+	 * We're passed an initial partially filled in entry that
+	 * has most fields filled in except for data transfer
+	 * related values.
+	 *
+	 * Our job is to fill in the initial request queue entry and
+	 * then to start allocating and filling in continuation entries
+	 * until we've covered the entire transfer.
+	 */
+
+	rq->req_header.rqs_entry_type = RQSTYPE_T7RQS;
+	rq->req_dl = datalen;
+	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+		rq->req_alen_datadir = 0x2;
+	} else {
+		rq->req_alen_datadir = 0x1;
+	}
+
+	eseg = dm_segs + nseg;
+
+	rq->req_dataseg.ds_base = DMA_LO32(dm_segs->ds_addr);
+	rq->req_dataseg.ds_basehi = DMA_HI32(dm_segs->ds_addr);
+	rq->req_dataseg.ds_count = dm_segs->ds_len;
+
+	datalen -= dm_segs->ds_len;
+
+	dm_segs++;
+	rq->req_seg_count++;
+
+	while (datalen > 0 && dm_segs != eseg) {
+		uint32_t onxti;
+		ispcontreq64_t local, *crq = &local, *cqe;
+
+		cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
+		onxti = nxti;
+		nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
+		if (nxti == mp->optr) {
+			isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
+			mp->error = MUSHERR_NOQENTRIES;
+			return;
+		}
+		rq->req_header.rqs_entry_count++;
+		MEMZERO((void *)crq, sizeof (*crq));
+		crq->req_header.rqs_entry_count = 1;
+		crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
+
+		seglim = 0;
+		while (datalen > 0 && seglim < ISP_CDSEG64 && dm_segs != eseg) {
+			crq->req_dataseg[seglim].ds_base =
+			    DMA_LO32(dm_segs->ds_addr);
+			crq->req_dataseg[seglim].ds_basehi =
+			    DMA_HI32(dm_segs->ds_addr);
+			crq->req_dataseg[seglim].ds_count =
+			    dm_segs->ds_len;
+			rq->req_seg_count++;
+			dm_segs++;
+			seglim++;
+			datalen -= dm_segs->ds_len;
+		}
+		if (isp->isp_dblev & ISP_LOGDEBUG1) {
+			isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
+		}
+		isp_put_cont64_req(isp, crq, cqe);
+		MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
+	}
+	*mp->nxtip = nxti;
+}
+
 static void
 dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 {
@@ -2067,7 +2449,7 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	bus_dma_segment_t *eseg;
 	ispreq64_t *rq;
 	int seglim, datalen;
-	uint16_t nxti;
+	uint32_t nxti;
 
 	mp = (mush_t *) arg;
 	if (error) {
@@ -2152,7 +2534,7 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	}
 
 	while (datalen > 0 && dm_segs != eseg) {
-		uint16_t onxti;
+		uint32_t onxti;
 		ispcontreq64_t local, *crq = &local, *cqe;
 
 		cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
@@ -2181,6 +2563,9 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 			seglim++;
 			datalen -= dm_segs->ds_len;
 		}
+		if (isp->isp_dblev & ISP_LOGDEBUG1) {
+			isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
+		}
 		isp_put_cont64_req(isp, crq, cqe);
 		MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
 	}
@@ -2198,7 +2583,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	bus_dma_segment_t *eseg;
 	ispreq_t *rq;
 	int seglim, datalen;
-	uint16_t nxti;
+	uint32_t nxti;
 
 	mp = (mush_t *) arg;
 	if (error) {
@@ -2278,7 +2663,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 	}
 
 	while (datalen > 0 && dm_segs != eseg) {
-		uint16_t onxti;
+		uint32_t onxti;
 		ispcontreq_t local, *crq = &local, *cqe;
 
 		cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
@@ -2305,6 +2690,9 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 			seglim++;
 			datalen -= dm_segs->ds_len;
 		}
+		if (isp->isp_dblev & ISP_LOGDEBUG1) {
+			isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
+		}
 		isp_put_cont_req(isp, crq, cqe);
 		MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
 	}
@@ -2316,7 +2704,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
  */
 static int
 isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
-	uint16_t *nxtip, uint16_t optr)
+	uint32_t *nxtip, uint32_t optr)
 {
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
 	ispreq_t *qep;
@@ -2348,7 +2736,9 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
 		}
 	} else
 #endif
-	if (sizeof (bus_addr_t) > 4) {
+	if (IS_24XX(isp)) {
+		eptr = dma_2400;
+	} else if (sizeof (bus_addr_t) > 4) {
 		eptr = dma2_a64;
 	} else {
 		eptr = dma2;
@@ -2433,6 +2823,9 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
 		return (retval);
 	}
 mbxsync:
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq);
+	}
 	switch (rq->req_header.rqs_entry_type) {
 	case RQSTYPE_REQUEST:
 		isp_put_request(isp, rq, qep);
@@ -2448,12 +2841,15 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
 	case RQSTYPE_T3RQS:
 		isp_put_request_t3(isp, (ispreqt3_t *) rq, (ispreqt3_t *) qep);
 		break;
+	case RQSTYPE_T7RQS:
+		isp_put_request_t7(isp, (ispreqt7_t *) rq, (ispreqt7_t *) qep);
+		break;
 	}
 	return (CMD_QUEUED);
 }
 
 static void
-isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
+isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle)
 {
 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
 	bus_dmamap_t *dp = &pcs->dmaps[isp_handle_index(handle)];
@@ -2469,10 +2865,12 @@ isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
 static void
 isp_pci_reset1(ispsoftc_t *isp)
 {
-	/* Make sure the BIOS is disabled */
-	isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
+	if (!IS_24XX(isp)) {
+		/* Make sure the BIOS is disabled */
+		isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
+	}
 	/* and enable interrupts */
-	ENABLE_INTS(isp);
+	ISP_ENABLE_INTS(isp);
 }
 
 static void
diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c
index c8b88fc61b0a..2e1273be8968 100644
--- a/sys/dev/isp/isp_sbus.c
+++ b/sys/dev/isp/isp_sbus.c
@@ -51,15 +51,17 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/isp/isp_freebsd.h>
 
-static uint16_t isp_sbus_rd_reg(ispsoftc_t *, int);
-static void isp_sbus_wr_reg(ispsoftc_t *, int, uint16_t);
+static uint32_t
+isp_sbus_rd_reg(ispsoftc_t *, int);
+static void
+isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t);
 static int
-isp_sbus_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
+isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
 static int isp_sbus_mbxdma(ispsoftc_t *);
 static int
-isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t);
+isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
 static void
-isp_sbus_dmateardown(ispsoftc_t *, XS_T *, uint16_t);
+isp_sbus_dmateardown(ispsoftc_t *, XS_T *, uint32_t);
 
 static void isp_sbus_reset1(ispsoftc_t *);
 static void isp_sbus_dumpregs(ispsoftc_t *, const char *);
@@ -149,6 +151,7 @@ isp_sbus_attach(device_t dev)
 	struct isp_sbussoftc *sbs;
 	ispsoftc_t *isp = NULL;
 	int locksetup = 0;
+	int ints_setup = 0;
 
 	/*
 	 * Figure out if we're supposed to skip this one.
@@ -184,10 +187,8 @@ isp_sbus_attach(device_t dev)
 
 	regs = NULL;
 	iqd = 0;
-
 	rid = 0;
-	regs =
-	    bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+	regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
 	if (regs == 0) {
 		device_printf(dev, "unable to map registers\n");
 		goto bad;
@@ -242,21 +243,19 @@ isp_sbus_attach(device_t dev)
 		sbs->sbus_mdvec.dv_conf1 |= BIU_BURST_ENABLE;
 	}
 
-	/*
-	 * Some early versions of the PTI SBus adapter
-	 * would fail in trying to download (via poking)
-	 * FW. We give up on them.
-	 */
-	if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 ||
-	    strcmp("ptisp", ofw_bus_get_name(dev)) == 0) {
-		isp->isp_confopts |= ISP_CFG_NORELOAD;
-	}
-
 	/*
 	 * We don't trust NVRAM on SBus cards
 	 */
 	isp->isp_confopts |= ISP_CFG_NONVRAM;
 
+	/*
+	 * Mark things if we're a PTI SBus adapter.
+	 */
+	if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 ||
+	    strcmp("ptisp", ofw_bus_get_name(dev)) == 0) {
+		SDPARAM(isp)->isp_ptisp = 1;
+	}
+
 
 #if __FreeBSD_version >= 700000
 	isp->isp_osinfo.fw = firmware_get("isp_1000");
@@ -277,14 +276,6 @@ isp_sbus_attach(device_t dev)
 	}
 #endif
 
-	iqd = 0;
-	sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
-	    RF_ACTIVE | RF_SHAREABLE);
-	if (sbs->sbus_ires == NULL) {
-		device_printf(dev, "could not allocate interrupt\n");
-		goto bad;
-	}
-
 	tval = 0;
         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
             "fwload_disable", &tval) == 0 && tval != 0) {
@@ -313,11 +304,20 @@ isp_sbus_attach(device_t dev)
 	mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
 	locksetup++;
 
+	iqd = 0;
+	sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
+	    RF_ACTIVE | RF_SHAREABLE);
+	if (sbs->sbus_ires == NULL) {
+		device_printf(dev, "could not allocate interrupt\n");
+		goto bad;
+	}
+
 	if (bus_setup_intr(dev, sbs->sbus_ires, ISP_IFLAGS,
 	    isp_sbus_intr, isp, &sbs->ih)) {
 		device_printf(dev, "could not setup interrupt\n");
 		goto bad;
 	}
+	ints_setup++;
 
 	/*
 	 * Set up logging levels.
@@ -327,8 +327,9 @@ isp_sbus_attach(device_t dev)
 	} else {
 		isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
 	}
-	if (bootverbose)
+	if (bootverbose) {
 		isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
+	}
 
 	/*
 	 * Make sure we're in reset state.
@@ -336,6 +337,7 @@ isp_sbus_attach(device_t dev)
 	ISP_LOCK(isp);
 	isp_reset(isp);
 	if (isp->isp_state != ISP_RESETSTATE) {
+		isp_uninit(isp);
 		ISP_UNLOCK(isp);
 		goto bad;
 	}
@@ -351,42 +353,33 @@ isp_sbus_attach(device_t dev)
 		ISP_UNLOCK(isp);
 		goto bad;
 	}
-	/*
-	 * XXXX: Here is where we might unload the f/w module
-	 * XXXX: (or decrease the reference count to it).
-	 */
 	ISP_UNLOCK(isp);
 	return (0);
 
 bad:
 
-	if (sbs && sbs->ih) {
+	if (sbs && ints_setup) {
 		(void) bus_teardown_intr(dev, sbs->sbus_ires, sbs->ih);
 	}
 
-	if (locksetup && isp) {
-		mtx_destroy(&isp->isp_osinfo.lock);
-	}
-
 	if (sbs && sbs->sbus_ires) {
 		bus_release_resource(dev, SYS_RES_IRQ, iqd, sbs->sbus_ires);
 	}
 
+	if (locksetup && isp) {
+		mtx_destroy(&isp->isp_osinfo.lock);
+	}
 
 	if (regs) {
 		(void) bus_release_resource(dev, 0, 0, regs);
 	}
 
 	if (sbs) {
-		if (sbs->sbus_isp.isp_param)
+		if (sbs->sbus_isp.isp_param) {
 			free(sbs->sbus_isp.isp_param, M_DEVBUF);
+		}
 		free(sbs, M_DEVBUF);
 	}
-
-	/*
-	 * XXXX: Here is where we might unload the f/w module
-	 * XXXX: (or decrease the reference count to it).
-	 */
 	return (ENXIO);
 }
 
@@ -394,17 +387,15 @@ static void
 isp_sbus_intr(void *arg)
 {
 	ispsoftc_t *isp = arg;
-	uint16_t isr, sema, mbox;
+	uint32_t isr;
+	uint16_t sema, mbox;
 
 	ISP_LOCK(isp);
 	isp->isp_intcnt++;
 	if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
 		isp->isp_intbogus++;
 	} else {
-		int iok = isp->isp_osinfo.intsok;
-		isp->isp_osinfo.intsok = 0;
 		isp_intr(isp, isr, sema, mbox);
-		isp->isp_osinfo.intsok = iok;
 	}
 	ISP_UNLOCK(isp);
 }
@@ -417,8 +408,7 @@ isp_sbus_intr(void *arg)
 	bus_space_read_2(sbc->sbus_st, sbc->sbus_sh, off)
 
 static int
-isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
-    uint16_t *semap, uint16_t *mbp)
+isp_sbus_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp)
 {
 	struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
 	uint16_t isr, sema;
@@ -438,7 +428,7 @@ isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
 	return (1);
 }
 
-static uint16_t
+static uint32_t
 isp_sbus_rd_reg(ispsoftc_t *isp, int regoff)
 {
 	uint16_t rval;
@@ -452,7 +442,7 @@ isp_sbus_rd_reg(ispsoftc_t *isp, int regoff)
 }
 
 static void
-isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val)
+isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
 {
 	struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp;
 	int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
@@ -605,8 +595,8 @@ typedef struct {
 	ispsoftc_t *isp;
 	void *cmd_token;
 	void *rq;
-	uint16_t *nxtip;
-	uint16_t optr;
+	uint32_t *nxtip;
+	uint32_t optr;
 	int error;
 } mush_t;
 
@@ -721,7 +711,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 
 static int
 isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
-	uint16_t *nxtip, uint16_t optr)
+	uint32_t *nxtip, uint32_t optr)
 {
 	struct isp_sbussoftc *sbs = (struct isp_sbussoftc *)isp;
 	ispreq_t *qep;
@@ -809,6 +799,9 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
 		return (retval);
 	}
 mbxsync:
+	if (isp->isp_dblev & ISP_LOGDEBUG1) {
+		isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq);
+	}
 	switch (rq->req_header.rqs_entry_type) {
 	case RQSTYPE_REQUEST:
 		isp_put_request(isp, rq, qep);
@@ -822,7 +815,7 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
 }
 
 static void
-isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
+isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle)
 {
 	struct isp_sbussoftc *sbs = (struct isp_sbussoftc *)isp;
 	bus_dmamap_t *dp = &sbs->dmaps[isp_handle_index(handle)];
@@ -834,12 +827,10 @@ isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
 	bus_dmamap_unload(sbs->dmat, *dp);
 }
 
-
 static void
 isp_sbus_reset1(ispsoftc_t *isp)
 {
-	/* enable interrupts */
-	ENABLE_INTS(isp);
+	ISP_ENABLE_INTS(isp);
 }
 
 static void
diff --git a/sys/dev/isp/isp_stds.h b/sys/dev/isp/isp_stds.h
new file mode 100644
index 000000000000..a25f7745a549
--- /dev/null
+++ b/sys/dev/isp/isp_stds.h
@@ -0,0 +1,200 @@
+/* $FreeBSD$ */
+/*-
+ * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters.
+ *
+ * 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 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.
+ *
+ */
+/*
+ * Structures that derive directly from public standards.
+ */
+#ifndef	_ISP_STDS_H
+#define	_ISP_STDS_H
+
+/*
+ * FC Frame Header
+ *
+ * Source: dpANS-X3.xxx-199x, section 18 (AKA FC-PH-2)
+ *
+ */
+typedef struct {
+	uint8_t		r_ctl;
+	uint8_t		d_id[3];
+	uint8_t		cs_ctl;
+	uint8_t		s_id[3];
+	uint8_t		type;
+	uint8_t		f_ctl;
+	uint8_t		seq_id;
+	uint8_t		df_ctl;
+	uint16_t	seq_cnt;
+	uint16_t	ox_id;
+	uint16_t	rx_id;
+	uint32_t	parameter;
+} fc_hdr_t;
+
+/*
+ * FCP_CMND_IU Payload
+ *
+ * Source: NICTS T10, Project 1144D, Revision 07a, Section 9 (AKA fcp2-r07a)
+ *
+ * Notes:
+ *	When additional cdb length is defined in fcp_cmnd_alen_datadir,
+ * 	bits 2..7, the actual cdb length is 16 + ((fcp_cmnd_alen_datadir>>2)*4),
+ *	with the datalength following in MSB format just after.
+ */
+typedef struct {
+	uint8_t		fcp_cmnd_lun[8];
+	uint8_t		fcp_cmnd_crn;
+	uint8_t		fcp_cmnd_task_attribute;
+	uint8_t		fcp_cmnd_task_management;
+	uint8_t		fcp_cmnd_alen_datadir;
+	union {
+		struct {
+			uint8_t		fcp_cmnd_cdb[16];
+			uint32_t	fcp_cmnd_dl;
+		} sf;
+		struct {
+			uint8_t		fcp_cmnd_cdb[1];
+		} lf;
+	} cdb_dl;
+} fcp_cmnd_iu_t;
+
+
+#define	FCP_CMND_TASK_ATTR_SIMPLE	0x00
+#define	FCP_CMND_TASK_ATTR_HEAD		0x01
+#define	FCP_CMND_TASK_ATTR_ORDERED	0x02
+#define	FCP_CMND_TASK_ATTR_ACA		0x04
+#define	FCP_CMND_TASK_ATTR_UNTAGGED	0x05
+#define	FCP_CMND_TASK_ATTR_MASK		0x07
+
+#define	FCP_CMND_ADDTL_CDBLEN_SHIFT	2
+
+#define	FCP_CMND_DATA_WRITE		0x01
+#define	FCP_CMND_DATA_READ		0x02
+
+#define	FCP_CMND_DATA_DIR_MASK		0x03
+
+#define	FCP_CMND_TMF_CLEAR_ACA		0x40
+#define	FCP_CMND_TMF_TGT_RESET		0x20
+#define	FCP_CMND_TMF_LUN_RESET		0x10
+#define	FCP_CMND_TMF_CLEAR_TASK_SET	0x04
+#define	FCP_CMND_TMF_ABORT_TASK_SET	0x02
+
+/*
+ * Basic CT IU Header
+ *
+ * Source: X3.288-199x Generic Services 2 Rev 5.3 (FC-GS-2) Section 4.3.1
+ */
+
+typedef struct {
+	uint8_t		ct_revision;
+	uint8_t		ct_in_id[3];
+	uint8_t		ct_fcs_type;
+	uint8_t		ct_fcs_subtype;
+	uint8_t		ct_options;
+	uint8_t		ct_reserved0;
+	uint16_t	ct_cmd_resp;
+	uint16_t	ct_bcnt_resid;
+	uint8_t		ct_reserved1;
+	uint8_t		ct_reason;
+	uint8_t		ct_explanation;
+	uint8_t		ct_vunique;
+} ct_hdr_t;
+#define	CT_REVISION		1
+#define	CT_FC_TYPE_FC		0xFC
+#define CT_FC_SUBTYPE_NS	0x02
+
+/*
+ * RFT_ID Requet CT_IU
+ *
+ * Source: INCITS xxx-200x Generic Services- 5 Rev 8.5 Section 5.2.5.30
+ */
+typedef struct {
+	ct_hdr_t	rftid_hdr;
+	uint8_t		rftid_reserved;
+	uint8_t		rftid_portid[3];
+	uint32_t	rftid_fc4types[8];
+} rft_id_t;
+
+
+/* unconverted miscellany */
+/*
+ * Basic FC Link Service defines
+ */
+/*
+ * These are in the R_CTL field.
+ */
+#define	ABTS			0x81
+#define	BA_ACC			0x84	/* of ABORT SEQUENCE */
+#define	BA_RJT			0x85	/* of ABORT SEQUENCE */
+
+/*
+ * Link Service Accept/Reject
+ */
+#define	LS_ACC			0x8002
+#define	LS_RJT			0x8001
+
+/*
+ * FC ELS Codes- bits 31-24 of the first payload word of an ELS frame.
+ */
+#define	PLOGI			0x03
+#define	FLOGI			0x04
+#define	LOGO			0x05
+#define	ABTX			0x06
+#define	PRLI			0x20
+#define	PRLO			0x21
+#define	TPRLO			0x24
+#define	RNC			0x53
+
+/*
+ * FC4 defines
+ */
+#define	FC4_IP		5	/* ISO/EEC 8802-2 LLC/SNAP */
+#define	FC4_SCSI	8	/* SCSI-3 via Fibre Channel Protocol (FCP) */
+#define	FC4_FC_SVC	0x20	/* Fibre Channel Services */
+
+#ifndef	MSG_ABORT
+#define	MSG_ABORT		0x06
+#endif
+#ifndef	MSG_BUS_DEV_RESET
+#define	MSG_BUS_DEV_RESET	0x0c
+#endif
+#ifndef	MSG_ABORT_TAG
+#define	MSG_ABORT_TAG		0x0d
+#endif
+#ifndef	MSG_CLEAR_QUEUE
+#define	MSG_CLEAR_QUEUE		0x0e
+#endif
+#ifndef	MSG_REL_RECOVERY
+#define	MSG_REL_RECOVERY	0x10
+#endif
+#ifndef	MSG_TERM_IO_PROC
+#define	MSG_TERM_IO_PROC	0x11
+#endif
+#ifndef	MSG_LUN_RESET
+#define	MSG_LUN_RESET		0x17
+#endif
+
+#endif	/* _ISP_STDS_H */
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c
index ebbd80b71114..a86b8ec415a7 100644
--- a/sys/dev/isp/isp_target.c
+++ b/sys/dev/isp/isp_target.c
@@ -53,15 +53,17 @@ static const char atiocope[] =
     "ATIO returned for lun %d because it was in the middle of Bus Device Reset "
     "on bus %d";
 static const char atior[] =
-    "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred "
-    "on bus %d";
+    "ATIO returned on for lun %d on from loopid %d because a Bus Reset "
+    "occurred on bus %d";
 
 static void isp_got_msg(ispsoftc_t *, in_entry_t *);
 static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *);
+static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *);
 static void isp_handle_atio(ispsoftc_t *, at_entry_t *);
 static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *);
 static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *);
 static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *);
+static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *);
 
 /*
  * The Qlogic driver gets an interrupt to look at response queue entries.
@@ -110,42 +112,57 @@ static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *);
  */
 
 int
-isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
+isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
 {
-	uint16_t status, seqid;
+	uint16_t status;
+	uint32_t seqid;
 	union {
 		at_entry_t	*atiop;
 		at2_entry_t	*at2iop;
 		at2e_entry_t	*at2eiop;
+		at7_entry_t	*at7iop;
 		ct_entry_t	*ctiop;
 		ct2_entry_t	*ct2iop;
 		ct2e_entry_t	*ct2eiop;
+		ct7_entry_t	*ct7iop;
 		lun_entry_t	*lunenp;
 		in_entry_t	*inotp;
 		in_fcentry_t	*inot_fcp;
 		in_fcentry_e_t	*inote_fcp;
+		in_fcentry_24xx_t *inot_24xx;
 		na_entry_t	*nackp;
 		na_fcentry_t	*nack_fcp;
 		na_fcentry_e_t	*nacke_fcp;
+		na_fcentry_24xx_t *nack_24xx;
 		isphdr_t	*hp;
+		abts_t		*abts;
+		abts_rsp_t	*abts_rsp;
+		els_t		*els;
 		void *		*vp;
 #define	atiop		unp.atiop
 #define	at2iop		unp.at2iop
 #define	at2eiop		unp.at2eiop
+#define	at7iop		unp.at7iop
 #define	ctiop		unp.ctiop
 #define	ct2iop		unp.ct2iop
 #define	ct2eiop		unp.ct2eiop
+#define	ct7iop		unp.ct7iop
 #define	lunenp		unp.lunenp
 #define	inotp		unp.inotp
 #define	inot_fcp	unp.inot_fcp
 #define	inote_fcp	unp.inote_fcp
+#define	inot_24xx	unp.inot_24xx
 #define	nackp		unp.nackp
 #define	nack_fcp	unp.nack_fcp
 #define	nacke_fcp	unp.nacke_fcp
+#define	nack_24xx	unp.nack_24xx
+#define	abts		unp.abts
+#define	abts_rsp	unp.abts_rsp
+#define els		unp.els
 #define	hdrp		unp.hp
 	} unp;
 	uint8_t local[QENTRY_LEN];
-	int bus, type, rval = 1;
+	int bus, type, level, rval = 1;
 
 	type = isp_get_response_type(isp, (isphdr_t *)vptr);
 	unp.vp = vptr;
@@ -154,30 +171,72 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
 
 	switch(type) {
 	case RQSTYPE_ATIO:
-		isp_get_atio(isp, atiop, (at_entry_t *) local);
-		isp_handle_atio(isp, (at_entry_t *) local);
+		if (IS_24XX(isp)) {
+			int len;
+
+			isp_get_atio7(isp, at7iop, (at7_entry_t *) local);
+			at7iop = (at7_entry_t *) local;
+			/*
+			 * Check for and do something with commands whose IULEN
+			 * extends past a singel queue entry.
+			 */
+			len = at7iop->at_ta_len & 0xfffff;
+			if (len > (QENTRY_LEN - 8)) {
+				len -= (QENTRY_LEN - 8);
+				isp_prt(isp, ISP_LOGINFO,
+				    "long IU length (%d) ignored", len);
+				while (len > 0) {
+					*optrp =  ISP_NXT_QENTRY(*optrp,
+					    RESULT_QUEUE_LEN(isp));
+					len -= QENTRY_LEN;
+				}
+			}
+			/*
+			 * Check for a task management function
+			 */
+			if (at7iop->at_cmnd.fcp_cmnd_task_management) {
+				isp_got_tmf_24xx(isp, at7iop);
+				break;
+			}
+			/*
+			 * Just go straight to outer layer for this one.
+			 */
+			(void) isp_async(isp, ISPASYNC_TARGET_ACTION, local);
+		} else {
+			isp_get_atio(isp, atiop, (at_entry_t *) local);
+			isp_handle_atio(isp, (at_entry_t *) local);
+		}
 		break;
+
 	case RQSTYPE_CTIO:
 		isp_get_ctio(isp, ctiop, (ct_entry_t *) local);
 		isp_handle_ctio(isp, (ct_entry_t *) local);
 		break;
+
 	case RQSTYPE_ATIO2:
-		if (IS_2KLOGIN(isp)) {
+		if (FCPARAM(isp)->isp_2klogin) {
 			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:
-		if (IS_2KLOGIN(isp)) {
+		if (FCPARAM(isp)->isp_2klogin) {
 			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_CTIO7:
+		isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local);
+		isp_handle_ctio7(isp, (ct7_entry_t *) local);
+		break;
+
 	case RQSTYPE_ENABLE_LUN:
 	case RQSTYPE_MODIFY_LUN:
 		isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local);
@@ -193,8 +252,36 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
 		 * (we set this initially in the Enable Lun entry).
 		 */
 		bus = 0;
-		if (IS_FC(isp)) {
-			if (IS_2KLOGIN(isp)) {
+		if (IS_24XX(isp)) {
+			isp_get_notify_24xx(isp, inot_24xx,
+			    (in_fcentry_24xx_t *)local);
+			inot_24xx = (in_fcentry_24xx_t *) local;
+			status = inot_24xx->in_status;
+			seqid = inot_24xx->in_rxid;
+			isp_prt(isp, ISP_LOGTDEBUG0,
+			    "Immediate Notify status=0x%x seqid=0x%x",
+			    status, seqid);
+			switch (status) {
+			case IN24XX_LIP_RESET:
+			case IN24XX_LINK_RESET:
+			case IN24XX_PORT_LOGOUT:
+			case IN24XX_PORT_CHANGED:
+			case IN24XX_LINK_FAILED:
+			case IN24XX_SRR_RCVD:
+			case IN24XX_ELS_RCVD:
+				(void) isp_async(isp, ISPASYNC_TARGET_ACTION,
+				    &local);
+				break;
+			default:
+				isp_prt(isp, ISP_LOGINFO,
+				    "isp_target_notify: unknown status (0x%x)",
+				    status);
+				isp_notify_ack(isp, local);
+				break;
+			}
+			break;
+		} else if (IS_FC(isp)) {
+			if (FCPARAM(isp)->isp_2klogin) {
 				isp_get_notify_fc_e(isp, inote_fcp,
 				    (in_fcentry_e_t *)local);
 			} else {
@@ -229,12 +316,28 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
 			}
 			break;
 		case IN_RSRC_UNAVAIL:
-			isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs");
+			isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs");
 			isp_notify_ack(isp, local);
 			break;
 		case IN_RESET:
-			(void) isp_target_async(isp, 0, ASYNC_BUS_RESET);
+		{
+			/*
+			 * We form the notify structure here because we need
+			 * to mark it as needing a NOTIFY ACK on return.
+			 */
+			tmd_notify_t notify;
+
+			MEMZERO(&notify, sizeof (tmd_notify_t));
+			notify.nt_hba = isp;
+			notify.nt_iid = INI_ANY;
+			/* nt_tgt set in outer layers */
+			notify.nt_lun = LUN_ANY;
+			notify.nt_tagval = TAG_ANY;
+			notify.nt_ncode = NT_BUS_RESET;
+			notify.nt_need_ack = 1;
+			(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
 			break;
+		}
 		case IN_PORT_LOGOUT:
 		case IN_ABORT_TASK:
 		case IN_PORT_CHANGED:
@@ -242,8 +345,9 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
 			(void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
 			break;
 		default:
-			isp_prt(isp, ISP_LOGERR,
-			    "bad status (0x%x) in isp_target_notify", status);
+			isp_prt(isp, ISP_LOGINFO,
+			    "isp_target_notify: unknown status (0x%x)",
+			    status);
 			isp_notify_ack(isp, local);
 			break;
 		}
@@ -254,26 +358,68 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
 		 * The ISP is acknowledging our acknowledgement of an
 		 * Immediate Notify entry for some asynchronous event.
 		 */
-		if (IS_FC(isp)) {
-			if (IS_2KLOGIN(isp)) {
+		if (IS_24XX(isp)) {
+			isp_get_notify_ack_24xx(isp, nack_24xx,
+			    (na_fcentry_24xx_t *) local);
+			nack_24xx = (na_fcentry_24xx_t *) local;
+			if (nack_24xx->na_status != NA_OK) {
+				level = ISP_LOGINFO;
+			} else {
+				level = ISP_LOGTDEBUG1;
+			}
+			isp_prt(isp, level,
+			    "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x",
+			    nack_24xx->na_status, nack_24xx->na_status_subcode,
+			    nack_24xx->na_rxid);
+		} else if (IS_FC(isp)) {
+			if (FCPARAM(isp)->isp_2klogin) {
 				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",
+			if (nack_fcp->na_status != NA_OK) {
+				level = ISP_LOGINFO;
+			} else {
+				level = ISP_LOGTDEBUG1;
+			}
+			isp_prt(isp, level,
+			    "Notify Ack Status=0x%x seqid 0x%x",
 			    nack_fcp->na_status, nack_fcp->na_seqid);
 		} else {
 			isp_get_notify_ack(isp, nackp, (na_entry_t *)local);
 			nackp = (na_entry_t *)local;
-			isp_prt(isp, ISP_LOGTDEBUG1,
+			if (nackp->na_status != NA_OK) {
+				level = ISP_LOGINFO;
+			} else {
+				level = ISP_LOGTDEBUG1;
+			}
+			isp_prt(isp, level,
 			    "Notify Ack event 0x%x status=0x%x seqid 0x%x",
 			    nackp->na_event, nackp->na_status, nackp->na_seqid);
 		}
 		break;
+
+	case RQSTYPE_ABTS_RCVD:
+		isp_get_abts(isp, abts, (abts_t *)local);
+		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
+		break;
+	case RQSTYPE_ABTS_RSP:
+		isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local);
+		abts_rsp = (abts_rsp_t *) local;
+		if (abts_rsp->abts_rsp_status) {
+			level = ISP_LOGINFO;
+		} else {
+			level = ISP_LOGTDEBUG0;
+		}
+		isp_prt(isp, level,
+		    "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)",
+		    abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status,
+		    abts_rsp->abts_rsp_payload.rsp.subcode1,
+		    abts_rsp->abts_rsp_payload.rsp.subcode2);
+		break;
 	default:
 		isp_prt(isp, ISP_LOGERR,
 		    "Unknown entry type 0x%x in isp_target_notify", type);
@@ -283,16 +429,23 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
 #undef	atiop
 #undef	at2iop
 #undef	at2eiop
+#undef	at7iop
 #undef	ctiop
 #undef	ct2iop
 #undef	ct2eiop
+#undef	ct7iop
 #undef	lunenp
 #undef	inotp
 #undef	inot_fcp
 #undef	inote_fcp
+#undef	inot_24xx
 #undef	nackp
 #undef	nack_fcp
 #undef	nacke_fcp
+#undef	hack_24xx
+#undef	abts
+#undef	abts_rsp
+#undef	els
 #undef	hdrp
 	return (rval);
 }
@@ -312,7 +465,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun,
     int cmd_cnt, int inot_cnt, uint32_t opaque)
 {
 	lun_entry_t el;
-	uint16_t nxti, optr;
+	uint32_t nxti, optr;
 	void *outp;
 
 
@@ -344,7 +497,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun,
 	if (IS_SCSI(isp)) {
 		el.le_tgt = tgt;
 		el.le_lun = lun;
-	} else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
+	} else if (FCPARAM(isp)->isp_sccfw == 0) {
 		el.le_lun = lun;
 	}
 
@@ -364,7 +517,7 @@ int
 isp_target_put_entry(ispsoftc_t *isp, void *ap)
 {
 	void *outp;
-	uint16_t nxti, optr;
+	uint32_t nxti, optr;
 	uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
 
 	if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
@@ -377,28 +530,34 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap)
 		isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp);
 		break;
 	case RQSTYPE_ATIO2:
-        if (IS_2KLOGIN(isp)) {
-            isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp);
-        } else {
-            isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp);
-        }
+		if (FCPARAM(isp)->isp_2klogin) {
+			isp_put_atio2e(isp, (at2e_entry_t *) ap,
+			    (at2e_entry_t *) outp);
+		} else {
+			isp_put_atio2(isp, (at2_entry_t *) ap,
+			    (at2_entry_t *) outp);
+		}
 		break;
 	case RQSTYPE_CTIO:
 		isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp);
 		break;
 	case RQSTYPE_CTIO2:
-        if (IS_2KLOGIN(isp)) {
-            isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp);
-        } else {
-            isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp);
-        }
+		if (FCPARAM(isp)->isp_2klogin) {
+			isp_put_ctio2e(isp, (ct2e_entry_t *) ap,
+			    (ct2e_entry_t *) outp);
+		} else {
+			isp_put_ctio2(isp, (ct2_entry_t *) ap,
+			    (ct2_entry_t *) outp);
+		}
+		break;
+	case RQSTYPE_CTIO7:
+		isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp);
 		break;
 	default:
 		isp_prt(isp, ISP_LOGERR,
 		    "Unknown type 0x%x in isp_put_entry", etype);
 		return (-1);
 	}
-
 	ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap);
 	ISP_ADD_REQUEST(isp, nxti);
 	return (0);
@@ -418,12 +577,12 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg)
 		at2_entry_t *aep = arg;
 		atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
 		atun._atio2.at_header.rqs_entry_count = 1;
-		if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
-			atun._atio2.at_scclun = (uint16_t) aep->at_scclun;
+		if (FCPARAM(isp)->isp_sccfw) {
+			atun._atio2.at_scclun = aep->at_scclun;
 		} else {
 			atun._atio2.at_lun = (uint8_t) aep->at_lun;
 		}
-		if (IS_2KLOGIN(isp)) {
+		if (FCPARAM(isp)->isp_2klogin) {
 			atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid;
 		} else {
 			atun._atio2.at_iid = aep->at_iid;
@@ -465,28 +624,56 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg)
  */
 
 int
-isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint16_t hdl)
+isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl)
 {
 	int sts;
 	union {
 		ct_entry_t _ctio;
 		ct2_entry_t _ctio2;
 		ct2e_entry_t _ctio2e;
+		ct7_entry_t _ctio7;
 	} un;
 
 	MEMZERO(&un, sizeof un);
 	sts = code & 0xff;
 
-	if (IS_FC(isp)) {
+	if (IS_24XX(isp)) {
+		at7_entry_t *aep = arg;
+		ct7_entry_t *cto = &un._ctio7;
+
+		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+		cto->ct_header.rqs_entry_count = 1;
+/* XXXX */	cto->ct_nphdl = aep->at_hdr.seq_id;
+		cto->ct_rxid = aep->at_rxid;
+		cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) |
+		    aep->at_hdr.s_id[2];
+		cto->ct_iid_hi = aep->at_hdr.s_id[0];
+		cto->ct_oxid = aep->at_hdr.ox_id;
+		cto->ct_scsi_status = sts;
+		cto->ct_flags = CT7_FLAG_MODE1 | CT7_NO_DATA | CT7_SENDSTATUS;
+		if (sts == SCSI_CHECK && (code & ECMD_SVALID)) {
+			cto->rsp.m1.ct_resplen = 16;
+			cto->rsp.m1.ct_resp[0] = 0xf0;
+			cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
+			cto->rsp.m1.ct_resp[7] = 8;
+			cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
+			cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
+		}
+		if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) {
+			cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
+			cto->ct_scsi_status |= CT2_DATA_UNDER;
+		}
+		cto->ct_syshandle = hdl;
+	} else if (IS_FC(isp)) {
 		at2_entry_t *aep = arg;
 		ct2_entry_t *cto = &un._ctio2;
 
 		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
 		cto->ct_header.rqs_entry_count = 1;
-		if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
+		if (FCPARAM(isp)->isp_sccfw == 0) {
 			cto->ct_lun = aep->at_lun;
 		}
-		if (IS_2KLOGIN(isp)) {
+		if (FCPARAM(isp)->isp_2klogin) {
 			un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid;
 		} else {
 			cto->ct_iid = aep->at_iid;
@@ -565,6 +752,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
 		notify.nt_ncode = NT_LINK_DOWN;
 		(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
 		break;
+	case ASYNC_LIP_ERROR:
 	case ASYNC_LIP_F8:
 	case ASYNC_LIP_OCCURRED:
 	case ASYNC_LOOP_RESET:
@@ -584,7 +772,13 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
 	{
 		uint8_t storage[QENTRY_LEN];
 		memset(storage, 0, QENTRY_LEN);
-		if (IS_FC(isp)) {
+		if (IS_24XX(isp)) {
+			ct7_entry_t *ct = (ct7_entry_t *) storage;
+			ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+			ct->ct_nphdl = CT7_OK;
+			ct->ct_syshandle = bus;
+			ct->ct_flags = CT7_SENDSTATUS|CT7_FASTPOST;
+		} else if (IS_FC(isp)) {
             		/* This should also suffice for 2K login code */
 			ct2_entry_t *ct = (ct2_entry_t *) storage;
 			ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
@@ -599,7 +793,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
 			ct->ct_flags = CT_SENDSTATUS;
 		}
 		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage);
-		return (0);
+		break;
 	}
 	default:
 		isp_prt(isp, ISP_LOGERR,
@@ -679,14 +873,14 @@ static void
 isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
 {
 	tmd_notify_t nt;
-	static const char f1[] = "%s from loop id %d lun %d seq 0x%x";
+	static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x";
 	static const char f2[] = 
-	    "unknown %s 0x%x lun %d loop id %d task flags 0x%x seq 0x%x\n";
+	    "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
 	uint16_t seqid, loopid;
 
 	MEMZERO(&nt, sizeof (tmd_notify_t));
 	nt.nt_hba = isp;
-	if (IS_2KLOGIN(isp)) {
+	if (FCPARAM(isp)->isp_2klogin) {
 		nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid;
 		loopid = ((in_fcentry_e_t *)inp)->in_iid;
 		seqid = ((in_fcentry_e_t *)inp)->in_seqid;
@@ -696,12 +890,13 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
 		seqid = inp->in_seqid;
 	}
 	/* nt_tgt set in outer layers */
-	if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
+	if (FCPARAM(isp)->isp_sccfw) {
 		nt.nt_lun = inp->in_scclun;
 	} else {
 		nt.nt_lun = inp->in_lun;
 	}
 	IN_FC_MAKE_TAGID(nt.nt_tagval, 0, seqid);
+	nt.nt_need_ack = 1;
 	nt.nt_lreserved = inp;
 
 	if (inp->in_status != IN_MSG_RECEIVED) {
@@ -741,11 +936,69 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
 	(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
 }
 
+static void
+isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
+{
+	tmd_notify_t nt;
+	static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%x";
+	static const char f2[] = 
+	    "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%x\n";
+	uint32_t sid;
+
+	MEMZERO(&nt, sizeof (tmd_notify_t));
+	nt.nt_hba = isp;
+	nt.nt_iid = INI_ANY;
+	nt.nt_lun =
+	    (aep->at_cmnd.fcp_cmnd_lun[0] << 8) |
+	    (aep->at_cmnd.fcp_cmnd_lun[1]);
+	nt.nt_tagval = aep->at_rxid;
+	nt.nt_lreserved = aep;
+	sid =
+	    (aep->at_hdr.s_id[0] << 16) |
+	    (aep->at_hdr.s_id[1] <<  8) |
+	    (aep->at_hdr.s_id[2]);
+
+	if (aep->at_cmnd.fcp_cmnd_task_management &
+	    FCP_CMND_TMF_ABORT_TASK_SET) {
+		isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET",
+		    sid, nt.nt_lun, nt.nt_tagval);
+		nt.nt_ncode = NT_ABORT_TASK_SET;
+	} else if (aep->at_cmnd.fcp_cmnd_task_management &
+	    FCP_CMND_TMF_CLEAR_TASK_SET) {
+		isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET",
+		    sid, nt.nt_lun, nt.nt_tagval);
+		nt.nt_ncode = NT_CLEAR_TASK_SET;
+	} else if (aep->at_cmnd.fcp_cmnd_task_management &
+	    FCP_CMND_TMF_LUN_RESET) {
+		isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET",
+		    sid, nt.nt_lun, nt.nt_tagval);
+		nt.nt_ncode = NT_LUN_RESET;
+	} else if (aep->at_cmnd.fcp_cmnd_task_management &
+	    FCP_CMND_TMF_TGT_RESET) {
+		isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET",
+		    sid, nt.nt_lun, nt.nt_tagval);
+		nt.nt_ncode = NT_TARGET_RESET;
+		nt.nt_lun = LUN_ANY;
+	} else if (aep->at_cmnd.fcp_cmnd_task_management &
+	    FCP_CMND_TMF_CLEAR_ACA) {
+		isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA",
+		    sid, nt.nt_lun, nt.nt_tagval);
+		nt.nt_ncode = NT_CLEAR_ACA;
+	} else {
+		isp_prt(isp, ISP_LOGWARN, f2,
+		    aep->at_cmnd.fcp_cmnd_task_management,
+		    nt.nt_lun, sid, nt.nt_tagval);
+		isp_endcmd(isp, aep, 0, 0);
+		return;
+	}
+	(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+}
+
 void
 isp_notify_ack(ispsoftc_t *isp, void *arg)
 {
 	char storage[QENTRY_LEN];
-	uint16_t nxti, optr;
+	uint32_t nxti, optr;
 	void *outp;
 
 	if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
@@ -756,14 +1009,49 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
 
 	MEMZERO(storage, QENTRY_LEN);
 
-	if (IS_FC(isp)) {
+	if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) {
+		at7_entry_t *aep = arg;
+		isp_endcmd(isp, aep, 0, 0);
+		return;
+	} else if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) {
+		abts_rsp_t *abts_rsp = (abts_rsp_t *) storage;
+		/*
+		 * The caller will have set response values as appropriate
+		 * in the ABTS structure just before calling us.
+		 */
+		MEMCPY(abts_rsp, arg, QENTRY_LEN);
+		isp_put_abts_rsp(isp, abts_rsp, (abts_rsp_t *)outp);
+	} else if (IS_24XX(isp)) {
+		na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage;
+		if (arg) {
+			in_fcentry_24xx_t *in = arg;
+			na->na_nphdl = in->in_nphdl;
+			na->na_status = in->in_status;
+			na->na_status_subcode = in->in_status_subcode;
+			na->na_rxid = in->in_rxid;
+			na->na_oxid = in->in_oxid;
+			if (in->in_status == IN24XX_SRR_RCVD) {
+				na->na_srr_rxid = in->in_srr_rxid;
+				na->na_srr_reloff_hi = in->in_srr_reloff_hi;
+				na->na_srr_reloff_lo = in->in_srr_reloff_lo;
+				na->na_srr_iu = in->in_srr_iu;
+				na->na_srr_flags = 1;
+				na->na_srr_reject_vunique = 0;
+				na->na_srr_reject_explanation = 1;
+				na->na_srr_reject_code = 1;
+			}
+		}
+		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
+		na->na_header.rqs_entry_count = 1;
+		isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp);
+	} else if (IS_FC(isp)) {
 		na_fcentry_t *na = (na_fcentry_t *) storage;
 		int iid = 0;
 
 		if (arg) {
 			in_fcentry_t *inp = arg;
 			MEMCPY(storage, arg, sizeof (isphdr_t));
-			if (IS_2KLOGIN(isp)) {
+			if (FCPARAM(isp)->isp_2klogin) {
 				((na_fcentry_e_t *)na)->na_iid =
 				    ((in_fcentry_e_t *)inp)->in_iid;
 				iid = ((na_fcentry_e_t *)na)->na_iid;
@@ -788,14 +1076,14 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
 		}
 		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
 		na->na_header.rqs_entry_count = 1;
-		if (IS_2KLOGIN(isp)) {
+		if (FCPARAM(isp)->isp_2klogin) {
 			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);
 		}
-		isp_prt(isp, ISP_LOGTDEBUG0, "notify ack iid %u seqid %x flags "
-		    "%x tflags %x response %x", iid, na->na_seqid,
+		isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x "
+		    "flags %x tflags %x response %x", iid, na->na_seqid,
 		    na->na_flags, na->na_task_flags, na->na_response);
 	} else {
 		na_entry_t *na = (na_entry_t *) storage;
@@ -815,8 +1103,8 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
 		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
 		na->na_header.rqs_entry_count = 1;
 		isp_put_notify_ack(isp, na, (na_entry_t *)outp);
-		isp_prt(isp, ISP_LOGTDEBUG0, "notify ack iid %u lun %u tgt %u "
-		    "seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt,
+		isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt "
+		    "%u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt,
 		    na->na_seqid, na->na_event);
 	}
 	ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);
@@ -897,7 +1185,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
 
 	default:
 		isp_prt(isp, ISP_LOGERR,
-		    "Unknown ATIO status 0x%x from initiator %d for lun %d",
+		    "Unknown ATIO status 0x%x from loopid %d for lun %d",
 		    aep->at_status, aep->at_iid, lun);
 		(void) isp_target_put_atio(isp, aep);
 		break;
@@ -909,13 +1197,13 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
 {
 	int lun, iid;
 
-	if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
+	if (FCPARAM(isp)->isp_sccfw) {
 		lun = aep->at_scclun;
 	} else {
 		lun = aep->at_lun;
 	}
 
-	if (IS_2KLOGIN(isp)) {
+	if (FCPARAM(isp)->isp_2klogin) {
 		iid = ((at2e_entry_t *)aep)->at_iid;
 	} else {
 		iid = aep->at_iid;
@@ -986,7 +1274,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
 
 	default:
 		isp_prt(isp, ISP_LOGERR,
-		    "Unknown ATIO2 status 0x%x from initiator %d for lun %d",
+		    "Unknown ATIO2 status 0x%x from loopid %d for lun %d",
 		    aep->at_status, iid, lun);
 		(void) isp_target_put_atio(isp, aep);
 		break;
@@ -1002,8 +1290,9 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
 
 	if (ct->ct_syshandle) {
 		xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
-		if (xs == NULL)
+		if (xs == NULL) {
 			pl = ISP_LOGALL;
+		}
 	} else {
 		xs = NULL;
 	}
@@ -1055,7 +1344,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
 		if (fmsg == NULL)
 			fmsg = "ABORT TAG message sent by Initiator";
 
-		isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg);
+		isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg);
 		break;
 
 	case CT_INVAL:
@@ -1156,14 +1445,15 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
 static void
 isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 {
-	XS_T *xs;
+	void *xs;
 	int pl = ISP_LOGTDEBUG2;
 	char *fmsg = NULL;
 
 	if (ct->ct_syshandle) {
 		xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
-		if (xs == NULL)
+		if (xs == NULL) {
 			pl = ISP_LOGALL;
+		}
 	} else {
 		xs = NULL;
 	}
@@ -1193,7 +1483,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 		 * status. These CTIOs are handled in that same way as
 		 * CT_ABORTED ones, so just fall through here.
 		 */
-		fmsg = "TARGET RESET Task Management Function Received";
+		fmsg = "TARGET RESET";
 		/*FALLTHROUGH*/
 	case CT_RESET:
 		if (fmsg == NULL)
@@ -1205,11 +1495,12 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 		 * Bus Free and returns all outstanding CTIOs with the status
 		 * set, then sends us an Immediate Notify entry.
 		 */
-		if (fmsg == NULL)
-			fmsg = "ABORT Task Management Function Received";
+		if (fmsg == NULL) {
+			fmsg = "ABORT";
+		}
 
-		isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s: RX_ID=0x%x",
-		    fmsg, ct->ct_rxid);
+		isp_prt(isp, ISP_LOGTDEBUG0,
+		    "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
 		break;
 
 	case CT_INVAL:
@@ -1235,7 +1526,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 		if (fmsg == NULL)
 			fmsg = "Port Logout";
 		/*FALLTHROUGH*/
-	case CT_PORTNOTAVAIL:
+	case CT_PORTUNAVAIL:
 		if (fmsg == NULL)
 			fmsg = "Port not available";
 		/*FALLTHROUGH*/
@@ -1246,7 +1537,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 	case CT_NOACK:
 		if (fmsg == NULL)
 			fmsg = "unacknowledged Immediate Notify pending";
-		isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
+		isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
 		break;
 
 	case CT_INVRXID:
@@ -1254,7 +1545,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 		 * CTIO rejected by the firmware because an invalid RX_ID.
 		 * Just print a message.
 		 */
-		isp_prt(isp, ISP_LOGERR,
+		isp_prt(isp, ISP_LOGWARN,
 		    "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
 		break;
 
@@ -1312,4 +1603,157 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 		 */
 	}
 }
+
+static void
+isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
+{
+	void *xs;
+	int pl = ISP_LOGTDEBUG2;
+	char *fmsg = NULL;
+
+	if (ct->ct_syshandle) {
+		xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
+		if (xs == NULL) {
+			pl = ISP_LOGALL;
+		}
+	} else {
+		xs = NULL;
+	}
+
+	switch(ct->ct_nphdl) {
+	case CT7_BUS_ERROR:
+		isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
+		/* FALL Through */
+	case CT7_DATA_OVER:
+	case CT7_DATA_UNDER:
+	case CT7_OK:
+		/*
+		 * There are generally 2 possibilities as to why we'd get
+		 * this condition:
+		 * 	We sent or received data.
+		 * 	We sent status & command complete.
+		 */
+
+		break;
+
+	case CT7_RESET:
+		if (fmsg == NULL) {
+			fmsg = "LIP Reset";
+		}
+		/*FALLTHROUGH*/
+	case CT7_ABORTED:
+		/*
+		 * When an Abort message is received the firmware goes to
+		 * Bus Free and returns all outstanding CTIOs with the status
+		 * set, then sends us an Immediate Notify entry.
+		 */
+		if (fmsg == NULL) {
+			fmsg = "ABORT";
+		}
+		isp_prt(isp, ISP_LOGTDEBUG0,
+		    "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
+		break;
+
+	case CT7_TIMEOUT:
+		if (fmsg == NULL) {
+			fmsg = "command";
+		}
+		isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
+		break;
+
+	case CT7_ERR:
+		fmsg = "Completed with Error";
+		/*FALLTHROUGH*/
+	case CT7_LOGOUT:
+		if (fmsg == NULL) {
+			fmsg = "Port Logout";
+		}
+		/*FALLTHROUGH*/
+	case CT7_PORTUNAVAIL:
+		if (fmsg == NULL) {
+			fmsg = "Port not available";
+		}
+		/*FALLTHROUGH*/
+	case CT7_PORTCHANGED:
+		if (fmsg == NULL) {
+			fmsg = "Port Changed";
+		}
+		isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
+		break;
+
+	case CT7_INVRXID:
+		/*
+		 * CTIO rejected by the firmware because an invalid RX_ID.
+		 * Just print a message.
+		 */
+		isp_prt(isp, ISP_LOGWARN,
+		    "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
+		break;
+
+	case CT7_REASSY_ERR:
+		isp_prt(isp, ISP_LOGWARN, "reassembly error");
+		break;
+
+	case CT7_SRR:
+		isp_prt(isp, ISP_LOGWARN, "SRR received");
+		break;
+
+	default:
+		isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x",
+		    ct->ct_nphdl);
+		break;
+	}
+
+	if (xs == NULL) {
+		/*
+		 * There may be more than one CTIO for a data transfer,
+		 * or this may be a status CTIO we're not monitoring.
+		 *
+		 * The assumption is that they'll all be returned in the
+		 * order we got them.
+		 */
+		if (ct->ct_syshandle == 0) {
+			if (ct->ct_flags & CT7_TERMINATE) {
+				isp_prt(isp, ISP_LOGINFO,
+				    "termination of 0x%x complete",
+				    ct->ct_rxid);
+			} else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) {
+				isp_prt(isp, pl,
+				    "intermediate CTIO completed ok");
+			} else {
+				isp_prt(isp, pl,
+				    "unmonitored CTIO completed ok");
+			}
+		} else {
+			isp_prt(isp, pl,
+			    "NO xs for CTIO (handle 0x%x) status 0x%x",
+			    ct->ct_syshandle, ct->ct_nphdl);
+		}
+	} else {
+		if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
+			ISP_DMAFREE(isp, xs, ct->ct_syshandle);
+		}
+		if (ct->ct_flags & CT2_SENDSTATUS) {
+			/*
+			 * Sent status and command complete.
+			 *
+			 * We're now really done with this command, so we
+			 * punt to the platform dependent layers because
+			 * only there can we do the appropriate command
+			 * complete thread synchronization.
+			 */
+			isp_prt(isp, pl, "status CTIO complete");
+		} else {
+			/*
+			 * Final CTIO completed. Release DMA resources and
+			 * notify platform dependent layers.
+			 */
+			isp_prt(isp, pl, "data CTIO complete");
+		}
+		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
+		/*
+		 * The platform layer will destroy the handle if appropriate.
+		 */
+	}
+}
 #endif
diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h
index be0387760c6d..80bbe64638fd 100644
--- a/sys/dev/isp/isp_target.h
+++ b/sys/dev/isp/isp_target.h
@@ -155,28 +155,48 @@ typedef struct {
 #define	TASK_FLAGS_CLEAR_TASK_SET	(1<<10)
 #define	TASK_FLAGS_ABORT_TASK_SET	(1<<9)
 
-#ifndef	MSG_ABORT
-#define	MSG_ABORT		0x06
-#endif
-#ifndef	MSG_BUS_DEV_RESET
-#define	MSG_BUS_DEV_RESET	0x0c
-#endif
-#ifndef	MSG_ABORT_TAG
-#define	MSG_ABORT_TAG		0x0d
-#endif
-#ifndef	MSG_CLEAR_QUEUE
-#define	MSG_CLEAR_QUEUE		0x0e
-#endif
-#ifndef	MSG_REL_RECOVERY
-#define	MSG_REL_RECOVERY	0x10
-#endif
-#ifndef	MSG_TERM_IO_PROC
-#define	MSG_TERM_IO_PROC	0x11
-#endif
-#ifndef	MSG_LUN_RESET
-#define	MSG_LUN_RESET		0x17
-#endif
+/*
+ * ISP24XX Immediate Notify
+ */
+typedef struct {
+	isphdr_t	in_header;
+	uint32_t	in_reserved;
+	uint16_t	in_nphdl;
+	uint16_t	in_reserved1;
+	uint16_t	in_flags;
+	uint16_t	in_srr_rxid;
+	uint16_t	in_status;
+	uint8_t		in_status_subcode;
+	uint8_t		in_reserved2;
+	uint32_t	in_rxid;
+	uint16_t	in_srr_reloff_lo;
+	uint16_t	in_srr_reloff_hi;
+	uint16_t	in_srr_iu;
+	uint16_t	in_srr_oxid;
+	uint8_t		in_reserved3[18];
+	uint8_t		in_reserved4;
+	uint8_t		in_vpindex;
+	uint32_t	in_reserved5;
+	uint16_t	in_portid_lo;
+	uint8_t		in_portid_hi;
+	uint8_t		in_reserved6;
+	uint16_t	in_reserved7;
+	uint16_t	in_oxid;
+} in_fcentry_24xx_t;
 
+#define	IN24XX_FLAG_PUREX_IOCB		0x1
+#define	IN24XX_FLAG_GLOBAL_LOGOUT	0x2
+
+#define	IN24XX_LIP_RESET	0x0E
+#define	IN24XX_LINK_RESET	0x0F
+#define	IN24XX_PORT_LOGOUT	0x29
+#define	IN24XX_PORT_CHANGED	0x2A
+#define	IN24XX_LINK_FAILED	0x2E
+#define	IN24XX_SRR_RCVD		0x45
+#define	IN24XX_ELS_RCVD		0x46	/*
+					 * login-affectin ELS received- check
+					 * subcode for specific opcode
+					 */
 /*
  * Notify Acknowledge Entry structure
  */
@@ -234,6 +254,36 @@ typedef struct {
 #define NAFC_RST_CLRD	0x20	/* Clear LIP Reset */
 #define	NAFC_TVALID	0x10	/* task mangement response code is valid */
 
+/*
+ * ISP24XX Notify Acknowledge
+ */
+
+typedef struct {
+	isphdr_t	na_header;
+	uint32_t	na_handle;
+	uint16_t	na_nphdl;
+	uint16_t	na_reserved1;
+	uint16_t	na_flags;
+	uint16_t	na_srr_rxid;
+	uint16_t	na_status;
+	uint8_t		na_status_subcode;
+	uint8_t		na_reserved2;
+	uint32_t	na_rxid;
+	uint16_t	na_srr_reloff_lo;
+	uint16_t	na_srr_reloff_hi;
+	uint16_t	na_srr_iu;
+	uint16_t	na_srr_flags;
+	uint8_t		na_reserved3[18];
+	uint8_t		na_reserved4;
+	uint8_t		na_vpindex;
+	uint8_t		na_srr_reject_vunique;
+	uint8_t		na_srr_reject_explanation;
+	uint8_t		na_srr_reject_code;
+	uint8_t		na_reserved5;
+	uint8_t		na_reserved6[6];
+	uint16_t	na_oxid;
+} na_fcentry_24xx_t;
+
 /*
  * Accept Target I/O Entry structure
  */
@@ -399,6 +449,32 @@ typedef struct {
 	tid &= ~0xffff;							\
 	tid |= (inst << 16)
 
+/*
+ * 24XX ATIO Definition
+ *
+ * This is *quite* different from other entry types.
+ * First of all, it has its own queue it comes in on.
+ *
+ * Secondly, it doesn't have a normal header.
+ *
+ * Thirdly, it's just a passthru of the FCP CMND IU
+ * which is recorded in big endian mode.
+ */
+typedef struct {
+	uint8_t		at_type;
+	uint8_t		at_count;
+	/*
+	 * Task attribute in high four bits,
+	 * the rest is the FCP CMND IU Length.
+	 * NB: the command can extend past the
+	 * length for a single queue entry.
+	 */
+	uint16_t	at_ta_len;
+	uint32_t	at_rxid;
+	fc_hdr_t	at_hdr;
+	fcp_cmnd_iu_t	at_cmnd;
+} at7_entry_t;
+
 
 /*
  * Continue Target I/O Entry structure
@@ -409,8 +485,7 @@ typedef struct {
  */
 typedef struct {
 	isphdr_t	ct_header;
-	uint16_t	ct_reserved;
-#define	ct_syshandle	ct_reserved	/* we use this */
+	uint16_t	ct_syshandle;
 	uint16_t	ct_fwhandle;	/* required by f/w */
 	uint8_t		ct_lun;	/* lun */
 	uint8_t		ct_iid;	/* initiator id */
@@ -425,14 +500,7 @@ typedef struct {
 	uint32_t	ct_resid;	/* residual length */
 	uint16_t	ct_timeout;
 	uint16_t	ct_seg_count;
-	/*
-	 * This is so we can share tag name space with
-	 * CTIO{2,3,4} with the minimum of pain.
-	 */
-	union {
-		ispds_t		ct_a[ISP_RQDSEG];
-	} _u;
-#define	ct_dataseg	_u.ct_a
+	ispds_t		ct_dataseg[ISP_RQDSEG];
 } ct_entry_t;
 
 /*
@@ -481,10 +549,10 @@ typedef struct {
 #define	CT_BUS_ERROR	0x10	/* (FC Only) DMA PCI Error */
 #define	CT_PANIC	0x13	/* Unrecoverable Error */
 #define CT_PHASE_ERROR	0x14	/* Bus phase sequence error */
-#define CT_BDR_MSG	0x17	/* Bus Device Reset msg received */
 #define	CT_DATA_UNDER	0x15	/* (FC only) Data Underrun */
+#define CT_BDR_MSG	0x17	/* Bus Device Reset msg received */
 #define CT_TERMINATED	0x19	/* due to Terminate Transfer mbox cmd */
-#define	CT_PORTNOTAVAIL	0x28	/* port not available */
+#define	CT_PORTUNAVAIL	0x28	/* port not available */
 #define	CT_LOGOUT	0x29	/* port logout */
 #define	CT_PORTCHANGED	0x2A	/* port changed */
 #define	CT_IDE		0x33	/* Initiator Detected Error */
@@ -513,8 +581,7 @@ typedef struct {
 #define	MAXRESPLEN	26
 typedef struct {
 	isphdr_t	ct_header;
-	uint16_t	ct_reserved;
-	uint16_t	ct_fwhandle;	/* just to match CTIO */
+	uint32_t	ct_syshandle;
 	uint8_t		ct_lun;		/* lun */
 	uint8_t		ct_iid;		/* initiator id */
 	uint16_t	ct_rxid;	/* response ID */
@@ -544,13 +611,10 @@ typedef struct {
 			uint16_t ct_scsi_status;
 			uint32_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;
-#define	ct_dataseg	_u.ct_a
-#define	ct_dataseg64	_u.ct_b
-#define	ct_dslist	_u.ct_c
+				ispds_t ct_dataseg[ISP_RQDSEG_T2];
+				ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
+				ispdslist_t ct_dslist;
+			} u;
 		} m0;
 		struct {
 			uint16_t _reserved;
@@ -572,8 +636,7 @@ typedef struct {
 
 typedef struct {
 	isphdr_t	ct_header;
-	uint16_t	ct_reserved;
-	uint16_t	ct_fwhandle;	/* just to match CTIO */
+	uint32_t	ct_syshandle;
 	uint16_t	ct_iid;		/* initiator id */
 	uint16_t	ct_rxid;	/* response ID */
 	uint16_t	ct_flags;
@@ -589,10 +652,10 @@ typedef struct {
 			uint16_t ct_scsi_status;
 			uint32_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;
+				ispds_t ct_dataseg[ISP_RQDSEG_T2];
+				ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
+				ispdslist_t ct_dslist;
+			} u;
 		} m0;
 		struct {
 			uint16_t _reserved;
@@ -615,16 +678,17 @@ typedef struct {
 /*
  * ct_flags values for CTIO2
  */
-#define	CT2_FLAG_MMASK	0x0003
 #define	CT2_FLAG_MODE0	0x0000
 #define	CT2_FLAG_MODE1	0x0001
 #define	CT2_FLAG_MODE2	0x0002
-#define CT2_DATA_IN	CT_DATA_IN
-#define CT2_DATA_OUT	CT_DATA_OUT
-#define CT2_NO_DATA	CT_NO_DATA
-#define CT2_DATAMASK	CT_DATAMASK
+#define		CT2_FLAG_MMASK	0x0003
+#define CT2_DATA_IN	0x0040
+#define CT2_DATA_OUT	0x0080
+#define CT2_NO_DATA	0x00C0
+#define 	CT2_DATAMASK	0x00C0
 #define	CT2_CCINCR	0x0100
 #define	CT2_FASTPOST	0x0200
+#define	CT2_CONFIRM	0x2000
 #define	CT2_TERMINATE	0x4000
 #define CT2_SENDSTATUS	0x8000
 
@@ -642,6 +706,183 @@ typedef struct {
 #define	CT2_DATA_OVER		0x0400
 #define	CT2_DATA_UNDER		0x0800
 
+/*
+ * ISP24XX CTIO
+ */
+#define	MAXRESPLEN_24XX	24
+typedef struct {
+	isphdr_t	ct_header;
+	uint32_t	ct_syshandle;
+	uint16_t	ct_nphdl;	/* status on returned CTIOs */
+	uint16_t	ct_timeout;
+	uint16_t	ct_seg_count;
+	uint8_t		ct_vpindex;
+	uint8_t		ct_xflags;
+	uint16_t	ct_iid_lo;	/* low 16 bits of portid */
+	uint8_t		ct_iid_hi;	/* hi 8 bits of portid */
+	uint8_t		ct_reserved;
+	uint32_t	ct_rxid;
+	uint16_t	ct_senselen;	/* mode 0 only */
+	uint16_t	ct_flags;
+	int32_t		ct_resid;	/* residual length */
+	uint16_t	ct_oxid;
+	uint16_t	ct_scsi_status;	/* modes 0 && 1 only */
+	union {
+		struct {
+			uint32_t	reloff;
+			uint32_t	reserved0;
+			uint32_t	ct_xfrlen;
+			uint32_t	reserved1;
+			ispds64_t	ds;
+		} m0;
+		struct {
+			uint16_t ct_resplen;
+			uint16_t reserved;
+			uint8_t  ct_resp[MAXRESPLEN_24XX];
+		} m1;
+		struct {
+			uint32_t reserved0;
+			uint32_t ct_datalen;
+			uint32_t reserved1;
+			ispds64_t ct_fcp_rsp_iudata;
+		} m2;
+	} rsp;
+} ct7_entry_t;
+
+/*
+ * ct_flags values for CTIO7
+ */
+#define CT7_DATA_IN	0x0002
+#define CT7_DATA_OUT	0x0001
+#define CT7_NO_DATA	0x0000
+#define 	CT7_DATAMASK	0x003
+#define	CT7_DSD_ENABLE	0x0004
+#define	CT7_CONF_STSFD	0x0010
+#define	CT7_EXPLCT_CONF	0x0020
+#define	CT7_FLAG_MODE0	0x0000
+#define	CT7_FLAG_MODE1	0x0040
+#define	CT7_FLAG_MODE7	0x0080
+#define		CT7_FLAG_MMASK	0x00C0
+#define	CT7_FASTPOST	0x0100
+#define	CT7_ATTR_MASK	0x1e00	/* task attributes from atio7 */
+#define	CT7_CONFIRM	0x2000
+#define	CT7_TERMINATE	0x4000
+#define CT7_SENDSTATUS	0x8000
+
+/*
+ * Type 7 CTIO status codes
+ */
+#define CT7_OK		0x01	/* completed without error */
+#define CT7_ABORTED	0x02	/* aborted by host */
+#define CT7_ERR		0x04	/* see sense data for error */
+#define CT7_INVAL	0x06	/* request for disabled lun */
+#define	CT7_INVRXID	0x08	/* (FC only) Invalid RX_ID */
+#define	CT7_DATA_OVER	0x09	/* (FC only) Data Overrun */
+#define CT7_TIMEOUT	0x0B	/* timed out */
+#define CT7_RESET	0x0E	/* LIP Rset Received */
+#define	CT7_BUS_ERROR	0x10	/* DMA PCI Error */
+#define	CT7_REASSY_ERR	0x11	/* DMA reassembly error */
+#define	CT7_DATA_UNDER	0x15	/* (FC only) Data Underrun */
+#define	CT7_PORTUNAVAIL	0x28	/* port not available */
+#define	CT7_LOGOUT	0x29	/* port logout */
+#define	CT7_PORTCHANGED	0x2A	/* port changed */
+#define	CT7_SRR		0x45	/* SRR Received */
+
+/*
+ * Other 24XX related target IOCBs
+ */
+
+/*
+ * ABTS Received
+ */
+typedef struct {
+	isphdr_t	abts_header;
+	uint8_t		abts_reserved0[6];
+	uint16_t	abts_nphdl;
+	uint16_t	abts_reserved1;
+	uint16_t	abts_sof;
+	uint32_t	abts_rxid_abts;
+	uint16_t	abts_did_lo;
+	uint8_t		abts_did_hi;
+	uint8_t		abts_r_ctl;
+	uint16_t	abts_sid_lo;
+	uint8_t		abts_sid_hi;
+	uint8_t		abts_cs_ctl;
+	uint16_t	abts_fs_ctl;
+	uint8_t		abts_f_ctl;
+	uint8_t		abts_type;
+	uint16_t	abts_seq_cnt;
+	uint8_t		abts_df_ctl;
+	uint8_t		abts_seq_id;
+	uint16_t	abts_rx_id;
+	uint16_t	abts_ox_id;
+	uint32_t	abts_param;
+	uint8_t		abts_reserved2[16];
+	uint32_t	abts_rxid_task;
+} abts_t;
+
+typedef struct {
+	isphdr_t	abts_rsp_header;
+	uint32_t	abts_rsp_handle;
+	uint16_t	abts_rsp_status;
+	uint16_t	abts_rsp_nphdl;
+	uint16_t	abts_rsp_ctl_flags;
+	uint16_t	abts_rsp_sof;
+	uint32_t	abts_rsp_rxid_abts;
+	uint16_t	abts_rsp_did_lo;
+	uint8_t		abts_rsp_did_hi;
+	uint8_t		abts_rsp_r_ctl;
+	uint16_t	abts_rsp_sid_lo;
+	uint8_t		abts_rsp_sid_hi;
+	uint8_t		abts_rsp_cs_ctl;
+	uint16_t	abts_rsp_f_ctl_lo;
+	uint8_t		abts_rsp_f_ctl_hi;
+	uint8_t		abts_rsp_type;
+	uint16_t	abts_rsp_seq_cnt;
+	uint8_t		abts_rsp_df_ctl;
+	uint8_t		abts_rsp_seq_id;
+	uint16_t	abts_rsp_rx_id;
+	uint16_t	abts_rsp_ox_id;
+	uint32_t	abts_rsp_param;
+	union {
+		struct {
+			uint16_t reserved;
+			uint8_t	last_seq_id;
+			uint8_t seq_id_valid;
+			uint16_t aborted_rx_id;
+			uint16_t aborted_ox_id;
+			uint16_t high_seq_cnt;
+			uint16_t low_seq_cnt;
+			uint8_t reserved2[4];
+		} ba_acc;
+		struct {
+			uint8_t vendor_unique;
+			uint8_t	explanation;
+			uint8_t reason;
+			uint8_t reserved;
+			uint8_t reserved2[12];
+		} ba_rjt;
+		struct {
+			uint8_t reserved[8];
+			uint32_t subcode1;
+			uint32_t subcode2;
+		} rsp;
+		uint8_t reserved[16];
+	} abts_rsp_payload;
+	uint32_t	abts_rsp_rxid_task;
+} abts_rsp_t;
+
+/* terminate this ABTS exchange */
+#define	ISP24XX_ABTS_RSP_TERMINATE	0x01
+
+#define	ISP24XX_ABTS_RSP_COMPLETE	0x00
+#define	ISP24XX_ABTS_RSP_RESET		0x04
+#define	ISP24XX_ABTS_RSP_ABORTED	0x05
+#define	ISP24XX_ABTS_RSP_TIMEOUT	0x06
+#define	ISP24XX_ABTS_RSP_INVXID		0x08
+#define	ISP24XX_ABTS_RSP_LOGOUT		0x29
+#define	ISP24XX_ABTS_RSP_SUBCODE	0x31
+
 /*
  * Debug macros
  */
@@ -649,6 +890,7 @@ typedef struct {
 #define	ISP_TDQE(isp, msg, idx, arg)	\
     if (isp->isp_dblev & ISP_LOGTDEBUG2) isp_print_qentry(isp, msg, idx, arg)
 
+#ifndef	ISP_TOOLS
 /*
  * The functions below are for the publicly available
  * target mode functions that are internal to the Qlogic driver.
@@ -657,7 +899,7 @@ typedef struct {
 /*
  * This function handles new response queue entry appropriate for target mode.
  */
-int isp_target_notify(ispsoftc_t *, void *, uint16_t *);
+int isp_target_notify(ispsoftc_t *, void *, uint32_t *);
 
 /*
  * This function externalizes the ability to acknowledge an Immediate Notify
@@ -690,7 +932,7 @@ int isp_target_put_atio(ispsoftc_t *, void *);
  * General routine to send a final CTIO for a command- used mostly for
  * local responses.
  */
-int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint16_t);
+int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint32_t);
 #define	ECMD_SVALID	0x100
 
 /*
@@ -699,5 +941,5 @@ int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint16_t);
  * Return nonzero if the interrupt that generated this event has been dismissed.
  */
 int isp_target_async(ispsoftc_t *, int, int);
-
+#endif
 #endif	/* _ISP_TARGET_H */
diff --git a/sys/dev/isp/isp_tpublic.h b/sys/dev/isp/isp_tpublic.h
index d1a0b3d2ca67..519a43b27ae0 100644
--- a/sys/dev/isp/isp_tpublic.h
+++ b/sys/dev/isp/isp_tpublic.h
@@ -71,14 +71,29 @@ typedef enum {
  * in, and the external module to call back with a QIN_HBA_REG that
  * passes back the corresponding information.
  */
-#define    QR_VERSION    10
+#define    QR_VERSION    13
 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;
+    struct {
+        enum {
+            R_FC,
+            R_SCSI
+        } r_type;
+        union {
+            struct {
+                uint64_t    r_wwnn;
+                uint64_t    r_wwpn;
+            } fc;
+            struct {
+                int         r_iid;
+            } scsi;
+        } r_id;
+    } r_info;
+    void *                  r_private;
 } hba_register_t;
 
 /*
@@ -104,7 +119,8 @@ typedef struct tmd_notify {
     uint64_t    nt_iid;         /* inititator id */
     uint64_t    nt_tgt;         /* target id */
     uint16_t    nt_lun;         /* logical unit */
-    uint16_t    nt_padding;     /* padding */
+    uint16_t                : 15,
+                nt_need_ack : 1;    /* this notify needs an ACK */
     uint32_t    nt_tagval;      /* tag value */
     tmd_ncode_t nt_ncode;       /* action */
     void *      nt_lreserved;
@@ -251,7 +267,7 @@ typedef struct {
 #define    TMD_SENSELEN     18
 #endif
 #ifndef    QCDS
-#define    QCDS             8
+#define    QCDS             (sizeof (void *))
 #endif
 
 typedef struct tmd_cmd {
@@ -279,7 +295,7 @@ typedef struct tmd_cmd {
         uint32_t        longs[QCDS / sizeof (uint32_t)];
         uint16_t        shorts[QCDS / sizeof (uint16_t)];
         uint8_t         bytes[QCDS];
-    } cd_lreserved[3], cd_hreserved[3];
+    } cd_lreserved[4], cd_hreserved[4];
 } tmd_cmd_t;
 
 /* defined tags */
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index 2ef8d51e42d7..a4461c724066 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -44,7 +44,7 @@
 #define MBOX_ABOUT_FIRMWARE		0x0008
 					/*   9 */
 					/*   a */
-					/*   b */
+#define	MBOX_LOAD_RISC_RAM		0x000b
 					/*   c */
 #define MBOX_WRITE_RAM_WORD_EXTENDED	0x000d
 #define MBOX_CHECK_FIRMWARE		0x000e
@@ -123,6 +123,7 @@
 #define	MBOX_GET_FIRMWARE_OPTIONS	0x0028
 #define	MBOX_SET_FIRMWARE_OPTIONS	0x0038
 #define	MBOX_GET_RESOURCE_COUNT		0x0042
+#define	MBOX_REQUEST_OFFLINE_MODE	0x0043
 #define	MBOX_ENHANCED_GET_PDB		0x0047
 #define	MBOX_EXEC_COMMAND_IOCB_A64	0x0054
 #define	MBOX_INIT_FIRMWARE		0x0060
@@ -148,12 +149,14 @@
 #define	MBOX_DRIVER_HEARTBEAT		0x005B
 #define	MBOX_FW_HEARTBEAT		0x005C
 
-#define	MBOX_GET_SET_DATA_RATE		0x005D	/* 23XX only */
-#define		MBGSD_GET_RATE	0
-#define		MBGSD_SET_RATE	1
+#define	MBOX_GET_SET_DATA_RATE		0x005D	/* 24XX/23XX only */
+#define		MBGSD_GET_RATE		0
+#define		MBGSD_SET_RATE		1
+#define		MBGSD_SET_RATE_NOW	2	/* 24XX only */
 #define		MBGSD_ONEGB	0
 #define		MBGSD_TWOGB	1
 #define		MBGSD_AUTO	2
+#define		MBGSD_FOURGB	3		/* 24XX only */
 
 
 #define	ISP2100_SET_PCI_PARAM		0x00ff
@@ -173,6 +176,10 @@
 #define	MBOX_LOOP_ID_USED		0x4008
 #define	MBOX_ALL_IDS_USED		0x4009
 #define	MBOX_NOT_LOGGED_IN		0x400A
+/* pseudo mailbox completion codes */
+#define	MBOX_REGS_BUSY			0x6000	/* registers in use */
+#define	MBOX_TIMEOUT			0x6001	/* command timed out */
+
 #define	MBLOGALL			0x000f
 #define	MBLOGNONE			0x0000
 #define	MBLOGMASK(x)			((x) & 0xf)
@@ -199,6 +206,8 @@
 #define	ASYNC_PDB_CHANGED		0x8014
 #define	ASYNC_CHANGE_NOTIFY		0x8015
 #define	ASYNC_LIP_F8			0x8016
+#define	ASYNC_LIP_ERROR			0x8017
+#define	ASYNC_SECURITY_UPDATE		0x801B
 #define	ASYNC_CMD_CMPLT			0x8020
 #define	ASYNC_CTIO_DONE			0x8021
 #define	ASYNC_IP_XMIT_DONE		0x8022
@@ -221,6 +230,8 @@
 #define		ISP_CONN_LOOPBACK	5
 #define	ASYNC_RIO_RESP			0x8040
 #define	ASYNC_RIO_COMP			0x8042
+#define	ASYNC_RCV_ERR			0x8048
+
 /*
  * 2.01.31 2200 Only. Need Bit 13 in Mailbox 1 for Set Firmware Options
  * mailbox command to enable this.
@@ -228,20 +239,14 @@
 #define	ASYNC_QFULL_SENT		0x8049
 
 /*
- * Mailbox Usages
+ * 24XX only
  */
+#define	ASYNC_RJT_SENT			0x8049
 
-#define	WRITE_REQUEST_QUEUE_IN_POINTER(isp, value)	\
-	ISP_WRITE(isp, isp->isp_rqstinrp, value)
-
-#define	READ_REQUEST_QUEUE_OUT_POINTER(isp)		\
-	ISP_READ(isp, isp->isp_rqstoutrp)
-
-#define	READ_RESPONSE_QUEUE_IN_POINTER(isp)		\
-	ISP_READ(isp, isp->isp_respinrp)
-
-#define	WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, value)	\
-	ISP_WRITE(isp, isp->isp_respoutrp, value)
+/*
+ * All IOCB Queue entries are this size
+ */
+#define	QENTRY_LEN			64
 
 /*
  * Command Structure Definitions
@@ -288,6 +293,7 @@ typedef struct {
 #define	RQSFLAG_FULL		0x02
 #define	RQSFLAG_BADHEADER	0x04
 #define	RQSFLAG_BADPACKET	0x08
+#define	RQSFLAG_MASK		0x0f
 
 /* RQS entry_type definitions */
 #define	RQSTYPE_REQUEST		0x01
@@ -307,11 +313,13 @@ typedef struct {
 #define	RQSTYPE_CTIO1		0x0f	/* Target Mode */
 #define	RQSTYPE_STATUS_CONT	0x10
 #define	RQSTYPE_T2RQS		0x11
+#define	RQSTYPE_CTIO7		0x12
 #define	RQSTYPE_IP_XMIT		0x13
+#define	RQSTYPE_TSK_MGMT	0x14
 #define	RQSTYPE_T4RQS		0x15
 #define	RQSTYPE_ATIO2		0x16	/* Target Mode */
 #define	RQSTYPE_CTIO2		0x17	/* Target Mode */
-#define	RQSTYPE_CSET0		0x18
+#define	RQSTYPE_T7RQS		0x18
 #define	RQSTYPE_T3RQS		0x19
 #define	RQSTYPE_IP_XMIT_64	0x1b
 #define	RQSTYPE_CTIO4		0x1e	/* Target Mode */
@@ -320,6 +328,12 @@ typedef struct {
 #define	RQSTYPE_RIO2		0x22
 #define	RQSTYPE_IP_RECV		0x23
 #define	RQSTYPE_IP_RECV_CONT	0x24
+#define	RQSTYPE_CT_PASSTHRU	0x29
+#define	RQSTYPE_ABORT_IO	0x33
+#define	RQSTYPE_T6RQS		0x48
+#define	RQSTYPE_LOGIN		0x52
+#define	RQSTYPE_ABTS_RCVD	0x54	/* 24XX only */
+#define	RQSTYPE_ABTS_RSP	0x55	/* 24XX only */
 
 
 #define	ISP_RQDSEG	4
@@ -329,7 +343,6 @@ typedef struct {
 	uint8_t		req_lun_trn;
 	uint8_t		req_target;
 	uint16_t	req_cdblen;
-#define	req_modifier	req_cdblen	/* marker packet */
 	uint16_t	req_flags;
 	uint16_t	req_reserved;
 	uint16_t	req_time;
@@ -337,13 +350,33 @@ typedef struct {
 	uint8_t		req_cdb[12];
 	ispds_t		req_dataseg[ISP_RQDSEG];
 } ispreq_t;
-
-#define	ispreq64_t	ispreqt3_t	/* same as.... */
 #define	ISP_RQDSEG_A64	2
 
-/*
- * A request packet can also be a marker packet.
- */
+typedef struct {
+	isphdr_t	mrk_header;
+	uint32_t	mrk_handle;
+	uint8_t		mrk_reserved0;
+	uint8_t		mrk_target;
+	uint16_t	mrk_modifier;
+	uint16_t	mrk_flags;
+	uint16_t	mrk_lun;
+	uint8_t		mrk_reserved1[48];
+} isp_marker_t;
+	
+typedef struct {
+	isphdr_t	mrk_header;
+	uint32_t	mrk_handle;
+	uint16_t	mrk_nphdl;
+	uint8_t		mrk_modifier;
+	uint8_t		mrk_reserved0;
+	uint8_t		mrk_reserved1;
+	uint8_t		mrk_vphdl;
+	uint16_t	mrk_reserved2;
+	uint8_t		mrk_lun[8];
+	uint8_t		mrk_reserved3[40];
+} isp_marker_24xx_t;
+	
+
 #define SYNC_DEVICE	0
 #define SYNC_TARGET	1
 #define SYNC_ALL	2
@@ -357,7 +390,7 @@ typedef struct {
 	uint8_t		req_target;
 	uint16_t	req_scclun;
 	uint16_t	req_flags;
-	uint16_t	_res2;
+	uint16_t	req_reserved;
 	uint16_t	req_time;
 	uint16_t	req_seg_count;
 	uint8_t		req_cdb[16];
@@ -371,7 +404,7 @@ typedef struct {
 	uint16_t	req_target;
 	uint16_t	req_scclun;
 	uint16_t	req_flags;
-	uint16_t	_res2;
+	uint16_t	req_reserved;
 	uint16_t	req_time;
 	uint16_t	req_seg_count;
 	uint8_t		req_cdb[16];
@@ -387,13 +420,14 @@ typedef struct {
 	uint8_t		req_target;
 	uint16_t	req_scclun;
 	uint16_t	req_flags;
-	uint16_t	_res2;
+	uint16_t	req_reserved;
 	uint16_t	req_time;
 	uint16_t	req_seg_count;
 	uint8_t		req_cdb[16];
 	uint32_t	req_totalcnt;
 	ispds64_t	req_dataseg[ISP_RQDSEG_T3];
 } ispreqt3_t;
+#define	ispreq64_t	ispreqt3_t	/* same as.... */
 
 typedef struct {
 	isphdr_t	req_header;
@@ -401,7 +435,7 @@ typedef struct {
 	uint16_t	req_target;
 	uint16_t	req_scclun;
 	uint16_t	req_flags;
-	uint16_t	_res2;
+	uint16_t	req_reserved;
 	uint16_t	req_time;
 	uint16_t	req_seg_count;
 	uint8_t		req_cdb[16];
@@ -437,16 +471,86 @@ typedef struct {
 	uint8_t		req_target;
 	uint16_t	req_cdblen;
 	uint16_t	req_flags;
-	uint16_t	_res1;
+	uint16_t	req_reserved;
 	uint16_t	req_time;
 	uint16_t	req_seg_count;
 	uint8_t		req_cdb[44];
 } ispextreq_t;
 
+/* 24XX only */
+typedef struct {
+	uint16_t	fcd_length;
+	uint16_t	fcd_a1500;
+	uint16_t	fcd_a3116;
+	uint16_t	fcd_a4732;
+	uint16_t	fcd_a6348;
+} fcp_cmnd_ds_t;
+
+typedef struct {
+	isphdr_t	req_header;
+	uint32_t	req_handle;
+	uint16_t	req_nphdl;
+	uint16_t	req_time;
+	uint16_t	req_seg_count;
+	uint16_t	req_fc_rsp_dsd_length;
+	uint8_t		req_lun[8];
+	uint16_t	req_flags;
+	uint16_t	req_fc_cmnd_dsd_length;
+	uint16_t	req_fc_cmnd_dsd_a1500;
+	uint16_t	req_fc_cmnd_dsd_a3116;
+	uint16_t	req_fc_cmnd_dsd_a4732;
+	uint16_t	req_fc_cmnd_dsd_a6348;
+	uint16_t	req_fc_rsp_dsd_a1500;
+	uint16_t	req_fc_rsp_dsd_a3116;
+	uint16_t	req_fc_rsp_dsd_a4732;
+	uint16_t	req_fc_rsp_dsd_a6348;
+	uint32_t	req_totalcnt;
+	uint16_t	req_tidlo;
+	uint8_t		req_tidhi;
+	uint8_t		req_vpidx;
+	ispds64_t	req_dataseg;
+} ispreqt6_t;
+
+typedef struct {
+	isphdr_t	req_header;
+	uint32_t	req_handle;
+	uint16_t	req_nphdl;
+	uint16_t	req_time;
+	uint16_t	req_seg_count;
+	uint16_t	req_reserved;
+	uint8_t		req_lun[8];
+	uint8_t		req_alen_datadir;
+	uint8_t		req_task_management;
+	uint8_t		req_task_attribute;
+	uint8_t		req_crn;
+	uint8_t		req_cdb[16];
+	uint32_t	req_dl;
+	uint16_t	req_tidlo;
+	uint8_t		req_tidhi;
+	uint8_t		req_vpidx;
+	ispds64_t	req_dataseg;
+} ispreqt7_t;
+
+/* I/O Abort Structure */
+typedef struct {
+	isphdr_t	abrt_header;
+	uint32_t	abrt_handle;
+	uint16_t	abrt_nphdl;
+	uint16_t	abrt_options;
+	uint32_t	abrt_cmd_handle;
+	uint8_t		abrt_reserved[32];
+	uint16_t	abrt_tidlo;
+	uint8_t		abrt_tidhi;
+	uint8_t		abrt_vpidx;
+	uint8_t		abrt_reserved1[12];
+} isp24xx_abrt_t;
+#define	ISP24XX_ABRT_NO_ABTS	0x01	/* don't actually send an ABTS */
+#define	ISP24XX_ABRT_ENXIO	0x31	/* in nphdl on return */
+
 #define	ISP_CDSEG	7
 typedef struct {
 	isphdr_t	req_header;
-	uint32_t	_res1;
+	uint32_t	req_reserved;
 	ispds_t		req_dataseg[ISP_CDSEG];
 } ispcontreq_t;
 
@@ -471,11 +575,33 @@ typedef struct {
 	uint8_t		req_sense_data[32];
 } ispstatusreq_t;
 
+/*
+ * Status Continuation
+ */
 typedef struct {
 	isphdr_t	req_header;
 	uint8_t		req_sense_data[60];
 } ispstatus_cont_t;
 
+/*
+ * 24XX Type 0 status
+ */
+typedef struct {
+	isphdr_t	req_header;
+	uint32_t	req_handle;
+	uint16_t	req_completion_status;
+	uint16_t	req_oxid;
+	uint32_t	req_resid;
+	uint16_t	req_reserved0;
+	uint16_t	req_state_flags;
+	uint16_t	req_reserved1;
+	uint16_t	req_scsi_status;
+	uint32_t	req_fcp_residual;
+	uint32_t	req_sense_len;
+	uint32_t	req_response_len;
+	uint8_t		req_rsp_sense[28];
+} isp24xx_statusreq_t;
+
 /* 
  * For Qlogic 2X00, the high order byte of SCSI status has
  * additional meaning.
@@ -486,6 +612,25 @@ typedef struct {
 #define	RQCS_SV	0x200	/* Sense Length Valid */
 #define	RQCS_RV	0x100	/* FCP Response Length Valid */
 
+/*
+ * CT Passthru IOCB
+ */
+typedef struct {
+	isphdr_t	ctp_header;
+	uint32_t	ctp_handle;
+	uint16_t	ctp_status;
+	uint16_t	ctp_nphdl;	/* n-port handle */
+	uint16_t	ctp_cmd_cnt;	/* Command DSD count */
+	uint16_t	ctp_vpidx;	/* low 8 bits */
+	uint16_t	ctp_time;
+	uint16_t	ctp_reserved0;
+	uint16_t	ctp_rsp_cnt;	/* Response DSD count */
+	uint16_t	ctp_reserved1[5];
+	uint32_t	ctp_rsp_bcnt;	/* Response byte count */
+	uint32_t	ctp_cmd_bcnt;	/* Command byte count */
+	ispds64_t	ctp_dataseg[2];
+} isp_ct_pt_t;
+
 /* 
  * Completion Status Codes.
  */
@@ -530,6 +675,13 @@ typedef struct {
 #define	RQCS_PORT_CHANGED		0x002A
 #define	RQCS_PORT_BUSY			0x002B
 
+/* 24XX Only Completion Codes */
+#define	RQCS_24XX_DRE			0x0011	/* data reassembly error */
+#define	RQCS_24XX_TABORT		0x0013	/* aborted by target */
+#define	RQCS_24XX_ENOMEM		0x002C	/* f/w resource unavailable */
+#define	RQCS_24XX_TMO			0x0030	/* task management overrun */
+
+
 /*
  * 1X00 specific State Flags 
  */
@@ -587,6 +739,7 @@ typedef struct {
 
 /*
  * About Firmware returns an 'attribute' word in mailbox 6.
+ * These attributes are for 2200 and 2300.
  */
 #define	ISP_FW_ATTR_TMODE	0x01
 #define	ISP_FW_ATTR_SCCLUN	0x02
@@ -598,8 +751,14 @@ typedef struct {
 #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))
+/* and these are for the 2400 */
+#define	ISP2400_FW_ATTR_CLASS2	(1 << 0)
+#define	ISP2400_FW_ATTR_IP	(1 << 1)
+#define	ISP2400_FW_ATTR_MULTIID	(1 << 2)
+#define	ISP2400_FW_ATTR_SB2	(1 << 3)
+#define	ISP2400_FW_ATTR_T10CRC	(1 << 4)
+#define	ISP2400_FW_ATTR_VI	(1 << 5)
+#define	ISP2400_FW_ATTR_EXPFW	(1 << 13)
 
 /*
  * Reduced Interrupt Operation Response Queue Entreis
@@ -616,7 +775,7 @@ typedef struct {
 } isp_rio2_t;
 
 /*
- * FC (ISP2100) specific data structures
+ * FC (ISP2100/ISP2200/ISP2300/ISP2400) specific data structures
  */
 
 /*
@@ -624,9 +783,9 @@ typedef struct {
  *
  * Version One (prime) format.
  */
-typedef struct isp_icb {
+typedef struct {
 	uint8_t		icb_version;
-	uint8_t		_reserved0;
+	uint8_t		icb_reserved0;
 	uint16_t	icb_fwoptions;
 	uint16_t	icb_maxfrmlen;
 	uint16_t	icb_maxalloc;
@@ -648,42 +807,48 @@ typedef struct isp_icb {
 	uint8_t		icb_ccnt;
 	uint8_t		icb_icnt;
 	uint16_t	icb_lunetimeout;
-	uint16_t	_reserved1;
+	uint16_t	icb_reserved1;
 	uint16_t	icb_xfwoptions;
 	uint8_t		icb_racctimer;
 	uint8_t		icb_idelaytimer;
 	uint16_t	icb_zfwoptions;
-	uint16_t	_reserved2[13];
+	uint16_t	icb_reserved2[13];
 } isp_icb_t;
+
 #define	ICB_VERSION1	1
 
-#define	ICBOPT_HARD_ADDRESS	0x0001
-#define	ICBOPT_FAIRNESS		0x0002
-#define	ICBOPT_FULL_DUPLEX	0x0004
-#define	ICBOPT_FAST_POST	0x0008
-#define	ICBOPT_TGT_ENABLE	0x0010
-#define	ICBOPT_INI_DISABLE	0x0020
-#define	ICBOPT_INI_ADISC	0x0040
-#define	ICBOPT_INI_TGTTYPE	0x0080
-#define	ICBOPT_PDBCHANGE_AE	0x0100
-#define	ICBOPT_NOLIP		0x0200
-#define	ICBOPT_SRCHDOWN		0x0400
-#define	ICBOPT_PREVLOOP		0x0800
-#define	ICBOPT_STOP_ON_QFULL	0x1000
-#define	ICBOPT_FULL_LOGIN	0x2000
-#define	ICBOPT_BOTH_WWNS	0x4000
 #define	ICBOPT_EXTENDED		0x8000
+#define	ICBOPT_BOTH_WWNS	0x4000
+#define	ICBOPT_FULL_LOGIN	0x2000
+#define	ICBOPT_STOP_ON_QFULL	0x1000	/* 2200/2100 only */
+#define	ICBOPT_PREVLOOP		0x0800
+#define	ICBOPT_SRCHDOWN		0x0400
+#define	ICBOPT_NOLIP		0x0200
+#define	ICBOPT_PDBCHANGE_AE	0x0100
+#define	ICBOPT_INI_TGTTYPE	0x0080
+#define	ICBOPT_INI_ADISC	0x0040
+#define	ICBOPT_INI_DISABLE	0x0020
+#define	ICBOPT_TGT_ENABLE	0x0010
+#define	ICBOPT_FAST_POST	0x0008
+#define	ICBOPT_FULL_DUPLEX	0x0004
+#define	ICBOPT_FAIRNESS		0x0002
+#define	ICBOPT_HARD_ADDRESS	0x0001
 
+#define	ICBXOPT_NO_LOGOUT	0x8000	/* no logout on link failure */
+#define	ICBXOPT_FCTAPE_CCQ	0x4000	/* FC-Tape Command Queueing */
+#define	ICBXOPT_FCTAPE_CONFIRM	0x2000
+#define	ICBXOPT_FCTAPE		0x1000
 #define	ICBXOPT_CLASS2_ACK0	0x0200
 #define	ICBXOPT_CLASS2		0x0100
-#define	ICBXOPT_LOOP_ONLY	(0 << 4)
-#define	ICBXOPT_PTP_ONLY	(1 << 4)
-#define	ICBXOPT_LOOP_2_PTP	(2 << 4)
-#define	ICBXOPT_PTP_2_LOOP	(3 << 4)
-
+#define	ICBXOPT_NO_PLAY		0x0080	/* don't play if can't get hard addr */
+#define	ICBXOPT_TOPO_MASK	0x0070
+#define	ICBXOPT_LOOP_ONLY	0x0000
+#define	ICBXOPT_PTP_ONLY	0x0010
+#define	ICBXOPT_LOOP_2_PTP	0x0020
+#define	ICBXOPT_PTP_2_LOOP	0x0030
 /*
  * The lower 4 bits of the xfwoptions field are the OPERATION MODE bits.
- * RIO is not defined for the 23XX cards
+ * RIO is not defined for the 23XX cards (just 2200)
  */
 #define	ICBXOPT_RIO_OFF		0
 #define	ICBXOPT_RIO_16BIT	1
@@ -693,14 +858,60 @@ typedef struct isp_icb {
 #define	ICBXOPT_ZIO		5	
 #define	ICBXOPT_TIMER_MASK	0x7
 
-#define	ICBZOPT_ENA_RDXFR_RDY	0x01
-#define	ICBZOPT_ENA_OOF		(1 << 6) /* out of order frame handling */
-#define	ICBZOPT_50_OHM		0x0200
-/* These 3 only apply to the 2300 */
-#define	ICBZOPT_RATE_ONEGB	(MBGSD_ONEGB << 14)
-#define	ICBZOPT_RATE_TWOGB	(MBGSD_TWOGB << 14)
-#define	ICBZOPT_RATE_AUTO	(MBGSD_AUTO << 14)
+#define	ICBZOPT_RATE_MASK	0xC000
+#define	ICBZOPT_RATE_ONEGB	0x0000
+#define	ICBZOPT_RATE_AUTO	0x8000
+#define	ICBZOPT_RATE_TWOGB	0x4000
+#define	ICBZOPT_50_OHM		0x2000
+#define	ICBZOPT_ENA_OOF		0x0040	/* out of order frame handling */
+#define	ICBZOPT_RSPSZ_MASK	0x0030
+#define	ICBZOPT_RSPSZ_24	0x0000
+#define	ICBZOPT_RSPSZ_12	0x0010
+#define	ICBZOPT_RSPSZ_24A	0x0020
+#define	ICBZOPT_RSPSZ_32	0x0030
+#define	ICBZOPT_SOFTID		0x0002
+#define	ICBZOPT_ENA_RDXFR_RDY	0x0001
 
+/* 2400 F/W options */
+#define	ICB2400_OPT1_BOTH_WWNS		0x00004000
+#define	ICB2400_OPT1_FULL_LOGIN		0x00002000
+#define	ICB2400_OPT1_PREVLOOP		0x00000800
+#define	ICB2400_OPT1_SRCHDOWN		0x00000400
+#define	ICB2400_OPT1_NOLIP		0x00000200
+#define	ICB2400_OPT1_INI_DISABLE	0x00000020
+#define	ICB2400_OPT1_TGT_ENABLE		0x00000010
+#define	ICB2400_OPT1_FULL_DUPLEX	0x00000004
+#define	ICB2400_OPT1_FAIRNESS		0x00000002
+#define	ICB2400_OPT1_HARD_ADDRESS	0x00000001
+
+#define	ICB2400_OPT2_FCTAPE		0x00001000
+#define	ICB2400_OPT2_CLASS2_ACK0	0x00000200
+#define	ICB2400_OPT2_CLASS2		0x00000100
+#define	ICB2400_OPT2_NO_PLAY		0x00000080
+#define	ICB2400_OPT2_TOPO_MASK		0x00000070
+#define	ICB2400_OPT2_LOOP_ONLY		0x00000000
+#define	ICB2400_OPT2_PTP_ONLY		0x00000010
+#define	ICB2400_OPT2_LOOP_2_PTP		0x00000020
+#define	ICB2400_OPT2_PTP_2_LOOP		0x00000030
+#define	ICB2400_OPT2_TIMER_MASK		0x00000007
+#define	ICB2400_OPT2_ZIO		0x00000005
+#define	ICB2400_OPT2_ZIO1		0x00000006
+
+#define	ICB2400_OPT3_75_OHM		0x00010000
+#define	ICB2400_OPT3_RATE_MASK		0x0000E000
+#define	ICB2400_OPT3_RATE_ONEGB		0x00000000
+#define	ICB2400_OPT3_RATE_TWOGB		0x00002000
+#define ICB2400_OPT3_RATE_AUTO		0x00004000
+#define	ICB2400_OPT3_RATE_FOURGB	0x00006000
+#define	ICB2400_OPT3_ENA_OOF_XFRDY	0x00000200
+#define	ICB2400_OPT3_NO_LOCAL_PLOGI	0x00000080
+#define	ICB2400_OPT3_ENA_OOF		0x00000040
+/* note that a response size flag of zero is reserved! */
+#define	ICB2400_OPT3_RSPSZ_MASK		0x00000030
+#define	ICB2400_OPT3_RSPSZ_12		0x00000010
+#define	ICB2400_OPT3_RSPSZ_24		0x00000020
+#define	ICB2400_OPT3_RSPSZ_32		0x00000030
+#define	ICB2400_OPT3_SOFTID		0x00000002
 
 #define	ICB_MIN_FRMLEN		256
 #define	ICB_MAX_FRMLEN		2112
@@ -714,6 +925,41 @@ typedef struct isp_icb {
 #define	ICB_LUN_ENABLE_TOV	180
 
 
+/*
+ * And somebody at QLogic had a great idea that you could just change
+ * the structure *and* keep the version number the same as the other cards.
+ */
+typedef struct {
+	uint16_t	icb_version;
+	uint16_t	icb_reserved0;
+	uint16_t	icb_maxfrmlen;
+	uint16_t	icb_execthrottle;
+	uint16_t	icb_xchgcnt;
+	uint16_t	icb_hardaddr;
+	uint8_t		icb_portname[8];
+	uint8_t		icb_nodename[8];
+	uint16_t	icb_rspnsin;
+	uint16_t	icb_rqstout;
+	uint16_t	icb_retry_count;
+	uint16_t	icb_priout;
+	uint16_t	icb_rsltqlen;
+	uint16_t	icb_rqstqlen;
+	uint16_t	icb_ldn_nols;
+	uint16_t	icb_prqstqlen;
+	uint16_t	icb_rqstaddr[4];
+	uint16_t	icb_respaddr[4];
+	uint16_t	icb_priaddr[4];	
+	uint16_t	icb_reserved1[4];
+	uint16_t	icb_atio_in;
+	uint16_t	icb_atioqlen;
+	uint16_t	icb_atioqaddr[4];
+	uint16_t	icb_idelaytimer;
+	uint16_t	icb_logintime;
+	uint32_t	icb_fwoptions1;
+	uint32_t	icb_fwoptions2;
+	uint32_t	icb_fwoptions3;
+	uint16_t	icb_reserved2[12];
+} isp_icb_2400_t;
 
 #define	RQRSP_ADDR0015	0
 #define	RQRSP_ADDR1631	1
@@ -750,22 +996,6 @@ typedef struct isp_icb {
 		((uint64_t) array[ICB_NNM6] << 48) | \
 		((uint64_t) array[ICB_NNM7] << 56)
 
-/*
- * FC-AL Position Map
- *
- * This is an at most 128 byte map that returns either
- * the LILP or Firmware generated list of ports.
- *
- * We deviate a bit from the returned qlogic format to
- * use an extra bit to say whether this was a LILP or
- * f/w generated map.
- */
-typedef struct {
-	uint8_t		fwmap	: 1,
-			count	: 7;
-	uint8_t		map[127];
-} fcpos_map_t;
-
 /*
  * Port Data Base Element
  */
@@ -774,7 +1004,6 @@ typedef struct {
 	uint16_t	pdb_options;
 	uint8_t		pdb_mstate;
 	uint8_t		pdb_sstate;
-#define	BITS2WORD(x)	((x)[0] << 16 | (x)[3] << 8 | (x)[2])
 	uint8_t		pdb_hardaddr_bits[4];
 	uint8_t		pdb_portid_bits[4];
 	uint8_t		pdb_nodename[8];
@@ -810,7 +1039,7 @@ typedef struct {
 	uint16_t	pdb_loopid;
 	uint16_t	pdb_il_ptr;
 	uint16_t	pdb_sl_ptr;
-} isp_pdb_t;
+} isp_pdb_21xx_t;
 
 #define	PDB_OPTIONS_XMITTING	(1<<11)
 #define	PDB_OPTIONS_LNKXMIT	(1<<10)
@@ -835,35 +1064,109 @@ typedef struct {
 #define			SVC3_ROLE_MASK	0x30
 #define			SVC3_ROLE_SHIFT	4
 
+#define	BITS2WORD(x)		((x)[0] << 16 | (x)[3] << 8 | (x)[2])
+#define	BITS2WORD_24XX(x)	((x)[0] << 16 | (x)[1] << 8 | (x)[2])
+
 /*
- * CT definition
- *
- * This is as the QLogic f/w documentations defines it- which is just opposite,
- * bit wise, from what the specification defines it as. Additionally, the
- * ct_response and ct_resid (really from FC-GS-2) need to be byte swapped.
+ * Port Data Base Element- 24XX cards
  */
-
 typedef struct {
-	uint8_t		ct_revision;
-	uint8_t		ct_portid[3];
-	uint8_t		ct_fcs_type;
-	uint8_t		ct_fcs_subtype;
-	uint8_t		ct_options;
-	uint8_t		ct_res0;
-	uint16_t	ct_response;
-	uint16_t	ct_resid;
-	uint8_t		ct_res1;
-	uint8_t		ct_reason;
-	uint8_t		ct_explanation;
-	uint8_t		ct_vunique;
-} ct_hdr_t;
-#define	FS_ACC	0x8002
-#define	FS_RJT	0x8001
+	uint16_t	pdb_flags;
+	uint8_t		pdb_curstate;
+	uint8_t		pdb_laststate;
+	uint8_t		pdb_hardaddr_bits[4];
+	uint8_t		pdb_portid_bits[4];
+#define		pdb_nxt_seqid_2400	pdb_portid_bits[3]
+	uint16_t	pdb_retry_timer;
+	uint16_t	pdb_handle;
+	uint16_t	pdb_rcv_dsize;
+	uint16_t	pdb_reserved0;
+	uint16_t	pdb_prli_svc0;
+	uint16_t	pdb_prli_svc3;
+	uint8_t		pdb_portname[8];
+	uint8_t		pdb_nodename[8];
+	uint8_t		pdb_reserved1[24];
+} isp_pdb_24xx_t;
 
-#define	FC4_IP		5 /* ISO/EEC 8802-2 LLC/SNAP "Out of Order Delivery" */
-#define	FC4_SCSI	8 /* SCSI-3 via Fivre Channel Protocol (FCP) */
-#define	FC4_FC_SVC	0x20	/* Fibre Channel Services */
+#define	PDB2400_TID_SUPPORTED	0x4000
+#define	PDB2400_FC_TAPE		0x0080
+#define	PDB2400_CLASS2_ACK0	0x0040
+#define	PDB2400_FCP_CONF	0x0020
+#define	PDB2400_CLASS2		0x0010
+#define	PDB2400_ADDR_VALID	0x0002
 
+/*
+ * Common elements from the above two structures that are actually useful to us.
+ */
+typedef struct {
+	uint16_t	handle;
+	uint16_t	reserved;
+	uint32_t	s3_role	: 8,
+			portid	: 24;
+	uint8_t		portname[8];
+	uint8_t		nodename[8];
+} isp_pdb_t;
+
+/*
+ * ISP24XX- Login/Logout Port IOCB
+ */
+typedef struct {
+	isphdr_t	plogx_header;
+	uint32_t	plogx_handle;
+	uint16_t	plogx_status;
+	uint16_t	plogx_nphdl;
+	uint16_t	plogx_flags;
+	uint16_t	plogx_vphdl;		/* low 8 bits */
+	uint16_t	plogx_portlo;		/* low 16 bits */
+	uint16_t	plogx_rspsz_porthi;
+	struct {
+		uint16_t	lo16;
+		uint16_t	hi16;
+	} plogx_ioparm[11];
+} isp_plogx_t;
+
+#define	PLOGX_STATUS_OK		0x00
+#define	PLOGX_STATUS_UNAVAIL	0x28
+#define	PLOGX_STATUS_LOGOUT	0x29
+#define	PLOGX_STATUS_IOCBERR	0x31
+
+#define	PLOGX_IOCBERR_NOLINK	0x01
+#define	PLOGX_IOCBERR_NOIOCB	0x02
+#define	PLOGX_IOCBERR_NOXGHG	0x03
+#define	PLOGX_IOCBERR_FAILED	0x04	/* further info in IOPARM 1 */
+#define	PLOGX_IOCBERR_NOFABRIC	0x05
+#define	PLOGX_IOCBERR_NOTREADY	0x07
+#define	PLOGX_IOCBERR_NOLOGIN	0x08	/* further info in IOPARM 1 */
+#define	PLOGX_IOCBERR_NOPCB	0x0a
+#define	PLOGX_IOCBERR_REJECT	0x18	/* further info in IOPARM 1 */
+#define	PLOGX_IOCBERR_EINVAL	0x19	/* further info in IOPARM 1 */
+#define	PLOGX_IOCBERR_PORTUSED	0x1a	/* further info in IOPARM 1 */
+#define	PLOGX_IOCBERR_HNDLUSED	0x1b	/* further info in IOPARM 1 */
+#define	PLOGX_IOCBERR_NOHANDLE	0x1c
+#define	PLOGX_IOCBERR_NOFLOGI	0x1f	/* further info in IOPARM 1 */
+
+#define	PLOGX_FLG_CMD_MASK	0xf
+#define	PLOGX_FLG_CMD_PLOGI	0
+#define	PLOGX_FLG_CMD_PRLI	1
+#define	PLOGX_FLG_CMD_PDISC	2
+#define	PLOGX_FLG_CMD_LOGO	8
+#define	PLOGX_FLG_CMD_PRLO	9
+#define	PLOGX_FLG_CMD_TPRLO	10
+
+#define	PLOGX_FLG_COND_PLOGI		0x10	/* if with PLOGI */
+#define	PLOGX_FLG_IMPLICIT		0x10	/* if with LOGO, PRLO, TPRLO */
+#define	PLOGX_FLG_SKIP_PRLI		0x20	/* if with PLOGI */
+#define	PLOGX_FLG_IMPLICIT_LOGO_ALL	0x20	/* if with LOGO */
+#define	PLOGX_FLG_EXPLICIT_LOGO		0x40	/* if with LOGO */
+#define	PLOGX_FLG_COMMON_FEATURES	0x80	/* if with PLOGI */
+#define	PLOGX_FLG_FREE_NPHDL		0x80	/* if with with LOGO */
+
+#define	PLOGX_FLG_CLASS2		0x100	/* if with PLOGI */
+#define	PLOGX_FLG_FCP2_OVERRIDE		0x200	/* if with PRLOG, PRLI */
+
+/*
+ * Simple Name Server Data Structures
+ */
 #define	SNS_GA_NXT	0x100
 #define	SNS_GPN_ID	0x112
 #define	SNS_GNN_ID	0x113
@@ -872,61 +1175,61 @@ typedef struct {
 #define	SNS_RFT_ID	0x217
 typedef struct {
 	uint16_t	snscb_rblen;	/* response buffer length (words) */
-	uint16_t	snscb_res0;
+	uint16_t	snscb_reserved0;
 	uint16_t	snscb_addr[4];	/* response buffer address */
 	uint16_t	snscb_sblen;	/* subcommand buffer length (words) */
-	uint16_t	snscb_res1;
+	uint16_t	snscb_reserved1;
 	uint16_t	snscb_data[1];	/* variable data */
 } sns_screq_t;	/* Subcommand Request Structure */
 
 typedef struct {
 	uint16_t	snscb_rblen;	/* response buffer length (words) */
-	uint16_t	snscb_res0;
+	uint16_t	snscb_reserved0;
 	uint16_t	snscb_addr[4];	/* response buffer address */
 	uint16_t	snscb_sblen;	/* subcommand buffer length (words) */
-	uint16_t	snscb_res1;
+	uint16_t	snscb_reserved1;
 	uint16_t	snscb_cmd;
-	uint16_t	snscb_res2;
-	uint32_t	snscb_res3;
+	uint16_t	snscb_reserved2;
+	uint32_t	snscb_reserved3;
 	uint32_t	snscb_port;
 } sns_ga_nxt_req_t;
 #define	SNS_GA_NXT_REQ_SIZE	(sizeof (sns_ga_nxt_req_t))
 
 typedef struct {
 	uint16_t	snscb_rblen;	/* response buffer length (words) */
-	uint16_t	snscb_res0;
+	uint16_t	snscb_reserved0;
 	uint16_t	snscb_addr[4];	/* response buffer address */
 	uint16_t	snscb_sblen;	/* subcommand buffer length (words) */
-	uint16_t	snscb_res1;
+	uint16_t	snscb_reserved1;
 	uint16_t	snscb_cmd;
-	uint16_t	snscb_res2;
-	uint32_t	snscb_res3;
+	uint16_t	snscb_reserved2;
+	uint32_t	snscb_reserved3;
 	uint32_t	snscb_portid;
 } sns_gxn_id_req_t;
 #define	SNS_GXN_ID_REQ_SIZE	(sizeof (sns_gxn_id_req_t))
 
 typedef struct {
 	uint16_t	snscb_rblen;	/* response buffer length (words) */
-	uint16_t	snscb_res0;
+	uint16_t	snscb_reserved0;
 	uint16_t	snscb_addr[4];	/* response buffer address */
 	uint16_t	snscb_sblen;	/* subcommand buffer length (words) */
-	uint16_t	snscb_res1;
+	uint16_t	snscb_reserved1;
 	uint16_t	snscb_cmd;
 	uint16_t	snscb_mword_div_2;
-	uint32_t	snscb_res3;
+	uint32_t	snscb_reserved3;
 	uint32_t	snscb_fc4_type;
 } sns_gid_ft_req_t;
 #define	SNS_GID_FT_REQ_SIZE	(sizeof (sns_gid_ft_req_t))
 
 typedef struct {
 	uint16_t	snscb_rblen;	/* response buffer length (words) */
-	uint16_t	snscb_res0;
+	uint16_t	snscb_reserved0;
 	uint16_t	snscb_addr[4];	/* response buffer address */
 	uint16_t	snscb_sblen;	/* subcommand buffer length (words) */
-	uint16_t	snscb_res1;
+	uint16_t	snscb_reserved1;
 	uint16_t	snscb_cmd;
-	uint16_t	snscb_res2;
-	uint32_t	snscb_res3;
+	uint16_t	snscb_reserved2;
+	uint32_t	snscb_reserved3;
 	uint32_t	snscb_port;
 	uint32_t	snscb_fc4_types[8];
 } sns_rft_id_req_t;
@@ -980,7 +1283,68 @@ typedef struct {
 	} snscb_ports[1];
 } sns_gid_ft_rsp_t;
 #define	SNS_GID_FT_RESP_SIZE(x)	((sizeof (sns_gid_ft_rsp_t)) + ((x - 1) << 2))
-
 #define	SNS_RFT_ID_RESP_SIZE	(sizeof (ct_hdr_t))
 
+/*
+ * Other Misc Structures
+ */
+
+/* ELS Pass Through */
+typedef struct {
+	isphdr_t	els_hdr;
+	uint32_t	els_handle;
+	uint16_t	els_status;
+	uint16_t	els_nphdl;
+	uint16_t	els_xmit_dsd_count;	/* outgoing only */
+	uint8_t		els_vphdl;
+	uint8_t		els_sof;
+	uint32_t	els_rxid;
+	uint16_t	els_recv_dsd_count;	/* outgoing only */
+	uint8_t		els_opcode;
+	uint8_t		els_reserved1;
+	uint8_t		els_did_lo;
+	uint8_t		els_did_mid;
+	uint8_t		els_did_hi;
+	uint8_t		els_reserved2;
+	uint16_t	els_reserved3;
+	uint16_t	els_ctl_flags;
+	union {
+		struct {
+			uint32_t	_els_bytecnt;
+			uint32_t	_els_subcode1;
+			uint32_t	_els_subcode2;
+			uint8_t		_els_reserved4[20];
+		} in;
+		struct {
+			uint32_t	_els_recv_bytecnt;
+			uint32_t	_els_xmit_bytecnt;
+			uint32_t	_els_xmit_dsd_length;
+			uint16_t	_els_xmit_dsd_a1500;
+			uint16_t	_els_xmit_dsd_a3116;
+			uint16_t	_els_xmit_dsd_a4732;
+			uint16_t	_els_xmit_dsd_a6348;
+			uint32_t	_els_recv_dsd_length;
+			uint16_t	_els_recv_dsd_a1500;
+			uint16_t	_els_recv_dsd_a3116;
+			uint16_t	_els_recv_dsd_a4732;
+			uint16_t	_els_recv_dsd_a6348;
+		} out;
+	} inout;
+#define	els_bytecnt		inout.in._els_bytecnt
+#define	els_subcode1		inout.in._els_subcode1
+#define	els_subcode2		inout.in._els_subcode2
+#define	els_reserved4		inout.in._els_reserved4
+#define	els_recv_bytecnt	inout.out._els_recv_bytecnt
+#define	els_xmit_bytecnt	inout.out._els_xmit_bytecnt
+#define	els_xmit_dsd_length	inout.out._els_xmit_dsd_length
+#define	els_xmit_dsd_a1500	inout.out._els_xmit_dsd_a1500
+#define	els_xmit_dsd_a3116	inout.out._els_xmit_dsd_a3116
+#define	els_xmit_dsd_a4732	inout.out._els_xmit_dsd_a4732
+#define	els_xmit_dsd_a6348	inout.out._els_xmit_dsd_a6348
+#define	els_recv_dsd_length	inout.out._els_recv_dsd_length
+#define	els_recv_dsd_a1500	inout.out._els_recv_dsd_a1500
+#define	els_recv_dsd_a3116	inout.out._els_recv_dsd_a3116
+#define	els_recv_dsd_a4732	inout.out._els_recv_dsd_a4732
+#define	els_recv_dsd_a6348	inout.out._els_recv_dsd_a6348
+} els_t;
 #endif	/* _ISPMBOX_H */
diff --git a/sys/dev/isp/ispreg.h b/sys/dev/isp/ispreg.h
index 8c5e5d413ee2..57b58772b9ab 100644
--- a/sys/dev/isp/ispreg.h
+++ b/sys/dev/isp/ispreg.h
@@ -64,6 +64,7 @@
 #define	PCI_MBOX_REGS_OFF		0x70
 #define	PCI_MBOX_REGS2100_OFF		0x10
 #define	PCI_MBOX_REGS2300_OFF		0x40
+#define	PCI_MBOX_REGS2400_OFF		0x80
 #define	SBUS_MBOX_REGS_OFF		0x80
 
 #define	PCI_SXP_REGS_OFF		0x80
@@ -110,12 +111,6 @@
 #define	BIU_NVRAM	(BIU_BLOCK+0xE)		/* RW : Bus NVRAM */
 /*
  * These are specific to the 2300.
- *
- * They *claim* you can read BIU_R2HSTSLO with a full 32 bit access
- * and get both registers, but I'm a bit dubious about that. But the
- * point here is that the top 16 bits are firmware defined bits that
- * the RISC processor uses to inform the host about something- usually
- * something which was nominally in a mailbox register.
  */
 #define	BIU_REQINP	(BIU_BLOCK+0x10)	/* Request Queue In */
 #define	BIU_REQOUTP	(BIU_BLOCK+0x12)	/* Request Queue Out */
@@ -139,6 +134,7 @@
 #define		ISPR2HST_FPOST		0x16	/* Low 16 bits fast post */
 #define		ISPR2HST_FPOST_CTIO	0x17	/* Low 16 bits fast post ctio */
 
+/* fifo command stuff- mostly for SPI */
 #define	DFIFO_COMMAND	(BIU_BLOCK+0x60)	/* RW : Command FIFO Port */
 #define		RDMA2100_CONTROL	DFIFO_COMMAND
 #define	DFIFO_DATA	(BIU_BLOCK+0x62)	/* RW : Data FIFO Port */
@@ -219,6 +215,8 @@
 #define	BIU_ICR_ENABLE_ALL_INTS		0x0002	/* Global enable all inter */
 #define	BIU_ICR_SOFT_RESET		0x0001	/* Soft Reset of ISP */
 
+#define	BIU_IMASK	(BIU_ICR_ENABLE_RISC_INT|BIU_ICR_ENABLE_ALL_INTS)
+
 #define	BIU2100_ICR_ENABLE_ALL_INTS	0x8000
 #define	BIU2100_ICR_ENA_FPM_INT		0x0020
 #define	BIU2100_ICR_ENA_FB_INT		0x0010
@@ -228,16 +226,7 @@
 #define	BIU2100_ICR_ENABLE_TXDMA_INT	0x0001
 #define	BIU2100_ICR_DISABLE_ALL_INTS	0x0000
 
-#define	ENABLE_INTS(isp)	(IS_SCSI(isp))?  \
- ISP_WRITE(isp, BIU_ICR, BIU_ICR_ENABLE_RISC_INT | BIU_ICR_ENABLE_ALL_INTS) : \
- ISP_WRITE(isp, BIU_ICR, BIU2100_ICR_ENA_RISC_INT | BIU2100_ICR_ENABLE_ALL_INTS)
-
-#define	INTS_ENABLED(isp)	((IS_SCSI(isp))?  \
- (ISP_READ(isp, BIU_ICR) & (BIU_ICR_ENABLE_RISC_INT|BIU_ICR_ENABLE_ALL_INTS)) :\
- (ISP_READ(isp, BIU_ICR) & \
-	(BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS)))
-
-#define	DISABLE_INTS(isp)	ISP_WRITE(isp, BIU_ICR, 0)
+#define	BIU2100_IMASK	(BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS)
 
 /* BUS STATUS REGISTER */
 #define	BIU_ISR_DMA_INT			0x0020	/* DMA interrupt pending */
@@ -254,11 +243,14 @@
 #define	BIU2100_ISR_RXDMA_INT_PENDING	0x0002	/* Global interrupt pending */
 #define	BIU2100_ISR_TXDMA_INT_PENDING	0x0001	/* Global interrupt pending */
 
-#define	INT_PENDING(isp, isr)	(IS_FC(isp)? \
-	((isr & BIU2100_ISR_RISC_INT) != 0) : ((isr & BIU_ISR_RISC_INT) != 0))
+#define	INT_PENDING(isp, isr)						\
+ IS_FC(isp)?								\
+  (IS_24XX(isp)? (isr & BIU2400_ISR_RISC_INT) : (isr & BIU2100_ISR_RISC_INT)) :\
+  (isr & BIU_ISR_RISC_INT)
 
 #define	INT_PENDING_MASK(isp)	\
-	(IS_FC(isp)? BIU2100_ISR_RISC_INT: BIU_ISR_RISC_INT)
+ (IS_FC(isp)? (IS_24XX(isp)? BIU2400_ISR_RISC_INT : BIU2100_ISR_RISC_INT) : \
+ (BIU_ISR_RISC_INT))
 
 /* BUS SEMAPHORE REGISTER */
 #define	BIU_SEMA_STATUS		0x0002	/* Semaphore Status Bit */
@@ -351,6 +343,86 @@
 #define	DMA_FIFO_SBUS_COUNT_MASK	0x007F	/* FIFO Byte count mask */
 #define	DMA_FIFO_PCI_COUNT_MASK		0x00FF	/* FIFO Byte count mask */
 
+/*
+ * 2400 Interface Offsets and Register Definitions
+ * 
+ * The 2400 looks quite different in terms of registers from other QLogic cards.
+ * It is getting to be a genuine pain and challenge to keep the same model
+ * for all.
+ */
+#define	BIU2400_FLASH_ADDR	(BIU_BLOCK+0x00)
+#define	BIU2400_FLASH_DATA	(BIU_BLOCK+0x04)
+#define	BIU2400_CSR		(BIU_BLOCK+0x08)
+#define	BIU2400_ICR		(BIU_BLOCK+0x0C)
+#define	BIU2400_ISR		(BIU_BLOCK+0x10)
+
+#define	BIU2400_REQINP		(BIU_BLOCK+0x1C) /* Request Queue In */
+#define	BIU2400_REQOUTP		(BIU_BLOCK+0x20) /* Request Queue Out */
+#define	BIU2400_RSPINP		(BIU_BLOCK+0x24) /* Response Queue In */
+#define	BIU2400_RSPOUTP		(BIU_BLOCK+0x28) /* Response Queue Out */
+#define	BIU2400_PRI_RQINP 	(BIU_BLOCK+0x2C) /* Priority Request Q In */
+#define	BIU2400_PRI_RSPINP 	(BIU_BLOCK+0x30) /* Priority Request Q Out */
+
+#define	BIU2400_ATIO_RSPINP	(BIU_BLOCK+0x3C)	/* ATIO Queue In */
+#define	BIU2400_ATIO_REQINP	(BIU_BLOCK+0x40)	/* ATIO Queue Out */
+
+#define	BIU2400_R2HSTSLO	(BIU_BLOCK+0x44)
+#define	BIU2400_R2HSTSHI	(BIU_BLOCK+0x46)
+
+#define	BIU2400_HCCR		(BIU_BLOCK+0x48)
+#define	BIU2400_GPIOD		(BIU_BLOCK+0x4C)
+#define	BIU2400_GPIOE		(BIU_BLOCK+0x50)
+#define	BIU2400_HSEMA		(BIU_BLOCK+0x58)
+
+/* BIU2400_FLASH_ADDR definitions */
+#define	BIU2400_FLASH_DFLAG	(1 << 30)
+
+/* BIU2400_CSR definitions */
+#define	BIU2400_NVERR		(1 << 18)
+#define	BIU2400_DMA_ACTIVE	(1 << 17)		/* RO */
+#define	BIU2400_DMA_STOP	(1 << 16)
+#define	BIU2400_FUNCTION	(1 << 15)		/* RO */
+#define	BIU2400_PCIX_MODE(x)	(((x) >> 8) & 0xf)	/* RO */
+#define	BIU2400_CSR_64BIT	(1 << 2)		/* RO */
+#define	BIU2400_FLASH_ENABLE	(1 << 1)
+#define	BIU2400_SOFT_RESET	(1 << 0)
+
+/* BIU2400_ICR definitions */
+#define	BIU2400_ICR_ENA_RISC_INT	0x8
+#define	BIU2400_IMASK			(BIU2400_ICR_ENA_RISC_INT)
+
+/* BIU2400_ISR definitions */
+#define	BIU2400_ISR_RISC_INT		0x8
+
+#define	BIU2400_R2HST_INTR		BIU_R2HST_INTR
+#define	BIU2400_R2HST_PAUSED		BIU_R2HST_PAUSED
+#define	BIU2400_R2HST_ISTAT_MASK	0x1f
+/* interrupt status meanings */
+#define	ISP2400R2HST_ROM_MBX_OK		0x1	/* ROM mailbox cmd done ok */
+#define	ISP2400R2HST_ROM_MBX_FAIL	0x2	/* ROM mailbox cmd done fail */
+#define	ISP2400R2HST_MBX_OK		0x10	/* mailbox cmd done ok */
+#define	ISP2400R2HST_MBX_FAIL		0x11	/* mailbox cmd done fail */
+#define	ISP2400R2HST_ASYNC_EVENT	0x12	/* Async Event */
+#define	ISP2400R2HST_RSPQ_UPDATE	0x13	/* Response Queue Update */
+#define	ISP2400R2HST_ATIO_RSPQ_UPDATE	0x1C	/* ATIO Response Queue Update */
+#define	ISP2400R2HST_ATIO_RQST_UPDATE	0x1D	/* ATIO Request Queue Update */
+
+/* BIU2400_HCCR definitions */
+
+#define	HCCR_2400_CMD_NOP		(0x0 << 28)
+#define	HCCR_2400_CMD_RESET		(0x1 << 28)
+#define	HCCR_2400_CMD_CLEAR_RESET	(0x2 << 28)
+#define	HCCR_2400_CMD_PAUSE		(0x3 << 28)
+#define	HCCR_2400_CMD_RELEASE		(0x4 << 28)
+#define	HCCR_2400_CMD_SET_HOST_INT	(0x5 << 28)
+#define	HCCR_2400_CMD_CLEAR_HOST_INT	(0x6 << 28)
+#define	HCCR_2400_CMD_CLEAR_RISC_INT	(0xA << 28)
+
+#define	HCCR_2400_RISC_ERR(x)		(((x) >> 12) & 0x7)	/* RO */
+#define	HCCR_2400_RISC2HOST_INT		(1 << 6)		/* RO */
+#define	HCCR_2400_RISC_RESET		(1 << 5)		/* RO */
+
+
 /*
  * Mailbox Block Register Offsets
  */
@@ -377,7 +449,7 @@
  * Strictly speaking, it's 
  *  SCSI && 2100 : 8 MBOX registers
  *  2200: 24 MBOX registers
- *  2300: 32 MBOX registers
+ *  2300/2400: 32 MBOX registers
  */
 #define	MBOX_OFF(n)	(MBOX_BLOCK + ((n) << 1))
 #define	NMBOX(isp)	\
@@ -389,9 +461,15 @@
 
 #define	MAX_MAILBOX(isp)	((IS_FC(isp))? 12 : 8)
 #define	MAILBOX_STORAGE		12
+/* if timeout == 0, then default timeout is picked */
+#define	MBCMD_DEFAULT_TIMEOUT	100000	/* 100 ms */
 typedef struct {
 	uint16_t param[MAILBOX_STORAGE];
-	uint16_t ibits, obits;
+	uint16_t ibits;
+	uint16_t obits;
+	uint32_t	: 28,
+		logval	: 4;
+	uint32_t timeout;
 } mbreg_t;
 
 /*
@@ -672,6 +750,7 @@ typedef struct {
 #define	PCI_HCCR_CMD_PARITY_ERR		0xE000	/* Generate parity error */
 #define	HCCR_CMD_TEST_MODE		0xF000	/* Set Test Mode */
 
+
 #define	ISP2100_HCCR_PARITY_ENABLE_2	0x0400
 #define	ISP2100_HCCR_PARITY_ENABLE_1	0x0200
 #define	ISP2100_HCCR_PARITY_ENABLE_0	0x0100
@@ -687,6 +766,25 @@ typedef struct {
 
 #define	PCI_HCCR_BIOS			0x0001	/*  W : BIOS enable */
 
+/*
+ * Defines for Interrupts
+ */
+#define	ISP_INTS_ENABLED(isp)						\
+ ((IS_SCSI(isp))?  							\
+  (ISP_READ(isp, BIU_ICR) & BIU_IMASK) :				\
+   (IS_24XX(isp)? (ISP_READ(isp, BIU2400_ICR) & BIU2400_IMASK) :	\
+   (ISP_READ(isp, BIU_ICR) & BIU2100_IMASK)))
+
+#define	ISP_ENABLE_INTS(isp)						\
+ (IS_SCSI(isp) ?  							\
+   ISP_WRITE(isp, BIU_ICR, BIU_IMASK) :					\
+   (IS_24XX(isp) ?							\
+    (ISP_WRITE(isp, BIU2400_ICR, BIU2400_IMASK)) :			\
+    (ISP_WRITE(isp, BIU_ICR, BIU2100_IMASK))))
+
+#define	ISP_DISABLE_INTS(isp)						\
+ IS_24XX(isp)? ISP_WRITE(isp, BIU2400_ICR, 0) : ISP_WRITE(isp, BIU_ICR, 0)
+
 /*
  * NVRAM Definitions (PCI cards only)
  */
@@ -736,9 +834,9 @@ typedef struct {
 #define	ISP_NVRAM_FAST_MTTR_ENABLE(c)		ISPBSMX(c, 22, 0, 0x01)
 
 #define	ISP_NVRAM_TARGOFF			28
-#define	ISP_NVARM_TARGSIZE			6
+#define	ISP_NVRAM_TARGSIZE			6
 #define	_IxT(tgt, tidx)			\
-	(ISP_NVRAM_TARGOFF + (ISP_NVARM_TARGSIZE * (tgt)) + (tidx))
+	(ISP_NVRAM_TARGOFF + (ISP_NVRAM_TARGSIZE * (tgt)) + (tidx))
 #define	ISP_NVRAM_TGT_RENEG(c, t)		ISPBSMX(c, _IxT(t, 0), 0, 0x01)
 #define	ISP_NVRAM_TGT_QFRZ(c, t)		ISPBSMX(c, _IxT(t, 0), 1, 0x01)
 #define	ISP_NVRAM_TGT_ARQ(c, t)			ISPBSMX(c, _IxT(t, 0), 2, 0x01)
@@ -937,7 +1035,7 @@ typedef struct {
 	ISPBSMX(c, _IxT16(t, 4, (b)), 7, 0x01)
 
 /*
- * Qlogic 2XXX NVRAM is an array of 256 bytes.
+ * Qlogic 2100 thru 2300 NVRAM is an array of 256 bytes.
  *
  * Some portion of the front of this is for general RISC engine parameters,
  * mostly reflecting the state of the last INITIALIZE FIRMWARE mailbox command.
@@ -1011,6 +1109,51 @@ typedef struct {
 
 #define	ISP2100_HBA_FEATURES(c)			((c)[232] | ((c)[233] << 8))
 
+/*
+ * Qlogic 2400 NVRAM is an array of 512 bytes with a 32 bit checksum.
+ */
+#define	ISP2400_NVRAM_PORT0_ADDR	0x80
+#define	ISP2400_NVRAM_PORT1_ADDR	0x180
+#define	ISP2400_NVRAM_SIZE		512
+
+#define	ISP2400_NVRAM_VERSION(c)		((c)[4] | ((c)[5] << 8))
+#define	ISP2400_NVRAM_MAXFRAMELENGTH(c)		(((c)[12]) | ((c)[13] << 8))
+#define	ISP2400_NVRAM_EXECUTION_THROTTLE(c)	(((c)[14]) | ((c)[15] << 8))
+#define	ISP2400_NVRAM_EXCHANGE_COUNT(c)		(((c)[16]) | ((c)[17] << 8))
+#define	ISP2400_NVRAM_HARDLOOPID(c)		((c)[18] | ((c)[19] << 8))
+
+#define	ISP2400_NVRAM_PORT_NAME(c)	(\
+		(((uint64_t)(c)[20]) << 56) | \
+		(((uint64_t)(c)[21]) << 48) | \
+		(((uint64_t)(c)[22]) << 40) | \
+		(((uint64_t)(c)[23]) << 32) | \
+		(((uint64_t)(c)[24]) << 24) | \
+		(((uint64_t)(c)[25]) << 16) | \
+		(((uint64_t)(c)[26]) <<  8) | \
+		(((uint64_t)(c)[27]) <<  0))
+
+#define	ISP2400_NVRAM_NODE_NAME(c)	(\
+		(((uint64_t)(c)[28]) << 56) | \
+		(((uint64_t)(c)[29]) << 48) | \
+		(((uint64_t)(c)[30]) << 40) | \
+		(((uint64_t)(c)[31]) << 32) | \
+		(((uint64_t)(c)[32]) << 24) | \
+		(((uint64_t)(c)[33]) << 16) | \
+		(((uint64_t)(c)[34]) <<  8) | \
+		(((uint64_t)(c)[35]) <<  0))
+
+#define	ISP2400_NVRAM_LOGIN_RETRY_CNT(c)	((c)[36] | ((c)[37] << 8))
+#define	ISP2400_NVRAM_LINK_DOWN_ON_NOS(c)	((c)[38] | ((c)[39] << 8))
+#define	ISP2400_NVRAM_INTERRUPT_DELAY(c)	((c)[40] | ((c)[41] << 8))
+#define	ISP2400_NVRAM_LOGIN_TIMEOUT(c)		((c)[42] | ((c)[43] << 8))
+
+#define	ISP2400_NVRAM_FIRMWARE_OPTIONS1(c)	\
+	((c)[44] | ((c)[45] << 8) | ((c)[46] << 16) | ((c)[47] << 24))
+#define	ISP2400_NVRAM_FIRMWARE_OPTIONS2(c)	\
+	((c)[48] | ((c)[49] << 8) | ((c)[50] << 16) | ((c)[51] << 24))
+#define	ISP2400_NVRAM_FIRMWARE_OPTIONS3(c)	\
+	((c)[52] | ((c)[53] << 8) | ((c)[54] << 16) | ((c)[55] << 24))
+
 /*
  * Firmware Crash Dump
  *
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 5ea8e8a7c415..fec8423a2625 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -31,20 +31,24 @@
 #define	_ISPVAR_H
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <dev/ic/isp_stds.h>
 #include <dev/ic/ispmbox.h>
 #endif
 #ifdef	__FreeBSD__
+#include <dev/isp/isp_stds.h>
 #include <dev/isp/ispmbox.h>
 #endif
 #ifdef	__linux__
+#include "isp_stds.h"
 #include "ispmbox.h"
 #endif
 #ifdef	__svr4__
+#include "isp_stds.h"
 #include "ispmbox.h"
 #endif
 
-#define	ISP_CORE_VERSION_MAJOR	2
-#define	ISP_CORE_VERSION_MINOR	11
+#define	ISP_CORE_VERSION_MAJOR	3
+#define	ISP_CORE_VERSION_MINOR	0
 
 /*
  * Vector for bus specific code to provide specific services.
@@ -52,17 +56,17 @@
 typedef struct ispsoftc ispsoftc_t;
 struct ispmdvec {
 	int		(*dv_rd_isr)
-	    (ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
-	uint16_t	(*dv_rd_reg) (ispsoftc_t *, int);
-	void		(*dv_wr_reg) (ispsoftc_t *, int, uint16_t);
+	    (ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
+	uint32_t	(*dv_rd_reg) (ispsoftc_t *, int);
+	void		(*dv_wr_reg) (ispsoftc_t *, int, uint32_t);
 	int		(*dv_mbxdma) (ispsoftc_t *);
 	int		(*dv_dmaset)
-	    (ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t);
-	void		(*dv_dmaclr) (ispsoftc_t *, XS_T *, uint16_t);
+	    (ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
+	void		(*dv_dmaclr) (ispsoftc_t *, XS_T *, uint32_t);
 	void		(*dv_reset0) (ispsoftc_t *);
 	void		(*dv_reset1) (ispsoftc_t *);
 	void		(*dv_dregs) (ispsoftc_t *, const char *);
-	uint16_t	*dv_ispfw;	/* ptr to f/w */
+	void *		dv_ispfw;	/* ptr to f/w */
 	uint16_t	dv_conf1;
 	uint16_t	dv_clock;	/* clock frequency */
 };
@@ -122,6 +126,7 @@ struct ispmdvec {
 #define	SYNC_SFORDEV	2	/* scratch, sync for ISP */
 #define	SYNC_SFORCPU	3	/* scratch, sync for CPU */
 #define	SYNC_REG	4	/* for registers */
+#define	SYNC_ATIOQ	5	/* atio result queue (24xx) */
 
 /*
  * Request/Response Queue defines and macros.
@@ -148,7 +153,7 @@ struct ispmdvec {
 
 #define	ISP_ADD_REQUEST(isp, nxti)					\
 	MEMORYBARRIER(isp, SYNC_REQUEST, isp->isp_reqidx, QENTRY_LEN);	\
-	WRITE_REQUEST_QUEUE_IN_POINTER(isp, nxti);			\
+	ISP_WRITE(isp, isp->isp_rqstinrp, nxti);			\
 	isp->isp_reqidx = nxti
 
 /*
@@ -161,6 +166,7 @@ typedef struct {
 			isp_cmd_dma_burst_enable: 1,
 			isp_data_dma_burst_enabl: 1,
 			isp_fifo_threshold	: 3,
+			isp_ptisp		: 1,
 			isp_ultramode		: 1,
 			isp_diffmode		: 1,
 			isp_lvdmode		: 1,
@@ -222,32 +228,125 @@ typedef struct {
 /*
  * Fibre Channel Specifics
  */
-#define	FL_PORT_ID		0x7e	/* FL_Port Special ID */
-#define	FC_PORT_ID		0x7f	/* Fabric Controller Special ID */
-#define	FC_SNS_ID		0x80	/* SNS Server Special ID */
+/* These are for 2100/2200/2300 cards */
+#define	FL_ID			0x7e	/* FL_Port Special ID */
+#define	SNS_ID			0x80	/* SNS Server Special ID */
+#define	NPH_MAX			0xfe
 
-/* #define	ISP_USE_GA_NXT	1 */	/* Use GA_NXT with switches */
-#ifndef	GA_NXT_MAX
-#define	GA_NXT_MAX	256
-#endif
+/* These are for 24XX cards */
+#define	NPH_RESERVED		0x7F0	/* begin of reserved N-port handles */
+#define	NPH_MGT_ID		0x7FA	/* Management Server Special ID */
+#define	NPH_SNS_ID		0x7FC	/* SNS Server Special ID */
+#define	NPH_FL_ID		0x7FE	/* FL Port Special ID */
+#define	NPH_MAX_24XX		0x800
 
+/*
+ * Limit for devices on an arbitrated loop.
+ */
+#define	LOCAL_LOOP_LIM		126
+
+/*
+ * Special Port IDs
+ */
+#define	MANAGEMENT_PORT_ID	0xFFFFFA
+#define	SNS_PORT_ID		0xFFFFFC
+#define	FABRIC_PORT_ID		0xFFFFFE
+
+
+/*
+ * FC Port Database entry.
+ *
+ * It has a handle that the f/w uses to address commands to a device.
+ * This handle's value may be assigned by the firmware (e.g., for local loop
+ * devices) or by the driver (e.g., for fabric devices).
+ *
+ * It has a state. If the state if VALID, that means that we've logged into
+ * the device. We also *may* have a initiator map index entry. This is a value
+ * from 0..MAX_FC_TARG that is used to index into the isp_ini_map array. If
+ * the value therein is non-zero, then that value minus one is used to index
+ * into the Port Database to find the handle for forming commands. There is
+ * back-index minus one value within to Port Database entry that tells us 
+ * which entry in isp_ini_map points to us (to avoid searching).
+ *
+ * Local loop devices the firmware automatically performs PLOGI on for us
+ * (which is why that handle is imposed upon us). Fabric devices we assign
+ * a handle to and perform the PLOGI on.
+ *
+ * When a PORT DATABASE CHANGED asynchronous event occurs, we mark all VALID
+ * entries as PROBATIONAL. This allows us, if policy says to, just keep track
+ * of devices whose handles change but are otherwise the same device (and
+ * thus keep 'target' constant).
+ *
+ * In any case, we search all possible local loop handles. For each one that
+ * has a port database entity returned, we search for any PROBATIONAL entry
+ * that matches it and update as appropriate. Otherwise, as a new entry, we
+ * find room for it in the Port Database. We *try* and use the handle as the
+ * index to put it into the Database, but that's just an optimization. We mark
+ * the entry VALID and make sure that the target index is updated and correct.
+ *
+ * When we get done searching the local loop, we then search similarily for
+ * a list of devices we've gotten from the fabric name controller (if we're
+ * on a fabric). VALID marking is also done similarily.
+ *
+ * When all of this is done, we can march through the database and clean up
+ * any entry that is still PROBATIONAL (these represent devices which have
+ * departed). Then we're done and can resume normal operations.
+ *
+ * Negative invariants that we try and test for are:
+ *
+ *  + There can never be two non-NIL entries with the same { Port, Node } WWN
+ *    duples.
+ *
+ *  + There can never be two non-NIL entries with the same handle.
+ *
+ *  + There can never be two non-NIL entries which have the same ini_map_idx
+ *    value.
+ */
 typedef struct {
-	uint32_t				: 13,
+	uint16_t	handle;
+	uint16_t	ini_map_idx	: 12,
+			autologin	: 1,	/* F/W does PLOGI/PLOGO */
+			state		: 3;
+	uint32_t			: 6,
+			roles		: 2,
+			portid		: 24;
+	uint32_t			: 6,
+			new_roles	: 2,
+			new_portid	: 24;
+	uint64_t	node_wwn;
+	uint64_t	port_wwn;
+} fcportdb_t;
+
+#define	FC_PORTDB_STATE_NIL		0
+#define	FC_PORTDB_STATE_PROBATIONAL	1
+#define	FC_PORTDB_STATE_DEAD		2
+#define	FC_PORTDB_STATE_CHANGED		3
+#define	FC_PORTDB_STATE_NEW		4
+#define	FC_PORTDB_STATE_PENDING_VALID	5
+#define	FC_PORTDB_STATE_VALID		7
+
+/*
+ * FC card specific information
+ */
+typedef struct {
+	uint32_t				: 10,
+				isp_tmode	: 1,
+				isp_2klogin	: 1,
+				isp_sccfw	: 1,
 				isp_gbspeed	: 3,
 						: 1,
-				isp_iid_set	: 1,
-				loop_seen_once	: 1,
+						: 1,
+						: 1,
 				isp_loopstate	: 4,	/* Current Loop State */
 				isp_fwstate	: 4,	/* ISP F/W state */
 				isp_gotdparms	: 1,
 				isp_topo	: 3,
-				isp_onfabric	: 1;
+				loop_seen_once	: 1;
 	uint32_t				: 8,
 				isp_portid	: 24;	/* S_ID */
 	uint16_t		isp_fwoptions;
 	uint16_t		isp_xfwoptions;
 	uint16_t		isp_zfwoptions;
-	uint16_t		isp_iid;	/* 'initiator' id */
 	uint16_t		isp_loopid;	/* hard loop id */
 	uint16_t		isp_fwattr;	/* firmware attributes */
 	uint16_t		isp_execthrottle;
@@ -258,34 +357,8 @@ typedef struct {
 	uint16_t		isp_maxfrmlen;
 	uint64_t		isp_nodewwn;
 	uint64_t		isp_portwwn;
-	/*
-	 * Port Data Base. This is indexed by 'target', which is invariate.
-	 * However, elements within can move around due to loop changes,
-	 * so the actual loop ID passed to the F/W is in this structure.
-	 * The first time the loop is seen up, loopid will match the index
-	 * (except for fabric nodes which are above mapped above FC_SNS_ID
-	 * and are completely virtual), but subsequent LIPs can cause things
-	 * to move around.
-	 */
-	struct lportdb {
-		uint32_t		loopid		: 16,
-							: 2,
-					fc4_type	: 4,
-					last_fabric_dev	: 1,
-					relogin		: 1,
-					force_logout	: 1,
-					was_fabric_dev	: 1,
-					fabric_dev	: 1,
-					loggedin	: 1,
-					roles		: 2,
-					tvalid		: 1,
-					valid		: 1;
-		uint32_t		port_type	: 8,
-					portid		: 24;
-		uint64_t		node_wwn;
-		uint64_t		port_wwn;
-	} portdb[MAX_FC_TARG], tport[FC_PORT_ID];
-
+	fcportdb_t		portdb[MAX_FC_TARG];
+	uint16_t		isp_ini_map[MAX_FC_TARG];
 	/*
 	 * Scratch DMA mapped in area to fetch Port Database stuff, etc.
 	 */
@@ -308,10 +381,10 @@ typedef struct {
 #define	LOOP_NIL		0
 #define	LOOP_LIP_RCVD		1
 #define	LOOP_PDB_RCVD		2
-#define	LOOP_SCANNING_FABRIC	3
-#define	LOOP_FSCAN_DONE		4
-#define	LOOP_SCANNING_LOOP	5
-#define	LOOP_LSCAN_DONE		6
+#define	LOOP_SCANNING_LOOP	3
+#define	LOOP_LSCAN_DONE		4
+#define	LOOP_SCANNING_FABRIC	5
+#define	LOOP_FSCAN_DONE		6
 #define	LOOP_SYNCING_PDB	7
 #define	LOOP_READY		8
 
@@ -350,7 +423,7 @@ struct ispsoftc {
 
 	uint32_t		isp_clock	: 8,	/* input clock */
 						: 4,
-				isp_port	: 1,	/* 23XX only */
+				isp_port	: 1,	/* 23XX/24XX only */
 				isp_failed	: 1,	/* board failed */
 				isp_open	: 1,	/* opened (ioctl) */
 				isp_touched	: 1,	/* board ever seen? */
@@ -361,10 +434,12 @@ struct ispsoftc {
 
 	uint32_t		isp_confopts;		/* config options */
 
-	uint16_t		isp_rqstinrp;	/* register for REQINP */
-	uint16_t		isp_rqstoutrp;	/* register for REQOUTP */
-	uint16_t		isp_respinrp;	/* register for RESINP */
-	uint16_t		isp_respoutrp;	/* register for RESOUTP */
+	uint32_t		isp_rqstinrp;	/* register for REQINP */
+	uint32_t		isp_rqstoutrp;	/* register for REQOUTP */
+	uint32_t		isp_respinrp;	/* register for RESINP */
+	uint32_t		isp_respoutrp;	/* register for RESOUTP */
+	uint32_t		isp_atioinrp;	/* register for ATIOINP */
+	uint32_t		isp_atiooutrp;	/* register for ATIOOUTP */
 
 	/*
 	 * Instrumentation
@@ -388,13 +463,13 @@ struct ispsoftc {
 		isp_sendmarker	:	2,	/* send a marker entry */
 		isp_update	:	2,	/* update parameters */
 		isp_nactive	:	16;	/* how many commands active */
-	volatile uint16_t	isp_reqodx;	/* index of last ISP pickup */
-	volatile uint16_t	isp_reqidx;	/* index of next request */
-	volatile uint16_t	isp_residx;	/* index of next result */
-	volatile uint16_t	isp_resodx;	/* index of next result */
-	volatile uint16_t	isp_rspbsy;
-	volatile uint16_t	isp_lasthdls;	/* last handle seed */
-	volatile uint16_t	isp_obits;	/* mailbox command output */
+	volatile uint32_t	isp_reqodx;	/* index of last ISP pickup */
+	volatile uint32_t	isp_reqidx;	/* index of next request */
+	volatile uint32_t	isp_residx;	/* index of next result */
+	volatile uint32_t	isp_resodx;	/* index of next result */
+	volatile uint32_t	isp_rspbsy;
+	volatile uint32_t	isp_lasthdls;	/* last handle seed */
+	volatile uint32_t	isp_obits;	/* mailbox command output */
 	volatile uint16_t	isp_mboxtmp[MAILBOX_STORAGE];
 	volatile uint16_t	isp_lastmbxcmd;	/* last mbox command sent */
 	volatile uint16_t	isp_mbxwrk0;
@@ -422,6 +497,11 @@ struct ispsoftc {
 	void *			isp_result;
 	XS_DMA_ADDR_T		isp_rquest_dma;
 	XS_DMA_ADDR_T		isp_result_dma;
+#ifdef	ISP_TARGET_MODE
+	/* for 24XX only */
+	void *			isp_atioq;
+	XS_DMA_ADDR_T		isp_atioq_dma;
+#endif
 };
 
 #define	SDPARAM(isp)	((sdparam *) (isp)->isp_param)
@@ -454,6 +534,7 @@ struct ispsoftc {
 #define	ISP_CFG_OWNFSZ		0x400	/* override NVRAM frame size */
 #define	ISP_CFG_OWNLOOPID	0x800	/* override NVRAM loopid */
 #define	ISP_CFG_OWNEXCTHROTTLE	0x1000	/* override NVRAM execution throttle */
+#define	ISP_CFG_FOURGB		0x2000	/* force 4GB connection (24XX only) */
 
 /*
  * Prior to calling isp_reset for the first time, the outer layer
@@ -491,6 +572,7 @@ struct ispsoftc {
  */
 #define	ISP_CODE_ORG			0x1000	/* default f/w code start */
 #define	ISP_CODE_ORG_2300		0x0800	/* ..except for 2300s */
+#define	ISP_CODE_ORG_2400		0x100000 /* ..and 2400s */
 #define	ISP_FW_REV(maj, min, mic)	((maj << 24) | (min << 16) | mic)
 #define	ISP_FW_MAJOR(code)		((code >> 24) & 0xff)
 #define	ISP_FW_MINOR(code)		((code >> 16) & 0xff)
@@ -501,6 +583,8 @@ struct ispsoftc {
 #define	ISP_FW_MICROX(xp)		(xp[2])
 #define	ISP_FW_NEWER_THAN(i, major, minor, micro)		\
  (ISP_FW_REVX((i)->isp_fwrev) > ISP_FW_REV(major, minor, micro))
+#define	ISP_FW_OLDER_THAN(i, major, minor, micro)		\
+ (ISP_FW_REVX((i)->isp_fwrev) < ISP_FW_REV(major, minor, micro))
 
 /*
  * Bus (implementation) types
@@ -539,7 +623,6 @@ struct ispsoftc {
 #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)
@@ -557,8 +640,8 @@ struct ispsoftc {
 #define	IS_FC(isp)	((isp)->isp_type & ISP_HA_FC)
 #define	IS_2100(isp)	((isp)->isp_type == ISP_HA_FC_2100)
 #define	IS_2200(isp)	((isp)->isp_type == ISP_HA_FC_2200)
-#define	IS_23XX(isp)	\
-    ((isp)->isp_type >= ISP_HA_FC_2300 && (isp)->isp_type < ISP_HA_FC_2400)
+#define	IS_23XX(isp)	((isp)->isp_type >= ISP_HA_FC_2300 && \
+				(isp)->isp_type < ISP_HA_FC_2400)
 #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)
@@ -567,10 +650,10 @@ struct ispsoftc {
 /*
  * DMA related macros
  */
-#define	DMA_WD3(x)	((((uint64_t)x) >> 48) & 0xffff)
-#define	DMA_WD2(x)	((((uint64_t)x) >> 32) & 0xffff)
-#define	DMA_WD1(x)	(((x) >> 16) & 0xffff)
-#define	DMA_WD0(x)	(((x) & 0xffff))
+#define	DMA_WD3(x)	(((uint16_t)(((uint64_t)x) >> 48)) & 0xffff)
+#define	DMA_WD2(x)	(((uint16_t)(((uint64_t)x) >> 32)) & 0xffff)
+#define	DMA_WD1(x)	((uint16_t)((x) >> 16) & 0xffff)
+#define	DMA_WD0(x)	((uint16_t)((x) & 0xffff))
 
 #define	DMA_LO32(x)	((uint32_t) (x))
 #define	DMA_HI32(x)	((uint32_t)(((uint64_t)x) >> 32))
@@ -609,7 +692,7 @@ void isp_fw_dump(ispsoftc_t *isp);
  * semaphore register and first mailbox register (if appropriate). This also
  * means that most spurious/bogus interrupts not for us can be filtered first.
  */
-void isp_intr(ispsoftc_t *, uint16_t, uint16_t, uint16_t);
+void isp_intr(ispsoftc_t *, uint32_t, uint16_t, uint16_t);
 
 
 /*
@@ -672,7 +755,7 @@ typedef enum {
 	ISPCTL_SCAN_LOOP,		/* (Re)scan Local Loop */
 	ISPCTL_PDB_SYNC,		/* Synchronize Port Database */
 	ISPCTL_SEND_LIP,		/* Send a LIP */
-	ISPCTL_GET_POSMAP,		/* Get FC-AL position map */
+	ISPCTL_GET_PORTNAME,		/* get portname from an N-port handle */
 	ISPCTL_RUN_MBOXCMD,		/* run a mailbox command */
 	ISPCTL_TOGGLE_TMODE,		/* toggle target mode */
 	ISPCTL_GET_PDB			/* get a single port database entry */
@@ -728,8 +811,10 @@ typedef enum {
 	ISPASYNC_LIP,			/* LIP Received */
 	ISPASYNC_LOOP_RESET,		/* Loop Reset Received */
 	ISPASYNC_CHANGE_NOTIFY,		/* FC Change Notification */
-	ISPASYNC_FABRIC_DEV,		/* FC Fabric Device Arrival */
-	ISPASYNC_PROMENADE,		/* FC Objects coming && going */
+	ISPASYNC_DEV_ARRIVED,		/* FC Device Arrival */
+	ISPASYNC_DEV_CHANGED,		/* FC Device Change */
+	ISPASYNC_DEV_STAYED,		/* FC Device Stayed the Same */
+	ISPASYNC_DEV_GONE,		/* FC Device Depart */
 	ISPASYNC_TARGET_NOTIFY,		/* target asynchronous notification event */
 	ISPASYNC_TARGET_ACTION,		/* target action requested */
 	ISPASYNC_CONF_CHANGE,		/* Platform Configuration Change */
@@ -804,7 +889,7 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
  *		of the same object is consistent.
  *
  *	MBOX_ACQUIRE(ispsoftc_t *)		acquire lock on mailbox regs
- *	MBOX_WAIT_COMPLETE(ispsoftc_t *)	wait for mailbox cmd to be done
+ *	MBOX_WAIT_COMPLETE(ispsoftc_t *, mbreg_t *) wait for cmd to be done
  *	MBOX_NOTIFY_COMPLETE(ispsoftc_t *)	notification of mbox cmd donee
  *	MBOX_RELEASE(ispsoftc_t *)		release lock on mailbox regs
  *