6973228 Cannot download firmware 2.103.x.x on Emulex FCoE HBAs default tip
authorSukumar Swaminathan <Sukumar.Swaminathan@Sun.COM>
Wed, 18 Aug 2010 15:52:48 -0600
changeset 13149 b23a4dab3d50
parent 13148 7f829eb09eb7
6973228 Cannot download firmware 2.103.x.x on Emulex FCoE HBAs 6960289 fiber side of emulex cna does not connect to the storage 6950462 Emulex HBA permanently DESTROYED, if the firmware upgrade is interrupted 6964513 COMSTAR - Emulex LP9002 fail to return a SCSI Inquiry correctly to a VMware 4 Initiator
usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c
usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c
usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c
usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c
usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c
usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c
usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_config.h
usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_extern.h
usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_fc.h
usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_hw.h
usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_mbox.h
usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_messages.h
usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_version.h
--- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c	Wed Aug 18 15:52:48 2010 -0600
@@ -42,6 +42,7 @@
 #endif /* DHCHAP_SUPPORT */
 
 static void	emlxs_timer(void *arg);
+static void	emlxs_timer_check_fw_update(emlxs_hba_t *hba);
 static void	emlxs_timer_check_heartbeat(emlxs_hba_t *hba);
 static uint32_t	emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag);
 static void	emlxs_timer_check_nodes(emlxs_port_t *port, uint8_t *flag);
@@ -157,6 +158,9 @@
 	/* Check heartbeat timer */
 	emlxs_timer_check_heartbeat(hba);
 
+	/* Check fw update timer */
+	emlxs_timer_check_fw_update(hba);
+
 #ifdef IDLE_TIMER
 	emlxs_pm_idle_timer(hba);
 #endif /* IDLE_TIMER */
@@ -811,6 +815,32 @@
 
 
 static void
+emlxs_timer_check_fw_update(emlxs_hba_t *hba)
+{
+	emlxs_port_t *port = &PPORT;
+
+	if (!(hba->fw_flag & FW_UPDATE_NEEDED)) {
+		hba->fw_timer = 0;
+		return;
+	}
+
+	if (hba->timer_tics < hba->fw_timer) {
+		return;
+	}
+
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_update_msg,
+	"A manual HBA reset or link reset (using luxadm or fcadm) "
+	"is required.");
+
+	/* Set timer for 24 hours */
+	hba->fw_timer = hba->timer_tics + (60 * 60 * 24);
+
+	return;
+
+} /* emlxs_timer_check_fw_update() */
+
+
+static void
 emlxs_timer_check_discovery(emlxs_port_t *port)
 {
 	emlxs_hba_t *hba = HBA;
--- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c	Wed Aug 18 15:52:48 2010 -0600
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Emulex.  All rights reserved.
+ * Copyright 2010 Emulex.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,33 +38,27 @@
 			PIMAGE_HDR ImageHdr, caddr_t Buffer);
 
 static int32_t	emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
-			uint32_t BufferSize, PAIF_HDR AifHeader,
-			int32_t DwcFile);
+			uint32_t BufferSize, PAIF_HDR AifHeader);
 static uint32_t	emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
 			uint32_t Size, emlxs_fw_image_t *fw_image);
 static void	emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq,
 			uint32_t Type, uint32_t RegionId, uint32_t WordCnt,
 			uint32_t BaseAddr);
 static uint32_t	emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
-			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
-			uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize,
-			PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile);
+			caddr_t Buffer, uint32_t len,
+			PWAKE_UP_PARMS WakeUpParms);
 static uint32_t	emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
 			uint32_t len, uint32_t offline,
 			emlxs_fw_image_t *fw_image);
-static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba, PAIF_HDR AifHdr,
+static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba,
 			caddr_t EntireBuffer, uint32_t FileType,
-			uint32_t BWCflag, uint32_t extType);
+			uint32_t extType);
 static void	emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base,
 			uint32_t DlByteCount, uint32_t Function,
 			uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
 			uint8_t MbxCmd, uint32_t StepCmd);
 static uint32_t	emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
 			uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
-static uint32_t	emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba, caddr_t Buffer,
-			uint32_t BufferSize, PAIF_HDR AifHeader,
-			PWAKE_UP_PARMS AbsWakeUpParms, uint32_t BWCflag,
-			uint32_t extType, uint32_t *numBootImage);
 static uint32_t	emlxs_update_exp_rom(emlxs_hba_t *hba,
 			PWAKE_UP_PARMS WakeUpParms);
 extern uint32_t	emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
@@ -72,7 +66,7 @@
 static void	emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base,
 			uint32_t DlByteCount, uint32_t Function,
 			uint32_t Complete, uint32_t BdeAddress,
-			uint32_t BdeSize, PROG_ID *ProgId);
+			uint32_t BdeSize, PROG_ID *ProgId, uint32_t keep);
 static void	emlxs_format_update_parms(MAILBOXQ *mbq,
 			PWAKE_UP_PARMS WakeUpParms);
 static void	emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
@@ -95,7 +89,7 @@
 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
 static uint32_t	emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
-			uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize);
+			uint32_t dwc_flag);
 static uint32_t	emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
 
 static uint32_t	emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
@@ -104,10 +98,6 @@
 
 static void	emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
 
-static uint32_t	emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize);
-
-static uint32_t	emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer,
-			uint32_t BufferSize, PAIF_HDR AifHeader);
 static uint32_t	emlxs_type_check(uint32_t type);
 
 static uint32_t	emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
@@ -142,6 +132,16 @@
 static int32_t emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer,
 			uint32_t len, uint32_t offline);
 
+static uint32_t emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer,
+			emlxs_fw_image_t *fw_image);
+static uint32_t emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId);
+
+static void emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *image);
+
+static uint32_t emlxs_clean_flash(emlxs_hba_t *hba,
+			PWAKE_UP_PARMS OldWakeUpParms,
+			PWAKE_UP_PARMS NewWakeUpParms);
+
 /* ************************************************************************* */
 
 extern int32_t
@@ -154,11 +154,6 @@
 	AIF_HDR AifHdr;
 	uint32_t ImageType;
 	WAKE_UP_PARMS WakeUpParms;
-	WAKE_UP_PARMS AbsWakeUpParms;
-	uint32_t MaxRbusSramSize;
-	uint32_t MaxIbusSramSize;
-	int32_t AbsChangeParams = 0;
-	int32_t DwcFile = FALSE;
 	uint32_t rval = 0;
 	emlxs_fw_image_t fw_image;
 	uint32_t i;
@@ -209,6 +204,9 @@
 		goto done;
 	}
 
+	/* Verify image */
+	emlxs_verify_image(hba, &fw_image);
+
 	/* Get image type */
 	Uptr = (uint32_t *)buffer;
 	ImageType = *Uptr;
@@ -239,26 +237,16 @@
 
 	/* Pre-pegasus adapters only */
 
-	/* Check for absolute image */
-	else if (ImageType == NOP_IMAGE_TYPE) {
+	/* Initialize headers */
+	if (ImageType == NOP_IMAGE_TYPE) {
 		bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
 		bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
-
-		if (AifHdr.ImageBase && (AifHdr.ImageBase == 0x20000)) {
-			DwcFile = TRUE;
-		}
-
-		AbsChangeParams = emlxs_build_parms(buffer,
-		    &AbsWakeUpParms, len, &AifHdr, DwcFile);
-	} else {	/* (ImageType != NOP_IMAGE_TYPE) Relative image */
-
+	} else { /* PRG file */
 		bzero((void *)&AifHdr, sizeof (AIF_HDR));
 		bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
 	}
 
-	/*
-	 * Everything checks out, now to just do it
-	 */
+	/* Everything checks out, now to just do it */
 
 	if (offline) {
 		if (emlxs_offline(hba) != FC_SUCCESS) {
@@ -268,7 +256,6 @@
 			    "Unable to take adapter offline.");
 
 			rval = EMLXS_OFFLINE_FAILED;
-
 			goto SLI_DOWNLOAD_EXIT;
 		}
 
@@ -279,11 +266,12 @@
 			    "Unable to restart adapter.");
 
 			rval = EMLXS_OFFLINE_FAILED;
-
 			goto SLI_DOWNLOAD_EXIT;
 		}
 	}
 
+	/* Pre-pegasus adapters */
+
 	if (ImageHdr.Id.Type == SBUS_FCODE) {
 		/* Erase Flash */
 		if (emlxs_erase_fcode_flash(hba)) {
@@ -291,7 +279,6 @@
 			    "Unable to erase flash.");
 
 			rval = EMLXS_IMAGE_FAILED;
-
 			goto SLI_DOWNLOAD_EXIT;
 		}
 
@@ -301,62 +288,47 @@
 			    "Unable to write flash.");
 
 			rval = EMLXS_IMAGE_FAILED;
-
 			goto SLI_DOWNLOAD_EXIT;
 		}
 
-	} else {	/* !SBUS_FCODE */
-
-
-		if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
-			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
-			    "Unable to get parameters.");
-
-			rval = EMLXS_IMAGE_FAILED;
-
-			goto SLI_DOWNLOAD_EXIT;
-		}
-
-		if (emlxs_get_max_sram(hba, &MaxRbusSramSize,
-		    &MaxIbusSramSize)) {
-			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
-			    "Unable to get RAM size.");
+		goto SLI_DOWNLOAD_EXIT;
+	}
+
+	/* Pre-pegasus PCI adapters */
+
+	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
+		    "Unable to get parameters.");
+
+		rval = EMLXS_IMAGE_FAILED;
+
+		goto SLI_DOWNLOAD_EXIT;
+	}
+
+	if (ImageType == NOP_IMAGE_TYPE) {
+		if (emlxs_start_abs_download(hba, &AifHdr,
+		    buffer, len, &WakeUpParms)) {
+			EMLXS_MSGF(EMLXS_CONTEXT,
+			    &emlxs_download_failed_msg,
+			    "Failed to program flash.");
 
 			rval = EMLXS_IMAGE_FAILED;
 
 			goto SLI_DOWNLOAD_EXIT;
 		}
 
-		if (ImageType == NOP_IMAGE_TYPE) {
-			if (emlxs_start_abs_download(hba, &AifHdr, buffer,
-			    &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize,
-			    (AbsChangeParams) ? &AbsWakeUpParms : NULL,
-			    DwcFile)) {
-				EMLXS_MSGF(EMLXS_CONTEXT,
-				    &emlxs_download_failed_msg,
-				    "Failed to program flash.");
-
-				rval = EMLXS_IMAGE_FAILED;
-
-				goto SLI_DOWNLOAD_EXIT;
-			}
-
-		} else {
-
-			if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
-			    &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize)) {
-				EMLXS_MSGF(EMLXS_CONTEXT,
-				    &emlxs_download_failed_msg,
-				    "Failed to program flash.");
-
-				rval = EMLXS_IMAGE_FAILED;
-
-				goto SLI_DOWNLOAD_EXIT;
-			}
+	} else { /* Relative PRG file */
+		if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
+		    &WakeUpParms, 0)) {
+			EMLXS_MSGF(EMLXS_CONTEXT,
+			    &emlxs_download_failed_msg,
+			    "Failed to program flash.");
+
+			rval = EMLXS_IMAGE_FAILED;
+
+			goto SLI_DOWNLOAD_EXIT;
 		}
-
-	}	/* !SBUS_FCODE */
-
+	}
 
 SLI_DOWNLOAD_EXIT:
 
@@ -461,12 +433,13 @@
 			image_ptr  += count;
 		}
 
-		/* Set last two words of last payload with */
-		/* image size and block crc */
+		/* Set last three words of last payload with */
+		/* load address, image size and block crc */
 		if (flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) {
-			wptr = (uint32_t *)&payload[(xfer_size - 8)];
-			wptr[0] = file->image_size;
-			wptr[1] = file->block_crc;
+			wptr = (uint32_t *)&payload[(xfer_size - 12)];
+			wptr[0] = file->load_address;
+			wptr[1] = file->image_size;
+			wptr[2] = file->block_crc;
 		}
 
 		/* Send write request */
@@ -1082,6 +1055,7 @@
 			file->image_offset = entry->offset;
 			file->block_size   = entry->pad_size;
 			file->block_crc    = entry->checksum;
+			file->load_address = entry->entry_point;
 		} else {
 			file->image_offset = entry->offset +
 			    sizeof (emlxs_sli4_ufi_header_t);
@@ -1097,6 +1071,10 @@
 					file->block_size = (k + 8) -
 					    file->image_offset;
 
+					/* Read load_address */
+					value = *(wptr - 2);
+					file->load_address = BE_SWAP32(value);
+
 					/* Read block_crc */
 					value = *wptr;
 					file->block_crc = BE_SWAP32(value);
@@ -1116,7 +1094,7 @@
 		}
 
 		/* Make sure image will fit in block specified */
-		if (file->image_size + 8 > file->block_size) {
+		if (file->image_size + 12 > file->block_size) {
 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
 			    "%s: Image too large for block. image=%x block=%x",
 			    file->label, file->image_size, file->block_size);
@@ -1134,6 +1112,7 @@
 			file2->image_size = file->image_size;
 			file2->block_size = file->block_size;
 			file2->block_crc = file->block_crc;
+			file2->load_address = file->load_address;
 
 			/* Save FCOE version info */
 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
@@ -1150,6 +1129,7 @@
 			file2->image_size = file->image_size;
 			file2->block_size = file->block_size;
 			file2->block_crc = file->block_crc;
+			file2->load_address = file->load_address;
 		}
 	}
 
@@ -1173,9 +1153,10 @@
 		}
 
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
-		    "%s: type=%x block=%x image=%x offset=%x crc=%x",
+		    "%s: type=%x block=%x image=%x offset=%x crc=%x load=%x",
 		    file->label, file->type, file->block_size,
-		    file->image_size, file->image_offset, file->block_crc);
+		    file->image_size, file->image_offset, file->block_crc,
+		    file->load_address);
 	}
 
 	return (0);
@@ -1660,13 +1641,11 @@
 emlxs_start_abs_download(emlxs_hba_t *hba,
     PAIF_HDR AifHdr,
     caddr_t Buffer,
-    PWAKE_UP_PARMS WakeUpParms,
-    uint32_t MaxRbusSramSize,
-    uint32_t MaxIbusSramSize, PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile)
+    uint32_t len,
+    PWAKE_UP_PARMS WakeUpParms)
 {
 	emlxs_port_t *port = &PPORT;
 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
-	IMAGE_HDR ImageHdr;
 	uint32_t *Src;
 	uint32_t *Dst;
 	caddr_t DataBuffer = NULL;
@@ -1677,8 +1656,10 @@
 	uint32_t DlToAddr = AifHdr->ImageBase;
 	uint32_t DlCount;
 	uint32_t i;
-
-	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+	WAKE_UP_PARMS AbsWakeUpParms;
+	int32_t AbsChangeParams;
+
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
 	    "Performing absolute download...");
 
 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
@@ -1701,16 +1682,20 @@
 
 	mb = (MAILBOX *)mbox;
 
+	AbsChangeParams = emlxs_build_parms(Buffer,
+	    &AbsWakeUpParms, len, AifHdr);
+
 	Buffer += sizeof (AIF_HDR);
 
-	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash...");
-
-	if (DwcFile) {
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Erasing flash...");
+
+	if (AifHdr->ImageBase == 0x20000) {
+		/* DWC File */
 		emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0,
-		    0, 0, NULL);
+		    0, 0, NULL, 0);
 	} else {
 		emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount,
-		    ERASE_FLASH, 0, 0, 0, NULL);
+		    ERASE_FLASH, 0, 0, 0, NULL, 0);
 	}
 
 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
@@ -1723,7 +1708,7 @@
 		goto EXIT_ABS_DOWNLOAD;
 	}
 
-	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
 	    "Programming flash...");
 
 	while (DlByteCount) {
@@ -1750,7 +1735,7 @@
 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
 
 		emlxs_format_prog_flash(mbox, DlToAddr, DlCount,
-		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL);
+		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL, 0);
 
 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
 		    MBX_SUCCESS) {
@@ -1779,31 +1764,12 @@
 	}
 #endif  /* FMA_SUPPORT */
 
-	bzero((caddr_t)&ImageHdr, sizeof (IMAGE_HDR));
-	ImageHdr.Id.Type = FUNC_FIRMWARE;
-
-	switch (MaxRbusSramSize) {
-	case REDUCED_RBUS_SRAM_CFG:
-		ImageHdr.Id.Id = REDUCED_SRAM_CFG_PROG_ID;
-		break;
-	case FULL_RBUS_SRAM_CFG:
-		ImageHdr.Id.Id = FULL_SRAM_CFG_PROG_ID;
-		break;
-	default:
-		ImageHdr.Id.Id = OTHER_SRAM_CFG_PROG_ID;
-		break;
-	}
-
 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
 
-	if (AbsWakeUpParms) {
+	if (AbsChangeParams) {
 		rval =
-		    emlxs_update_wakeup_parms(hba, AbsWakeUpParms,
+		    emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
 		    WakeUpParms);
-	} else {
-		rval =
-		    emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
-		    &ImageHdr.Id, 1);
 	}
 
 EXIT_ABS_DOWNLOAD:
@@ -1827,16 +1793,20 @@
     uint32_t DlByteCount,
     uint32_t Function,
     uint32_t Complete,
-    uint32_t BdeAddress, uint32_t BdeSize, PROG_ID *ProgId)
+    uint32_t BdeAddress,
+    uint32_t BdeSize,
+    PROG_ID *ProgId,
+    uint32_t keep)
 {
 	MAILBOX *mb = (MAILBOX *)mbq;
 
 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
 
-	if (ProgId)
+	if (ProgId) {
 		mb->mbxCommand = MBX_DOWN_LOAD;
-	else
+	} else {
 		mb->mbxCommand = MBX_LOAD_SM;
+	}
 
 	mb->un.varLdSM.load_cmplt = Complete;
 	mb->un.varLdSM.method = DL_FROM_SLIM;
@@ -1844,6 +1814,7 @@
 	mb->un.varLdSM.erase_or_prog = Function;
 	mb->un.varLdSM.dl_to_adr = Base;
 	mb->un.varLdSM.dl_len = DlByteCount;
+	mb->un.varLdSM.keep = keep;
 
 	if (BdeSize) {
 		mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
@@ -1911,6 +1882,7 @@
 	MAILBOX *mb;
 	MAILBOXQ *mbox;
 	uint32_t rval = 0;
+	PROG_ID old_prog_id;
 
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
@@ -1928,6 +1900,7 @@
 		(void) emlxs_update_exp_rom(hba, WakeUpParms);
 	}
 
+	old_prog_id = WakeUpParms->u0.boot_bios_id;
 	WakeUpParms->u0.boot_bios_id = *prog_id;
 
 	emlxs_format_update_parms(mbox, WakeUpParms);
@@ -1937,6 +1910,7 @@
 		    "Unable to update boot wakeup parms: Mailbox cmd=%x "
 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
 
+		WakeUpParms->u0.boot_bios_id = old_prog_id;
 		rval = 1;
 	}
 
@@ -1958,6 +1932,7 @@
 	uint32_t rval = 0;
 	MAILBOXQ *mbox;
 	MAILBOX *mb;
+	PROG_ID old_prog_id;
 
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
@@ -1967,8 +1942,12 @@
 		return (1);
 	}
 
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+	    "FF: Updating parms...");
+
 	mb = (MAILBOX *)mbox;
 
+	old_prog_id = WakeUpParms->prog_id;
 	WakeUpParms->prog_id = *prog_id;
 
 	emlxs_format_update_parms(mbox, WakeUpParms);
@@ -1978,6 +1957,7 @@
 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
 
+		WakeUpParms->prog_id = old_prog_id;
 		rval = 1;
 	}
 
@@ -1998,6 +1978,7 @@
 	uint32_t rval = 0;
 	MAILBOXQ *mbox;
 	MAILBOX *mb;
+	PROG_ID old_prog_id;
 
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
@@ -2007,8 +1988,12 @@
 		return (1);
 	}
 
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+	    "SLI1: Updating parms...");
+
 	mb = (MAILBOX *)mbox;
 
+	old_prog_id = WakeUpParms->sli1_prog_id;
 	WakeUpParms->sli1_prog_id = *prog_id;
 
 	emlxs_format_update_parms(mbox, WakeUpParms);
@@ -2018,6 +2003,7 @@
 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
 
+		WakeUpParms->sli1_prog_id = old_prog_id;
 		rval = 1;
 	}
 
@@ -2038,6 +2024,7 @@
 	uint32_t rval = 0;
 	MAILBOXQ *mbox;
 	MAILBOX *mb;
+	PROG_ID old_prog_id;
 
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
@@ -2047,8 +2034,12 @@
 		return (1);
 	}
 
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+	    "SLI2: Updating parms...");
+
 	mb = (MAILBOX *)mbox;
 
+	old_prog_id = WakeUpParms->sli2_prog_id;
 	WakeUpParms->sli2_prog_id = *prog_id;
 
 	emlxs_format_update_parms(mbox, WakeUpParms);
@@ -2058,6 +2049,7 @@
 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
 
+		WakeUpParms->sli2_prog_id = old_prog_id;
 		rval = 1;
 	}
 
@@ -2078,6 +2070,7 @@
 	uint32_t rval = 0;
 	MAILBOXQ *mbox;
 	MAILBOX *mb;
+	PROG_ID old_prog_id;
 
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
@@ -2087,8 +2080,12 @@
 		return (1);
 	}
 
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+	    "SLI3: Updating parms...");
+
 	mb = (MAILBOX *)mbox;
 
+	old_prog_id = WakeUpParms->sli3_prog_id;
 	WakeUpParms->sli3_prog_id = *prog_id;
 
 	emlxs_format_update_parms(mbox, WakeUpParms);
@@ -2098,6 +2095,7 @@
 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
 
+		WakeUpParms->sli3_prog_id = old_prog_id;
 		rval = 1;
 	}
 
@@ -2118,6 +2116,7 @@
 	uint32_t rval = 0;
 	MAILBOXQ *mbox;
 	MAILBOX *mb;
+	PROG_ID old_prog_id;
 
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
@@ -2127,8 +2126,12 @@
 		return (1);
 	}
 
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+	    "SLI4: Updating parms...");
+
 	mb = (MAILBOX *)mbox;
 
+	old_prog_id = WakeUpParms->sli4_prog_id;
 	WakeUpParms->sli4_prog_id = *prog_id;
 
 	emlxs_format_update_parms(mbox, WakeUpParms);
@@ -2138,6 +2141,7 @@
 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
 
+		WakeUpParms->sli4_prog_id = old_prog_id;
 		rval = 1;
 	}
 
@@ -2150,13 +2154,184 @@
 } /* emlxs_update_sli4_wakeup_parms() */
 
 
+static uint32_t
+emlxs_clean_flash(emlxs_hba_t *hba,
+    PWAKE_UP_PARMS OldWakeUpParms, PWAKE_UP_PARMS NewWakeUpParms)
+{
+	emlxs_port_t *port = &PPORT;
+	PROG_ID load_list[MAX_LOAD_ENTRY];
+	PROG_ID *wakeup_list[MAX_LOAD_ENTRY];
+	uint32_t count;
+	uint32_t i;
+	uint32_t j;
+	uint32_t k = 0;
+	uint32_t *wptr;
+
+	if (!NewWakeUpParms) {
+		return (1);
+	}
+
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+	    "Cleaning flash...");
+
+	/* If old wakeup parameter list is available, */
+	/* then cleanup old entries */
+	if (OldWakeUpParms) {
+		if (bcmp(&OldWakeUpParms->prog_id, &NewWakeUpParms->prog_id,
+		    sizeof (PROG_ID))) {
+
+			wptr = (uint32_t *)&OldWakeUpParms->prog_id;
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "OLD:      prog_id: 0x%08x 0x%08x  Removing.",
+			    wptr[0], wptr[1]);
+
+			(void) emlxs_delete_load_entry(hba,
+			    &OldWakeUpParms->prog_id);
+		}
+
+		if (bcmp(&OldWakeUpParms->u0.boot_bios_id,
+		    &NewWakeUpParms->u0.boot_bios_id, sizeof (PROG_ID))) {
+
+			wptr = (uint32_t *)&OldWakeUpParms->u0.boot_bios_id;
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "OLD: boot_bios_id: 0x%08x 0x%08x  Removing.",
+			    wptr[0], wptr[1]);
+
+			(void) emlxs_delete_load_entry(hba,
+			    &OldWakeUpParms->u0.boot_bios_id);
+		}
+
+		if (bcmp(&OldWakeUpParms->sli1_prog_id,
+		    &NewWakeUpParms->sli1_prog_id, sizeof (PROG_ID))) {
+
+			wptr = (uint32_t *)&OldWakeUpParms->sli1_prog_id;
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "OLD: sli1_prog_id: 0x%08x 0x%08x  Removing.",
+			    wptr[0], wptr[1]);
+
+			(void) emlxs_delete_load_entry(hba,
+			    &OldWakeUpParms->sli1_prog_id);
+		}
+
+		if (bcmp(&OldWakeUpParms->sli2_prog_id,
+		    &NewWakeUpParms->sli2_prog_id, sizeof (PROG_ID))) {
+
+			wptr = (uint32_t *)&OldWakeUpParms->sli2_prog_id;
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "OLD: sli2_prog_id: 0x%08x 0x%08x  Removing.",
+			    wptr[0], wptr[1]);
+
+			(void) emlxs_delete_load_entry(hba,
+			    &OldWakeUpParms->sli2_prog_id);
+		}
+
+		if (bcmp(&OldWakeUpParms->sli3_prog_id,
+		    &NewWakeUpParms->sli3_prog_id, sizeof (PROG_ID))) {
+
+			wptr = (uint32_t *)&OldWakeUpParms->sli3_prog_id;
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "OLD: sli3_prog_id: 0x%08x 0x%08x  Removing.",
+			    wptr[0], wptr[1]);
+
+			(void) emlxs_delete_load_entry(hba,
+			    &OldWakeUpParms->sli3_prog_id);
+		}
+
+		if (bcmp(&OldWakeUpParms->sli4_prog_id,
+		    &NewWakeUpParms->sli4_prog_id, sizeof (PROG_ID))) {
+
+			wptr = (uint32_t *)&OldWakeUpParms->sli4_prog_id;
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "OLD: sli4_prog_id: 0x%08x 0x%08x  Removing.",
+			    wptr[0], wptr[1]);
+
+			(void) emlxs_delete_load_entry(hba,
+			    &OldWakeUpParms->sli4_prog_id);
+		}
+
+		return (0);
+	}
+
+	/* Otherwise use the current load list */
+	count = emlxs_get_load_list(hba, load_list);
+
+	if (!count) {
+		return (1);
+	}
+
+	/* Init the wakeup list */
+	wptr = (uint32_t *)&NewWakeUpParms->prog_id;
+	if (*wptr) {
+		wakeup_list[k++] = &NewWakeUpParms->prog_id;
+	}
+
+	wptr = (uint32_t *)&NewWakeUpParms->u0.boot_bios_id;
+	if (*wptr) {
+		wakeup_list[k++] = &NewWakeUpParms->u0.boot_bios_id;
+	}
+
+	wptr = (uint32_t *)&NewWakeUpParms->sli1_prog_id;
+	if (*wptr) {
+		wakeup_list[k++] = &NewWakeUpParms->sli1_prog_id;
+	}
+
+	wptr = (uint32_t *)&NewWakeUpParms->sli2_prog_id;
+	if (*wptr) {
+		wakeup_list[k++] = &NewWakeUpParms->sli2_prog_id;
+	}
+
+	wptr = (uint32_t *)&NewWakeUpParms->sli3_prog_id;
+	if (*wptr) {
+		wakeup_list[k++] = &NewWakeUpParms->sli3_prog_id;
+	}
+
+	wptr = (uint32_t *)&NewWakeUpParms->sli4_prog_id;
+	if (*wptr) {
+		wakeup_list[k++] = &NewWakeUpParms->sli4_prog_id;
+	}
+
+	if (k == 0) {
+		return (0);
+	}
+
+	/* Match load list to wakeup list */
+	for (i = 0; i < count; i++) {
+
+		wptr = (uint32_t *)&load_list[i];
+
+		for (j = 0; j < k; j++) {
+			if (bcmp((uint8_t *)wakeup_list[j],
+			    (uint8_t *)&load_list[i], sizeof (PROG_ID)) == 0) {
+				break;
+			}
+		}
+
+		/* No match */
+		if (j == k) {
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "Load List[%d]: %08x %08x  Removing.",
+			    i, wptr[0], wptr[1]);
+
+			(void) emlxs_delete_load_entry(hba, &load_list[i]);
+		} else {
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+			    "Load List[%d]: %08x %08x  Preserving.",
+			    i, wptr[0], wptr[1]);
+		}
+	}
+
+	return (0);
+
+} /* emlxs_clean_flash() */
+
+
 /* ARGSUSED */
 static uint32_t
 emlxs_start_rel_download(emlxs_hba_t *hba,
     PIMAGE_HDR ImageHdr,
     caddr_t Buffer,
     PWAKE_UP_PARMS WakeUpParms,
-    uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize)
+    uint32_t dwc_flag)
 {
 	emlxs_port_t *port = &PPORT;
 	MAILBOXQ *mbox;
@@ -2164,21 +2339,23 @@
 	uint32_t *Src;
 	uint32_t *Dst;
 	caddr_t DataBuffer = NULL;
-	uint32_t rval = 1;
-	uint32_t DlByteCount = ImageHdr->BlockSize;
+	uint32_t rval = 0;
+	uint32_t DlByteCount;
 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
 	uint32_t DlCount;
 	uint32_t i;
-
-	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-	    "Performing relative download...");
+	uint32_t *wptr;
+
+	wptr = (uint32_t *)&ImageHdr->Id;
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
+	    "Relative download: %08x %08x", wptr[0], wptr[1]);
 
 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
 	    KM_NOSLEEP)) == NULL) {
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
 		    "Unable to allocate data buffer.");
 
-		return (rval);
+		return (1);
 	}
 
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
@@ -2188,60 +2365,31 @@
 
 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
 
-		return (rval);
-	}
-
-	if (ImageHdr->Id.Type == FUNC_FIRMWARE) {
-		switch (MaxRbusSramSize) {
-		case REDUCED_RBUS_SRAM_CFG:
-			if (ImageHdr->Id.Id != REDUCED_SRAM_CFG_PROG_ID) {
-				EMLXS_MSGF(EMLXS_CONTEXT,
-				    &emlxs_image_bad_msg,
-				    "Invalid header id.");
-
-				return (1);
-			}
-			break;
-		case FULL_RBUS_SRAM_CFG:
-			if (ImageHdr->Id.Id != FULL_SRAM_CFG_PROG_ID) {
-				EMLXS_MSGF(EMLXS_CONTEXT,
-				    &emlxs_image_bad_msg,
-				    "Invalid header id.");
-
-				return (1);
-			}
-			break;
-		default:
-			if (ImageHdr->Id.Id != OTHER_SRAM_CFG_PROG_ID) {
-				EMLXS_MSGF(EMLXS_CONTEXT,
-				    &emlxs_image_bad_msg,
-				    "Invalid header id.");
-
-				return (1);
-			}
-			break;
-		}
+		return (1);
 	}
 
 	mb = (MAILBOX *)mbox;
 
+	DlByteCount = ImageHdr->BlockSize;
+
 	emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
-	    &ImageHdr->Id);
-
-	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash...");
-
-	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
+	    &ImageHdr->Id, 0);
+
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
+	    "  Erasing flash...");
+
+	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
+
+	if (rval) {
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
 		    "Unable to erase flash. Mailbox cmd=%x status=%x",
 		    mb->mbxCommand, mb->mbxStatus);
 
-		rval = 1;
-
 		goto EXIT_REL_DOWNLOAD;
 	}
 
-	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-	    "Programming flash...");
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
+	    "  Programming flash...");
 
 	while (DlByteCount) {
 		if (DlByteCount > SegSize) {
@@ -2269,16 +2417,16 @@
 		    0,
 		    DlCount,
 		    PROGRAM_FLASH,
-		    (DlByteCount) ? 0 : 1, 0, DlCount, &ImageHdr->Id);
-
-		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
-		    MBX_SUCCESS) {
+		    (DlByteCount) ? 0 : 1,
+		    0, DlCount, &ImageHdr->Id, dwc_flag);
+
+		rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
+
+		if (rval) {
 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
 			    "Unable to program flash. Mailbox cmd=%x status=%x",
 			    mb->mbxCommand, mb->mbxStatus);
 
-			rval = 1;
-
 			goto EXIT_REL_DOWNLOAD;
 		}
 
@@ -2297,57 +2445,73 @@
 	}
 #endif  /* FMA_SUPPORT */
 
+	/* Update wakeup parameters */
 	switch (ImageHdr->Id.Type) {
 	case TEST_PROGRAM:
-		rval = 0;
 		break;
 
 	case FUNC_FIRMWARE:
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "FF: Updating parms...");
-		rval =
-		    emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
-		    &ImageHdr->Id);
+		if (!dwc_flag) {
+			rval = emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
+			    &ImageHdr->Id);
+		} else {
+			WakeUpParms->prog_id = ImageHdr->Id;
+		}
 		break;
 
 	case BOOT_BIOS:
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "BOOT: Updating parms...");
-		rval =
-		    emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
-		    &ImageHdr->Id, 1);
+		if (!dwc_flag) {
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+			    "BOOT: Updating parms...");
+
+			rval = emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
+			    &ImageHdr->Id, 1);
+		} else {
+			if (hba->wakeup_parms.u0.boot_bios_wd[0]) {
+				WakeUpParms->u0.boot_bios_id = ImageHdr->Id;
+			}
+
+			if (!(hba->model_info.chip &
+			    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
+				WakeUpParms->u1.EROM_prog_id = ImageHdr->Id;
+			}
+		}
 		break;
 
 	case SLI1_OVERLAY:
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "SLI1: Updating parms...");
-		rval =
-		    emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
-		    &ImageHdr->Id);
+		if (!dwc_flag) {
+			rval = emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
+			    &ImageHdr->Id);
+		} else {
+			WakeUpParms->sli1_prog_id = ImageHdr->Id;
+		}
 		break;
 
 	case SLI2_OVERLAY:
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "SLI2: Updating parms...");
-		rval =
-		    emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
-		    &ImageHdr->Id);
+		if (!dwc_flag) {
+			rval = emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
+			    &ImageHdr->Id);
+		} else {
+			WakeUpParms->sli2_prog_id = ImageHdr->Id;
+		}
 		break;
 
 	case SLI3_OVERLAY:
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "SLI3: Updating parms...");
-		rval =
-		    emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
-		    &ImageHdr->Id);
+		if (!dwc_flag) {
+			rval = emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
+			    &ImageHdr->Id);
+		} else {
+			WakeUpParms->sli3_prog_id = ImageHdr->Id;
+		}
 		break;
 
 	case SLI4_OVERLAY:
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "SLI4: Updating parms...");
-		rval =
-		    emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
-		    &ImageHdr->Id);
+		if (!dwc_flag) {
+			rval = emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
+			    &ImageHdr->Id);
+		} else {
+			WakeUpParms->sli4_prog_id = ImageHdr->Id;
+		}
 		break;
 
 	default:
@@ -2371,6 +2535,74 @@
 } /* emlxs_start_rel_download() */
 
 
+static uint32_t
+emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer, emlxs_fw_image_t *fw_image)
+{
+	emlxs_port_t *port = &PPORT;
+	uint32_t rval = 0;
+	WAKE_UP_PARMS RelWakeUpParms;
+	WAKE_UP_PARMS WakeUpParms;
+	uint32_t i;
+	IMAGE_HDR ImageHdr;
+	caddr_t bptr;
+	uint32_t flash_cleaned = 0;
+
+	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 0)) {
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
+		    "Unable to get wakeup parameters.");
+
+		return (EMLXS_IMAGE_FAILED);
+	}
+
+download:
+
+	bcopy(&WakeUpParms, &RelWakeUpParms, sizeof (WAKE_UP_PARMS));
+
+	for (i = 0; i < MAX_PROG_TYPES; i++) {
+		if (!fw_image->prog[i].version) {
+			continue;
+		}
+
+		bptr = buffer + fw_image->prog[i].offset;
+
+		bcopy(bptr, &ImageHdr, sizeof (IMAGE_HDR));
+
+		rval = emlxs_start_rel_download(hba, &ImageHdr, bptr,
+		    &RelWakeUpParms, 1);
+
+		if (rval) {
+			EMLXS_MSGF(EMLXS_CONTEXT,
+			    &emlxs_download_failed_msg,
+			    "Failed to program flash.");
+
+			if ((rval == NO_FLASH_MEM_AVAIL) && !flash_cleaned) {
+				/* Cleanup using current load list */
+				(void) emlxs_clean_flash(hba, 0, &WakeUpParms);
+
+				flash_cleaned = 1;
+				goto download;
+			}
+
+			return (EMLXS_IMAGE_FAILED);
+		}
+	}
+
+	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
+	    "Updating wakeup parameters.");
+
+	if (emlxs_update_wakeup_parms(hba, &RelWakeUpParms,
+	    &RelWakeUpParms)) {
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
+		    "Unable to update parameters.");
+
+		return (EMLXS_IMAGE_FAILED);
+	}
+
+	return (0);
+
+} /* emlxs_proc_rel_2mb() */
+
+
 #define	FLASH_POLLING_BIT	0x80
 #define	FLASH_ERROR_BIT		0x20
 
@@ -2639,6 +2871,46 @@
 } /* emlxs_erase_fcode_flash() */
 
 
+static uint32_t
+emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId)
+{
+	emlxs_port_t *port = &PPORT;
+	MAILBOXQ *mbox = NULL;
+	MAILBOX *mb;
+	uint32_t rval = 0;
+
+	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
+	    KM_NOSLEEP)) == NULL) {
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+		    "Unable to allocate mailbox buffer.");
+
+		return (1);
+	}
+
+	mb = (MAILBOX *)mbox;
+	mb->mbxCommand = MBX_DEL_LD_ENTRY;
+	mb->un.varDelLdEntry.list_req = FLASH_LOAD_LIST;
+	mb->un.varDelLdEntry.prog_id = *progId;
+
+	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
+		    "Unable to delete load entry: Mailbox cmd=%x status=%x",
+		    mb->mbxCommand, mb->mbxStatus);
+
+		rval = 1;
+	}
+
+done:
+
+	if (mbox) {
+		kmem_free(mbox, sizeof (MAILBOXQ));
+	}
+
+	return (rval);
+
+} /* emlxs_delete_load_entry() */
+
+
 extern uint32_t
 emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
 {
@@ -2646,7 +2918,7 @@
 	LOAD_ENTRY *LoadEntry;
 	LOAD_LIST *LoadList = NULL;
 	uint32_t i;
-	uint32_t rval = 0;
+	uint32_t count = 0;
 
 	bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
 
@@ -2655,12 +2927,10 @@
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
 		    "Unable to allocate LOADLIST buffer.");
 
-		rval = 1;
 		goto done;
 	}
 
 	if (emlxs_read_load_list(hba, LoadList)) {
-		rval = 1;
 		goto done;
 	}
 
@@ -2668,10 +2938,11 @@
 		LoadEntry = &LoadList->load_entry[i];
 		if ((LoadEntry->un.wd[0] != 0) &&
 		    (LoadEntry->un.wd[0] != 0xffffffff)) {
-			load_list[i] = LoadEntry->un.id;
 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
-			    "Load List[%d]: %08x %08x", i,
+			    "Load List[%d]: %08x %08x", count,
 			    LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
+
+			load_list[count++] = LoadEntry->un.id;
 		}
 	}
 
@@ -2681,7 +2952,7 @@
 		kmem_free(LoadList, sizeof (LOAD_LIST));
 	}
 
-	return (rval);
+	return (count);
 
 } /* emlxs_get_load_list() */
 
@@ -2920,74 +3191,11 @@
 } /* emlxs_read_load_list() */
 
 
-static uint32_t
-emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize)
-{
-	uint32_t Version;
-
-	if (BufferSize < (SLI_VERSION_LOC + 4))
-		return (0xffffffff);
-
-	Buffer += SLI_VERSION_LOC;
-	Version = *((uint32_t *)Buffer);
-
-	return (Version);
-
-} /* emlxs_get_abs_image_type() */
-
-
-static uint32_t
-emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer,
-    uint32_t BufferSize, PAIF_HDR AifHeader)
-{
-	emlxs_port_t *port = &PPORT;
-	IMAGE_HDR ImageHdr;
-	uint32_t NextImage;
-	uint32_t i;
-	uint8_t *Sptr;
-	uint8_t *Dptr;
-	uint32_t HwId = 0xffffffff;
-
-	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
-
-	while (BufferSize > NextImage) {
-		Sptr = (uint8_t *)&Buffer[NextImage];
-		Dptr = (uint8_t *)&ImageHdr;
-		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
-			Dptr[i] = Sptr[i];
-		}
-
-		if (ImageHdr.BlockSize == 0xffffffff)
-			break;
-
-		switch (ImageHdr.Id.Type) {
-		case 6:
-		case 7:
-			if (HwId == 0xffffffff) {
-				HwId = ImageHdr.Id.Id;
-			}
-
-			if (HwId != ImageHdr.Id.Id) {
-				EMLXS_MSGF(EMLXS_CONTEXT,
-				    &emlxs_image_bad_msg,
-				    "Invalid hardware id. %x %x", HwId,
-				    ImageHdr.Id.Id);
-			}
-			break;
-		}
-
-		NextImage += ImageHdr.BlockSize;
-	}
-
-	return (HwId);
-
-} /* emlxs_get_dwc_image_type() */
-
 
 static int
 emlxs_build_parms(caddr_t Buffer,
     PWAKE_UP_PARMS AbsWakeUpParms,
-    uint32_t BufferSize, PAIF_HDR AifHeader, int32_t DwcFile)
+    uint32_t BufferSize, PAIF_HDR AifHeader)
 {
 	IMAGE_HDR ImageHdr;
 	uint32_t NextImage;
@@ -2998,7 +3206,8 @@
 
 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
 
-	if (!DwcFile && ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
+	if ((AifHeader->ImageBase != 0x20000) &&
+	    ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
 		return (FALSE);
 	}
 
@@ -3257,6 +3466,164 @@
 } /* emlxs_validate_version() */
 
 
+static void
+emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *fw_image)
+{
+	emlxs_port_t *port = &PPORT;
+	emlxs_vpd_t *vpd = &VPD;
+	uint32_t i;
+	uint32_t count;
+
+	/* Check for AWC file */
+	if (fw_image->awc.version) {
+		if (fw_image->awc.version == vpd->postKernRev) {
+			fw_image->awc.version = 0;
+		}
+
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+		    "AWC file: KERN: old=%s  new=%s  %s.",
+		    vpd->postKernName,
+		    fw_image->awc.label,
+		    (fw_image->awc.version)? "Update":"Skip");
+	}
+
+	/* Check for BWC file */
+	if (fw_image->bwc.version) {
+		if (strcmp(vpd->fcode_version, fw_image->bwc.label) == 0) {
+			fw_image->bwc.version = 0;
+		}
+
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+		    "BWC file: BOOT: old=%s  new=%s  %s.",
+		    vpd->fcode_version,
+		    fw_image->bwc.label,
+		    (fw_image->bwc.version)? "Update":"Skip");
+	}
+
+	/* Check for DWC file */
+	if (fw_image->dwc.version) {
+		/* Check for program files */
+		count = 0;
+		for (i = 0; i < MAX_PROG_TYPES; i++) {
+			if (!fw_image->prog[i].version) {
+				continue;
+			}
+
+			/* Skip components that don't need updating */
+			switch (i) {
+			case TEST_PROGRAM:
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: TEST:             new=%s  "
+				    "Update.",
+				    fw_image->prog[i].label);
+				break;
+
+			case BOOT_BIOS:
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: BOOT:             new=%s  "
+				    "Update.",
+				    fw_image->prog[i].label);
+				break;
+
+			case FUNC_FIRMWARE:
+				if (vpd->opFwRev &&
+				    (fw_image->prog[i].version ==
+				    vpd->opFwRev)) {
+					fw_image->prog[i].version = 0;
+				}
+
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: STUB: old=%s  new=%s  %s.",
+				    vpd->opFwName,
+				    fw_image->prog[i].label,
+				    (fw_image->prog[i].version)?
+				    "Update":"Skip");
+				break;
+
+			case SLI1_OVERLAY:
+				if (vpd->sli1FwRev &&
+				    (fw_image->prog[i].version ==
+				    vpd->sli1FwRev)) {
+					fw_image->prog[i].version = 0;
+				}
+
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: SLI1: old=%s  new=%s  %s.",
+				    vpd->sli1FwName,
+				    fw_image->prog[i].label,
+				    (fw_image->prog[i].version)?
+				    "Update":"Skip");
+				break;
+
+			case SLI2_OVERLAY:
+				if (vpd->sli2FwRev &&
+				    (fw_image->prog[i].version ==
+				    vpd->sli2FwRev)) {
+					fw_image->prog[i].version = 0;
+				}
+
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: SLI2: old=%s  new=%s  %s.",
+				    vpd->sli2FwName,
+				    fw_image->prog[i].label,
+				    (fw_image->prog[i].version)?
+				    "Update":"Skip");
+				break;
+
+			case SLI3_OVERLAY:
+				if (vpd->sli3FwRev &&
+				    (fw_image->prog[i].version ==
+				    vpd->sli3FwRev)) {
+					fw_image->prog[i].version = 0;
+				}
+
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: SLI3: old=%s  new=%s  %s.",
+				    vpd->sli3FwName,
+				    fw_image->prog[i].label,
+				    (fw_image->prog[i].version)?
+				    "Update":"Skip");
+				break;
+
+			case SLI4_OVERLAY:
+				if (vpd->sli4FwRev &&
+				    (fw_image->prog[i].version ==
+				    vpd->sli4FwRev)) {
+					fw_image->prog[i].version = 0;
+				}
+
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: SLI4: old=%s  new=%s  %s.",
+				    vpd->sli4FwRev,
+				    fw_image->prog[i].label,
+				    (fw_image->prog[i].version)?
+				    "Update":"Skip");
+				break;
+
+			default:
+				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+				    "DWC file: type=%x version=%x label=%s  "
+				    "Update.",
+				    i,
+				    fw_image->prog[i].version,
+				    fw_image->prog[i].label);
+			}
+
+			if (fw_image->prog[i].version) {
+				count++;
+			}
+		}
+
+		if (!count) {
+			fw_image->dwc.version = 0;
+		}
+	}
+
+	return;
+
+} /* emlxs_verify_image() */
+
+
 static uint32_t
 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
     emlxs_fw_image_t *image)
@@ -3266,6 +3633,7 @@
 	AIF_HDR AifHdr;
 	IMAGE_HDR ImageHdr;
 	uint32_t NextImage;
+	uint32_t count;
 	uint32_t FileType;
 	uint32_t FileLen = 0;
 	uint32_t TotalLen = 0;
@@ -3379,6 +3747,7 @@
 				NextImage = sizeof (AIF_HDR) + 4;
 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
 
+				count = 0;
 				while (BufferSize > NextImage) {
 					bcopy(&bptr[NextImage], &ImageHdr,
 					    sizeof (IMAGE_HDR));
@@ -3416,10 +3785,19 @@
 						return (rval);
 					}
 
+					count++;
 					NextImage += ImageHdr.BlockSize;
 
 				}	/* while () */
 
+				if (count == 0) {
+					EMLXS_MSGF(EMLXS_CONTEXT,
+					    &emlxs_image_bad_msg,
+					    "DWC file has no PRG images.");
+
+					return (EMLXS_IMAGE_BAD);
+				}
+
 				break;
 			}
 
@@ -3520,7 +3898,9 @@
 
 			NextImage += ImageHdr.BlockSize;
 		}
-	} else {
+
+	} else { /* PRG File */
+
 		/* Precheck image size */
 		if (Size < sizeof (IMAGE_HDR)) {
 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
@@ -3570,8 +3950,10 @@
 
 		/* Acquire the versions */
 		image->prog[type].version =
-		    (ImageHdr.Id.Type << 24) | (ImageHdr.Id.
-		    Id << 16) | (ImageHdr.Id.Ver << 8) | ImageHdr.Id.Rev;
+		    (ImageHdr.Id.Type << 24) |
+		    (ImageHdr.Id.Id << 16) |
+		    (ImageHdr.Id.Ver << 8) |
+		    ImageHdr.Id.Rev;
 
 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
 
@@ -3584,23 +3966,19 @@
 
 	/*
 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
-	 * image file is greater than version 3.8
+	 * image file is < version 3.8
 	 */
 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
-		if (image->prog[SLI2_OVERLAY].version != 0) {
-			ver = (image->prog[SLI2_OVERLAY].version &
-			    0x0000ff00) >> 8;
-
-			if ((((ver & 0xf0) == 0x30) &&
-			    ((ver & 0x0f) >= 0x08)) ||
-			    ((ver & 0xf0) > 0x30)) {
-				EMLXS_MSGF(EMLXS_CONTEXT,
-				    &emlxs_image_incompat_msg,
-				    "ASIC Check: Image requires DragonFly "
-				    "V2 ASIC");
-
-				return (EMLXS_IMAGE_INCOMPATIBLE);
-			}
+		ver = (image->prog[SLI2_OVERLAY].version &
+		    0x0000ff00) >> 8;
+
+		if (ver >= 0x38) {
+			EMLXS_MSGF(EMLXS_CONTEXT,
+			    &emlxs_image_incompat_msg,
+			    "ASIC Check: Image requires DragonFly "
+			    "V2 ASIC");
+
+			return (EMLXS_IMAGE_INCOMPATIBLE);
 		}
 	}
 
@@ -3752,63 +4130,14 @@
     uint32_t offline, emlxs_fw_image_t *fw_image)
 {
 	emlxs_port_t *port = &PPORT;
-	caddr_t AwcBuffer = NULL;
-	caddr_t BwcBuffer = NULL;
-	caddr_t DwcBuffer = NULL;
-	AIF_HDR *AwcAifHdr;
-	AIF_HDR *BwcAifHdr;
-	AIF_HDR *DwcAifHdr;
-	uint32_t BWCflag;
-	emlxs_vpd_t *vpd;
-	uint32_t i;
-	uint32_t count;
-	uint32_t extType = 0;
 	uint32_t rval = 0;
 
-	vpd = &VPD;
-
-	/* Check for AWC file */
-	if (fw_image->awc.version) {
-		AwcBuffer = buffer + fw_image->awc.offset;
-		AwcAifHdr = (AIF_HDR *)AwcBuffer;
-	}
-
-	/* Check for BWC file */
-	if (fw_image->bwc.version) {
-		extType = BWCext;
-		BwcBuffer = buffer + fw_image->bwc.offset;
-		BwcAifHdr = (AIF_HDR *)BwcBuffer;
-	}
-
-	/* Check for DWC file */
-	if (fw_image->dwc.version) {
-		extType = DWCext;
-		DwcBuffer = buffer + fw_image->dwc.offset;
-		DwcAifHdr = (AIF_HDR *)DwcBuffer;
-	}
-
-	/* Check for program files */
-	count = 0;
-	for (i = 0; i < MAX_PROG_TYPES; i++) {
-		if (fw_image->prog[i].version) {
-			count++;
-		}
-	}
-
-	if (count > 1) {
-		extType = ALLext;
-
-		if (fw_image->bwc.version) {
-			BWCflag = ALL_WITH_BWC;
-		} else {
-			BWCflag = ALL_WITHOUT_BWC;
-		}
-	} else {
-		BWCflag = NO_ALL;
-	}
-
 	/* If nothing to download then quit now */
-	if (!AwcBuffer && !DwcBuffer && !BwcBuffer) {
+	if (!fw_image->awc.version &&
+	    !fw_image->dwc.version &&
+	    !fw_image->bwc.version) {
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
+		    "Nothing new to update.  Exiting.");
 		return (0);
 	}
 
@@ -3825,65 +4154,33 @@
 		}
 	}
 
-	if (AwcBuffer) {
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "AWC file: KERN: old=%s  new=%s ", vpd->postKernName,
-		    fw_image->awc.label);
-
+	if (fw_image->awc.version) {
 		rval = emlxs_proc_abs_2mb(hba,
-		    AwcAifHdr, AwcBuffer, FILE_TYPE_AWC, BWCflag, extType);
+		    (buffer + fw_image->awc.offset),
+		    FILE_TYPE_AWC, 0);
 
 		if (rval) {
 			goto SLI_DOWNLOAD_2MB_EXIT;
 		}
 	}
 
-	if (DwcBuffer) {
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "DWC file: TEST:             new=%s ",
-		    fw_image->prog[TEST_PROGRAM].label);
-
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "DWC file: STUB: old=%s  new=%s ", vpd->opFwName,
-		    fw_image->prog[FUNC_FIRMWARE].label);
-
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "DWC file: SLI1: old=%s  new=%s ", vpd->sli1FwName,
-		    fw_image->prog[SLI1_OVERLAY].label);
-
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "DWC file: SLI2: old=%s  new=%s ", vpd->sli2FwName,
-		    fw_image->prog[SLI2_OVERLAY].label);
-
-		if (vpd->sli3FwRev || fw_image->prog[SLI3_OVERLAY].version) {
-			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-			    "DWC file: SLI3: old=%s  new=%s ",
-			    vpd->sli3FwName,
-			    fw_image->prog[SLI3_OVERLAY].label);
-		}
-
-		if (vpd->sli4FwRev || fw_image->prog[SLI4_OVERLAY].version) {
-			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-			    "DWC file: SLI4: old=%s  new=%s ",
-			    vpd->sli4FwName,
-			    fw_image->prog[SLI4_OVERLAY].label);
-		}
-
+	if (fw_image->bwc.version) {
 		rval = emlxs_proc_abs_2mb(hba,
-		    DwcAifHdr, DwcBuffer, FILE_TYPE_DWC, BWCflag, extType);
+		    (buffer + fw_image->bwc.offset),
+		    FILE_TYPE_BWC,
+		    (fw_image->dwc.version)? ALLext:BWCext);
 
 		if (rval) {
 			goto SLI_DOWNLOAD_2MB_EXIT;
 		}
 	}
 
-	if (BwcBuffer) {
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
-		    "BWC file: BOOT: old=%s  new=%s ", vpd->fcode_version,
-		    fw_image->bwc.label);
-
-		rval = emlxs_proc_abs_2mb(hba,
-		    BwcAifHdr, BwcBuffer, FILE_TYPE_BWC, BWCflag, extType);
+	if (fw_image->dwc.version) {
+		rval = emlxs_proc_rel_2mb(hba, buffer, fw_image);
+
+		if (rval) {
+			goto SLI_DOWNLOAD_2MB_EXIT;
+		}
 	}
 
 SLI_DOWNLOAD_2MB_EXIT:
@@ -3912,22 +4209,21 @@
  *
  */
 static uint32_t
-emlxs_proc_abs_2mb(emlxs_hba_t *hba,
-    PAIF_HDR AifHdr,
-    caddr_t EntireBuffer,
-    uint32_t FileType, uint32_t BWCflag, uint32_t extType)
+emlxs_proc_abs_2mb(emlxs_hba_t *hba, caddr_t EntireBuffer,
+    uint32_t FileType, uint32_t extType)
 {
 	emlxs_port_t *port = &PPORT;
+	PAIF_HDR AifHdr;
 	caddr_t Buffer = NULL;
 	caddr_t DataBuffer = NULL;
 	uint32_t *Src;
 	uint32_t *Dst;
 	MAILBOXQ *mbox;
 	MAILBOX *mb;
-	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
+	uint32_t DlByteCount;
 	uint32_t rval = 0;
 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
-	uint32_t DlToAddr = AifHdr->ImageBase;
+	uint32_t DlToAddr;
 	uint32_t DlCount;
 	WAKE_UP_PARMS AbsWakeUpParms;
 	uint32_t i;
@@ -3935,9 +4231,11 @@
 	uint32_t EraseByteCount;
 	uint32_t AreaId;
 	uint32_t RspProgress = 0;
-	uint32_t numBootImage = 0;
-	uint32_t ParamsChg = 0;
-	uint32_t BufferSize;
+	uint32_t ParamsChg;
+
+	AifHdr = (PAIF_HDR)EntireBuffer;
+	DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
+	DlToAddr = AifHdr->ImageBase;
 
 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
 	    KM_NOSLEEP)) == NULL) {
@@ -3947,8 +4245,6 @@
 		return (EMLXS_IMAGE_FAILED);
 	}
 
-	bzero(DataBuffer, sizeof (DL_SLIM_SEG_BYTE_COUNT));
-
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
@@ -3961,18 +4257,18 @@
 
 	mb = (MAILBOX *)mbox;
 
-	BufferSize = DlByteCount + sizeof (AIF_HDR) + sizeof (uint32_t);
 	Buffer = EntireBuffer + sizeof (AIF_HDR);
 
 	switch (FileType) {
 	case FILE_TYPE_AWC:
+		ParamsChg = 0;
 		break;
 
 	case FILE_TYPE_BWC:
-		ParamsChg = emlxs_build_parms_2mb_bwc(hba,
+		rval = emlxs_build_parms_2mb_bwc(hba,
 		    AifHdr, extType, &AbsWakeUpParms);
 
-		if (ParamsChg == FALSE) {
+		if (rval == FALSE) {
 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
 			    "BWC build parms failed.");
 
@@ -3980,22 +4276,7 @@
 
 			goto EXIT_ABS_DOWNLOAD;
 		}
-		break;
-
-	case FILE_TYPE_DWC:
-		ParamsChg = emlxs_build_parms_2mb_dwc(hba,
-		    Buffer,
-		    BufferSize,
-		    AifHdr, &AbsWakeUpParms, BWCflag, extType, &numBootImage);
-
-		if (ParamsChg == FALSE) {
-			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
-			    "DWC build parms failed.");
-
-			rval = EMLXS_IMAGE_FAILED;
-
-			goto EXIT_ABS_DOWNLOAD;
-		}
+		ParamsChg = 1;
 		break;
 
 	default:
@@ -4190,7 +4471,7 @@
 
 	/* Read wakeup paramters */
 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
-	    CFG_DATA_NO_REGION) {
+	    (uint32_t)CFG_DATA_NO_REGION) {
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
 		    "Unable to get BWC parameters.");
 		return (FALSE);
@@ -4242,148 +4523,6 @@
 } /* emlxs_build_parms_2mb_bwc() */
 
 
-/* ARGSUSED */
-static uint32_t
-emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba,
-    caddr_t Buffer,
-    uint32_t BufferSize,
-    PAIF_HDR AifHeader,
-    PWAKE_UP_PARMS AbsWakeUpParms,
-    uint32_t BWCflag, uint32_t extType, uint32_t *numBootImage)
-{
-	emlxs_port_t *port = &PPORT;
-	uint32_t NextImage;
-	uint32_t i;
-	IMAGE_HDR ImageHdr;
-	uint32_t *ptr1;
-	uint32_t *ptr2;
-	PROG_ID BootId[MAX_BOOTID];
-	uint32_t ChangeParams = FALSE;
-	WAKE_UP_PARMS WakeUpParms;
-	caddr_t Sptr;
-	caddr_t Dptr;
-
-	bzero(&BootId, (sizeof (PROG_ID)) * MAX_BOOTID);
-
-	/* Read wakeup paramters */
-	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
-	    CFG_DATA_NO_REGION) {
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
-		    "Unable to get DWC parameters.");
-		return (FALSE);
-	}
-
-	bcopy((caddr_t)AbsWakeUpParms, (caddr_t)&WakeUpParms,
-	    sizeof (WAKE_UP_PARMS));
-
-	if (((BWCflag == ALL_WITHOUT_BWC) || (extType == DWCext)) &&
-	    (WakeUpParms.u0.boot_bios_wd[0])) {
-		*numBootImage = 0;
-	}
-
-	/* incoming buffer is without aif header */
-	NextImage = 0x84 - sizeof (AIF_HDR);
-	BufferSize -= (sizeof (AIF_HDR) + sizeof (uint32_t));
-
-	while (BufferSize > NextImage) {
-		Sptr = &Buffer[NextImage];
-		Dptr = (caddr_t)&ImageHdr;
-		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
-			Dptr[i] = Sptr[i];
-		}
-
-		if (ImageHdr.BlockSize == 0xffffffff) {
-			break;
-		}
-
-		switch (ImageHdr.Id.Type) {
-		case TEST_PROGRAM:
-			break;
-
-		case FUNC_FIRMWARE:
-			AbsWakeUpParms->prog_id = ImageHdr.Id;
-			ChangeParams = TRUE;
-			break;
-
-		case BOOT_BIOS:
-			if (!WakeUpParms.u0.boot_bios_wd[0]) {
-				if (extType == DWCext) {
-					break;
-				} else if (BWCflag == ALL_WITHOUT_BWC) {
-					/* for possible future changes */
-					break;
-				}
-			}
-			ChangeParams = TRUE;
-
-			if (*numBootImage < MAX_BOOTID) {
-				BootId[*numBootImage] = ImageHdr.Id;
-				(*numBootImage)++;
-			}
-			break;
-
-		case SLI1_OVERLAY:
-			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
-			ChangeParams = TRUE;
-			break;
-
-		case SLI2_OVERLAY:
-			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
-			ChangeParams = TRUE;
-			break;
-
-		case SLI3_OVERLAY:
-			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
-			ChangeParams = TRUE;
-			break;
-
-		case SLI4_OVERLAY:
-			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
-			ChangeParams = TRUE;
-			break;
-		}
-
-		NextImage += ImageHdr.BlockSize;
-	}
-
-	if ((ChangeParams) && ((BWCflag == ALL_WITHOUT_BWC) ||
-	    (extType == DWCext))) {
-
-		if (*numBootImage > 1) {
-			for (i = 0; i < *numBootImage; i++) {
-				ptr1 =
-				    (uint32_t *)&WakeUpParms.u0.
-				    boot_bios_id;
-				ptr2 = (uint32_t *)&BootId[i];
-
-				if (ptr1[0] == ptr2[0]) {
-					AbsWakeUpParms->u1.EROM_prog_id =
-					    BootId[i];
-					(void) emlxs_update_exp_rom(hba,
-					    AbsWakeUpParms);
-					break;
-				}
-			}
-		} else {
-			if (*numBootImage == 1) {
-				ptr2 = (uint32_t *)&BootId[0];
-
-				if (WakeUpParms.u0.boot_bios_wd[0] == ptr2[0]) {
-					AbsWakeUpParms->u1.EROM_prog_id =
-					    BootId[0];
-					(void) emlxs_update_exp_rom(hba,
-					    AbsWakeUpParms);
-				}
-			}
-		}
-	}
-
-	return (ChangeParams);
-
-
-} /* emlxs_build_parms_2mb_dwc() */
-
-
 extern uint32_t
 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
     uint32_t *MaxIbusSize)
@@ -4394,6 +4533,14 @@
 	uint32_t *Uptr;
 	uint32_t rval = 0;
 
+	if (MaxRbusSize) {
+		*MaxRbusSize = 0;
+	}
+
+	if (MaxIbusSize) {
+		*MaxIbusSize = 0;
+	}
+
 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
 	    KM_NOSLEEP)) == NULL) {
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
@@ -4425,8 +4572,13 @@
 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
 	}
 
-	*MaxRbusSize = Uptr[0];
-	*MaxIbusSize = Uptr[1];
+	if (MaxRbusSize) {
+		*MaxRbusSize = Uptr[0];
+	}
+
+	if (MaxIbusSize) {
+		*MaxIbusSize = Uptr[1];
+	}
 
 Exit_Function:
 
@@ -4684,6 +4836,7 @@
 	emlxs_vpd_t *vpd;
 	PROG_ID load_list[MAX_LOAD_ENTRY];
 	uint32_t i;
+	uint32_t count;
 
 	vpd = &VPD;
 
@@ -4716,12 +4869,14 @@
 		    &hba->wakeup_parms.u1.EROM_prog_id, 0);
 	} else {	/* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
 
-		if (emlxs_get_load_list(hba, load_list)) {
+		count = emlxs_get_load_list(hba, load_list);
+
+		if (!count) {
 			return (FC_FAILURE);
 		}
 
 		/* Scan load list for a boot image */
-		for (i = 0; i < MAX_LOAD_ENTRY; i++) {
+		for (i = 0; i < count; i++) {
 			if (load_list[i].Type == BOOT_BIOS) {
 				/* Update the parms with the boot image id */
 				/* Don't load the EROM this time */
@@ -4732,7 +4887,7 @@
 			}
 		}
 
-		if (i == MAX_LOAD_ENTRY) {
+		if (i == count) {
 			return (EMLXS_NO_BOOT_CODE);
 		}
 	}
--- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c	Wed Aug 18 15:52:48 2010 -0600
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Emulex.  All rights reserved.
+ * Copyright 2010 Emulex.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1353,6 +1353,7 @@
 			if (vport->vpi == 0) {
 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg,
 				    "%s%s%s", linkspeed, topology, mode);
+
 			} else if (npiv_linkup) {
 				EMLXS_MSGF(EMLXS_CONTEXT,
 				    &emlxs_npiv_link_up_msg, "%s%s%s",
@@ -1372,6 +1373,7 @@
 			if (vport->vpi == 0) {
 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg,
 				    "%s%s%s *", linkspeed, topology, mode);
+
 			} else if (npiv_linkup) {
 				EMLXS_MSGF(EMLXS_CONTEXT,
 				    &emlxs_npiv_link_up_msg, "%s%s%s *",
--- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c	Wed Aug 18 15:52:48 2010 -0600
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Emulex.  All rights reserved.
+ * Copyright 2010 Emulex.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -196,6 +196,7 @@
 	uint32_t read_rev_reset;
 	uint32_t key = 0;
 	uint32_t fw_check;
+	uint32_t kern_update = 0;
 	uint32_t rval = 0;
 	uint32_t offset;
 	uint8_t vpd_data[DMP_VPD_SIZE];
@@ -215,6 +216,29 @@
 		(void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
 	}
 
+	/*
+	 * Get a buffer which will be used repeatedly for mailbox commands
+	 */
+	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
+
+	mb = (MAILBOX *)mbq;
+
+	hba->mbox_queue_flag = 0;
+	hba->sli.sli3.hc_copy = 0;
+	hba->fc_edtov = FF_DEF_EDTOV;
+	hba->fc_ratov = FF_DEF_RATOV;
+	hba->fc_altov = FF_DEF_ALTOV;
+	hba->fc_arbtov = FF_DEF_ARBTOV;
+
+	/* Set the fw_check flag */
+	fw_check = cfg[CFG_FW_CHECK].current;
+
+	if ((fw_check & 0x04) ||
+	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
+		kern_update = 1;
+	}
+
+reset:
 	/* Initialize sli mode based on configuration parameter */
 	switch (cfg[CFG_SLI_MODE].current) {
 	case 2:	/* SLI2 mode */
@@ -244,24 +268,6 @@
 		sli_mode_mask = EMLXS_SLI2_MASK;
 	}
 
-	/* Set the fw_check flag */
-	fw_check = cfg[CFG_FW_CHECK].current;
-
-	hba->mbox_queue_flag = 0;
-	hba->sli.sli3.hc_copy = 0;
-	hba->fc_edtov = FF_DEF_EDTOV;
-	hba->fc_ratov = FF_DEF_RATOV;
-	hba->fc_altov = FF_DEF_ALTOV;
-	hba->fc_arbtov = FF_DEF_ARBTOV;
-
-	/*
-	 * Get a buffer which will be used repeatedly for mailbox commands
-	 */
-	mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
-
-	mb = (MAILBOX *)mbq;
-reset:
-
 	/* Reset & Initialize the adapter */
 	if (emlxs_sli3_hba_init(hba)) {
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
@@ -682,8 +688,11 @@
 	 * If firmware checking is enabled and the adapter model indicates
 	 * a firmware image, then perform firmware version check
 	 */
-	if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
-	    hba->model_info.fwid) || ((fw_check == 2) &&
+	hba->fw_flag = 0;
+	hba->fw_timer = 0;
+
+	if (((fw_check & 0x1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
+	    hba->model_info.fwid) || ((fw_check & 0x2) &&
 	    hba->model_info.fwid)) {
 		emlxs_firmware_t *fw;
 
@@ -701,7 +710,14 @@
 		 * versions of adapter
 		 */
 		if (fw) {
-			if ((fw->kern && (vpd->postKernRev != fw->kern)) ||
+			if (!kern_update &&
+			    ((fw->kern && (vpd->postKernRev != fw->kern)) ||
+			    (fw->stub && (vpd->opFwRev != fw->stub)))) {
+
+				hba->fw_flag |= FW_UPDATE_NEEDED;
+
+			} else if ((fw->kern && (vpd->postKernRev !=
+			    fw->kern)) ||
 			    (fw->stub && (vpd->opFwRev != fw->stub)) ||
 			    (fw->sli1 && (vpd->sli1FwRev != fw->sli1)) ||
 			    (fw->sli2 && (vpd->sli2FwRev != fw->sli2)) ||
@@ -728,6 +744,9 @@
 						EMLXS_MSGF(EMLXS_CONTEXT,
 						    &emlxs_init_msg,
 						    "Firmware update failed.");
+
+						hba->fw_flag |=
+						    FW_UPDATE_NEEDED;
 					}
 #ifdef MODFW_SUPPORT
 					/*
@@ -3569,8 +3588,9 @@
 
 		iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX;
 
-		if (dbuf->db_data_size ==
-		    fct_task->task_expected_xfer_length)
+		if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) &&
+		    (dbuf->db_data_size ==
+		    fct_task->task_expected_xfer_length))
 			iocb->ULPCT = 0x1;
 			/* enable auto-rsp AP feature */
 	}
--- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c	Wed Aug 18 15:52:48 2010 -0600
@@ -180,6 +180,7 @@
 	uint8_t *outptr;
 	uint32_t status;
 	uint32_t fw_check;
+	uint32_t kern_update = 0;
 	emlxs_firmware_t hba_fw;
 	emlxs_firmware_t *fw;
 
@@ -192,6 +193,11 @@
 	/* Set the fw_check flag */
 	fw_check = cfg[CFG_FW_CHECK].current;
 
+	if ((fw_check & 0x04) ||
+	    (hba->fw_flag & FW_UPDATE_KERNEL)) {
+		kern_update = 1;
+	}
+
 	hba->mbox_queue_flag = 0;
 	hba->fc_edtov = FF_DEF_EDTOV;
 	hba->fc_ratov = FF_DEF_RATOV;
@@ -532,8 +538,11 @@
 	 * If firmware checking is enabled and the adapter model indicates
 	 * a firmware image, then perform firmware version check
 	 */
-	if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
-	    hba->model_info.fwid) || ((fw_check == 2) &&
+	hba->fw_flag = 0;
+	hba->fw_timer = 0;
+
+	if (((fw_check & 0x1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) &&
+	    hba->model_info.fwid) || ((fw_check & 0x2) &&
 	    hba->model_info.fwid)) {
 
 		/* Find firmware image indicated by adapter model */
@@ -563,7 +572,13 @@
 				hba_fw.sli4 = vpd->sli4FwRev;
 			}
 
-			if ((fw->kern && (hba_fw.kern != fw->kern)) ||
+			if (!kern_update &&
+			    ((fw->kern && (hba_fw.kern != fw->kern)) ||
+			    (fw->stub && (hba_fw.stub != fw->stub)))) {
+
+				hba->fw_flag |= FW_UPDATE_NEEDED;
+
+			} else if ((fw->kern && (hba_fw.kern != fw->kern)) ||
 			    (fw->stub && (hba_fw.stub != fw->stub)) ||
 			    (fw->sli1 && (hba_fw.sli1 != fw->sli1)) ||
 			    (fw->sli2 && (hba_fw.sli2 != fw->sli2)) ||
@@ -591,6 +606,9 @@
 						EMLXS_MSGF(EMLXS_CONTEXT,
 						    &emlxs_init_msg,
 						    "Firmware update failed.");
+
+						hba->fw_flag |=
+						    FW_UPDATE_NEEDED;
 					}
 #ifdef MODFW_SUPPORT
 					/*
@@ -6689,6 +6707,7 @@
 emlxs_sli4_check_fcf_config(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec)
 {
 	int i;
+	uint32_t rval = 1;
 
 	if (!(hba->flag & FC_FIP_SUPPORTED)) {
 		if (!hba->sli.sli4.cfgFCOE.length) {
@@ -6718,12 +6737,15 @@
 	/* Just check FabricName for now */
 	for (i = 0; i < MAX_FCFCONNECTLIST_ENTRIES; i++) {
 		if ((hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) &&
-		    (bcmp((char *)fcfrec->fabric_name_identifier,
-		    hba->sli.sli4.cfgFCF.entry[i].FabricName, 8) == 0)) {
-			return (1);  /* success */
-		}
-	}
-	return (0);
+		    (hba->sli.sli4.cfgFCF.entry[i].Valid)) {
+			rval = 0;
+			if (bcmp((char *)fcfrec->fabric_name_identifier,
+			    hba->sli.sli4.cfgFCF.entry[i].FabricName, 8) == 0) {
+				return (1);  /* success */
+			}
+		}
+	}
+	return (rval);
 }
 
 
--- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c	Wed Aug 18 15:52:48 2010 -0600
@@ -46,6 +46,7 @@
 static void	emlxs_fca_attach(emlxs_hba_t *hba);
 static void	emlxs_fca_detach(emlxs_hba_t *hba);
 static void	emlxs_drv_banner(emlxs_hba_t *hba);
+static int32_t	emlxs_fca_reset(opaque_t fca_port_handle, uint32_t cmd);
 
 static int32_t	emlxs_get_props(emlxs_hba_t *hba);
 static int32_t	emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp);
@@ -268,7 +269,7 @@
 	emlxs_ub_free,
 	emlxs_ub_release,
 	emlxs_pkt_abort,
-	emlxs_reset,
+	emlxs_fca_reset,
 	emlxs_port_manage,
 	emlxs_get_device,
 	emlxs_notify
@@ -306,7 +307,7 @@
 	emlxs_ub_free,
 	emlxs_ub_release,
 	emlxs_pkt_abort,
-	emlxs_reset,
+	emlxs_fca_reset,
 	emlxs_port_manage,
 	emlxs_get_device,
 	emlxs_notify
@@ -344,7 +345,7 @@
 	emlxs_ub_free,
 	emlxs_ub_release,
 	emlxs_pkt_abort,
-	emlxs_reset,
+	emlxs_fca_reset,
 	emlxs_port_manage,
 	emlxs_get_device,
 	emlxs_notify
@@ -375,7 +376,7 @@
 	emlxs_ub_free,
 	emlxs_ub_release,
 	emlxs_pkt_abort,
-	emlxs_reset,
+	emlxs_fca_reset,
 	emlxs_port_manage,
 	emlxs_get_device,
 	emlxs_notify
@@ -3851,21 +3852,13 @@
 
 
 extern int32_t
-emlxs_reset(opaque_t fca_port_handle, uint32_t cmd)
-{
-	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
+emlxs_reset(emlxs_port_t *port, uint32_t cmd)
+{
 	emlxs_hba_t	*hba = HBA;
 	int		rval;
 	int		ret;
 	clock_t		timeout;
 
-	if (!(port->flag & EMLXS_PORT_BOUND)) {
-		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
-		    "fca_reset failed. Port not bound.");
-
-		return (FC_UNBOUND);
-	}
-
 	switch (cmd) {
 	case FC_FCA_LINK_RESET:
 
@@ -3875,7 +3868,7 @@
 		}
 
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
-		    "fca_reset: Resetting Link.");
+		    "Resetting Link.");
 
 		mutex_enter(&EMLXS_LINKUP_LOCK);
 		hba->linkup_wait_flag = TRUE;
@@ -3910,7 +3903,7 @@
 	case FC_FCA_CORE:
 #ifdef DUMP_SUPPORT
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
-		    "fca_reset: Core dump.");
+		    "Dumping Core.");
 
 		/* Schedule a USER dump */
 		emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0);
@@ -3925,7 +3918,7 @@
 	case FC_FCA_RESET_CORE:
 
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
-		    "fca_reset: Resetting Adapter.");
+		    "Resetting Adapter.");
 
 		rval = FC_SUCCESS;
 
@@ -3933,7 +3926,7 @@
 			(void) emlxs_online(hba);
 		} else {
 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
-			    "fca_reset: Adapter reset failed. Device busy.");
+			    "Adapter reset failed. Device busy.");
 
 			rval = FC_DEVICE_BUSY;
 		}
@@ -3942,7 +3935,7 @@
 
 	default:
 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
-		    "fca_reset: Unknown command. cmd=%x", cmd);
+		    "emlxs_reset: Unknown command. cmd=%x", cmd);
 
 		break;
 	}
@@ -3952,6 +3945,64 @@
 } /* emlxs_reset() */
 
 
+static int32_t
+emlxs_fca_reset(opaque_t fca_port_handle, uint32_t cmd)
+{
+	emlxs_port_t	*port = (emlxs_port_t *)fca_port_handle;
+	emlxs_hba_t	*hba = HBA;
+	int32_t		rval;
+
+	if (!(port->flag & EMLXS_PORT_BOUND)) {
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
+		    "fca_reset: Port not bound.");
+
+		return (FC_UNBOUND);
+	}
+
+	switch (cmd) {
+	case FC_FCA_LINK_RESET:
+		if (hba->fw_flag & FW_UPDATE_NEEDED) {
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
+			    "fca_reset: FC_FCA_LINK_RESET -> FC_FCA_RESET");
+			cmd = FC_FCA_RESET;
+		} else {
+			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
+			    "fca_reset: FC_FCA_LINK_RESET");
+		}
+		break;
+
+	case FC_FCA_CORE:
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
+		    "fca_reset: FC_FCA_CORE");
+		break;
+
+	case FC_FCA_RESET:
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
+		    "fca_reset: FC_FCA_RESET");
+		break;
+
+	case FC_FCA_RESET_CORE:
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
+		    "fca_reset: FC_FCA_RESET_CORE");
+		break;
+
+	default:
+		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
+		    "fca_reset: Unknown command. cmd=%x", cmd);
+		return (FC_FAILURE);
+	}
+
+	if (hba->fw_flag & FW_UPDATE_NEEDED) {
+		hba->fw_flag |= FW_UPDATE_KERNEL;
+	}
+
+	rval = emlxs_reset(port, cmd);
+
+	return (rval);
+
+} /* emlxs_fca_reset() */
+
+
 extern int
 emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm)
 {
@@ -6862,6 +6913,18 @@
 		}
 		break;
 
+	case CFG_FW_CHECK:
+		/* The 0x2 bit implies the 0x1 bit will also be set */
+		if (new_value & 0x2) {
+			new_value |= 0x1;
+		}
+
+		/* The 0x4 bit should not be set if 0x1 or 0x2 is not set */
+		if (!(new_value & 0x3) && (new_value & 0x4)) {
+			new_value &= ~0x4;
+		}
+		break;
+
 	case CFG_LINK_SPEED:
 		if (vpd->link_speed) {
 			switch (new_value) {
--- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_config.h	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_config.h	Wed Aug 18 15:52:48 2010 -0600
@@ -283,10 +283,10 @@
 
 	/* CFG_FW_CHECK */
 	{"fw-check",
-		0, 2, 1, 0,
-		PARM_DYNAMIC_RESET | PARM_BOOLEAN | PARM_HIDDEN,
-	"Enables firmware revision checking of adapters. "
-		"[0=Off 1=Sun-only 2=All]"},
+		0, 7, 1, 0,
+		PARM_DYNAMIC_RESET | PARM_HEX | PARM_HIDDEN,
+	"Enables firmware revision checking. "
+		"[0=Off 1=Sun-only 2=All 4=kern-update]"},
 
 	/* CFG_TRI_REQUIRED */
 	{"tri-required",
--- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_extern.h	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_extern.h	Wed Aug 18 15:52:48 2010 -0600
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Emulex.  All rights reserved.
+ * Copyright 2010 Emulex.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -170,8 +170,7 @@
 
 extern uint32_t			emlxs_get_instance(int32_t ddiinst);
 extern char			*emlxs_mscmd_xlate(uint16_t cmd);
-extern int32_t			emlxs_reset(opaque_t fca_port_handle,
-					uint32_t cmd);
+extern int32_t			emlxs_reset(emlxs_port_t *port, uint32_t cmd);
 extern void			emlxs_swap_service_params(SERV_PARM *sp);
 extern void			emlxs_swap_fcp_pkt(emlxs_buf_t *sbp);
 extern void			emlxs_swap_ct_pkt(emlxs_buf_t *sbp);
--- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_fc.h	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_fc.h	Wed Aug 18 15:52:48 2010 -0600
@@ -1813,6 +1813,11 @@
 #define	FC_LINKDOWN_MASK	0xFFF30C1F	/* Bits to protect during */
 						/* a linkdown */
 
+	uint32_t fw_timer;
+	uint32_t fw_flag;
+#define	FW_UPDATE_NEEDED	0x00000001
+#define	FW_UPDATE_KERNEL	0x00000002
+
 	uint32_t temperature;			/* Last reported temperature */
 
 	/* SBUS adapter management */
--- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_hw.h	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_hw.h	Wed Aug 18 15:52:48 2010 -0600
@@ -2261,6 +2261,7 @@
 	uint32_t	image_size;
 	uint32_t	block_size;
 	uint32_t	block_crc;
+	uint32_t	load_address;
 	char		label[BE_VERSION_SIZE];
 } emlxs_be_fw_file_t;
 
--- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_mbox.h	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_mbox.h	Wed Aug 18 15:52:48 2010 -0600
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Emulex.  All rights reserved.
+ * Copyright 2010 Emulex.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -391,7 +391,8 @@
 typedef struct
 {
 #ifdef EMLXS_BIG_ENDIAN
-	uint32_t	rsvd2:25;
+	uint32_t	rsvd2:24;
+	uint32_t	keep:1;
 	uint32_t	acknowledgment:1;
 	uint32_t	version:1;
 	uint32_t	erase_or_prog:1;
@@ -408,7 +409,8 @@
 	uint32_t	erase_or_prog:1;
 	uint32_t	version:1;
 	uint32_t	acknowledgment:1;
-	uint32_t	rsvd2:25;
+	uint32_t	keep:1;
+	uint32_t	rsvd2:24;
 #endif
 
 #define	DL_FROM_BDE	0	/* method */
@@ -3685,7 +3687,7 @@
 
 
 #define	PROG_DESCR_STR_LEN	24
-#define	MAX_LOAD_ENTRY		10
+#define	MAX_LOAD_ENTRY		32
 
 typedef struct
 {
--- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_messages.h	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_messages.h	Wed Aug 18 15:52:48 2010 -0600
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Emulex.  All rights reserved.
+ * Copyright 2010 Emulex.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1733,6 +1733,20 @@
 		NULL, \
 		0)
 
+	DEFINE_MSG(1540, \
+		emlxs_fw_update_msg, \
+		"Firmware update required.", \
+		EMLXS_WARNING, \
+		MSG_FIRMWARE, \
+		"This indicates that a firmware update is required on the " \
+		"adapter.", \
+		"The user must perform a manual adapter reset or link reset" \
+		"once the host environment is stable to trigger an automatic" \
+		"firmware download. DO NOT POWER CYCLE OR REBOOT THE SYSTEM" \
+		"DURING THE DOWNLOAD OPERATION.", \
+		NULL, \
+		0)
+
 	/* GROUP:  CT		1600 - 1699 */
 
 	DEFINE_MSG(1600, \
--- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_version.h	Wed Aug 18 15:57:57 2010 -0600
+++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_version.h	Wed Aug 18 15:52:48 2010 -0600
@@ -31,11 +31,11 @@
 extern "C" {
 #endif
 
-#define	EMLXS_VERSION		"2.50o"
-#define	EMLXS_DATE_MINUTE	"45"	/* 00-59 */
-#define	EMLXS_DATE_HOUR		"09"	/* 00-23 */
-#define	EMLXS_DATE_DAY		"08"	/* 00-31 */
-#define	EMLXS_DATE_MONTH	"01"	/* 01-12 */
+#define	EMLXS_VERSION		"2.50q"
+#define	EMLXS_DATE_MINUTE	"00"	/* 00-59 */
+#define	EMLXS_DATE_HOUR		"17"	/* 00-23 */
+#define	EMLXS_DATE_DAY		"30"	/* 00-31 */
+#define	EMLXS_DATE_MONTH	"07"	/* 01-12 */
 #define	EMLXS_DATE_YEAR		"2010"	/* YYYY  */
 
 #define	EMLXS_REVISION		EMLXS_DATE_YEAR "." EMLXS_DATE_MONTH "." \