1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <emlxs.h>
29 
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C);
32 
33 #define	MAX_BOOTID	10
34 
35 static uint32_t	emlxs_erase_fcode_flash(emlxs_hba_t *hba);
36 
37 static uint32_t	emlxs_write_fcode_flash(emlxs_hba_t *hba,
38 			PIMAGE_HDR ImageHdr, caddr_t Buffer);
39 
40 static int32_t	emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
41 			uint32_t BufferSize, PAIF_HDR AifHeader);
42 static uint32_t	emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
43 			uint32_t Size, emlxs_fw_image_t *fw_image);
44 static void	emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq,
45 			uint32_t Type, uint32_t RegionId, uint32_t WordCnt,
46 			uint32_t BaseAddr);
47 static uint32_t	emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
48 			caddr_t Buffer, uint32_t len,
49 			PWAKE_UP_PARMS WakeUpParms);
50 static uint32_t	emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
51 			uint32_t len, uint32_t offline,
52 			emlxs_fw_image_t *fw_image);
53 static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba,
54 			caddr_t EntireBuffer, uint32_t FileType,
55 			uint32_t extType);
56 static void	emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base,
57 			uint32_t DlByteCount, uint32_t Function,
58 			uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
59 			uint8_t MbxCmd, uint32_t StepCmd);
60 static uint32_t	emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
61 			uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
62 static uint32_t	emlxs_update_exp_rom(emlxs_hba_t *hba,
63 			PWAKE_UP_PARMS WakeUpParms);
64 extern uint32_t	emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
65 			uint32_t *MaxIbusSize);
66 static void	emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base,
67 			uint32_t DlByteCount, uint32_t Function,
68 			uint32_t Complete, uint32_t BdeAddress,
69 			uint32_t BdeSize, PROG_ID *ProgId, uint32_t keep);
70 static void	emlxs_format_update_parms(MAILBOXQ *mbq,
71 			PWAKE_UP_PARMS WakeUpParms);
72 static void	emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
73 			uint32_t region_id, uint32_t size);
74 static uint32_t	emlxs_update_wakeup_parms(emlxs_hba_t *hba,
75 			PWAKE_UP_PARMS AbsWakeUpParms,
76 			PWAKE_UP_PARMS WakeUpParms);
77 static uint32_t	emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba,
78 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id,
79 			uint32_t proc_erom);
80 static uint32_t	emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba,
81 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
82 static uint32_t	emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba,
83 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
84 static uint32_t	emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba,
85 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
86 static uint32_t	emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba,
87 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
88 static uint32_t	emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba,
89 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
90 static uint32_t	emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
91 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
92 			uint32_t dwc_flag);
93 static uint32_t	emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
94 
95 static uint32_t	emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
96 
97 static void	emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr);
98 
99 static void	emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
100 
101 
102 static uint32_t	emlxs_type_check(uint32_t type);
103 
104 static uint32_t	emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
105 
106 static uint32_t	emlxs_stub_check(emlxs_hba_t *hba, uint32_t version);
107 
108 static uint32_t	emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version);
109 
110 static uint32_t	emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version);
111 
112 static uint32_t	emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version);
113 
114 static uint32_t	emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version);
115 
116 static uint32_t	emlxs_bios_check(emlxs_hba_t *hba, uint32_t version);
117 
118 static uint32_t	emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version);
119 
120 static uint32_t	emlxs_validate_version(emlxs_hba_t *hba,
121 			emlxs_fw_file_t *file, uint32_t id, uint32_t type,
122 			char *file_type);
123 static uint32_t emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
124 			uint32_t len, emlxs_be_fw_image_t *fw_image);
125 static uint32_t emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
126 			uint32_t len, emlxs_be_fw_image_t *fw_image);
127 
128 
129 static int32_t emlxs_sli4_verify_crc(emlxs_hba_t *hba,
130 			emlxs_be_fw_file_t *file,
131 			MAILBOXQ *mbq, MATCHMAP *mp);
132 static int32_t emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
133 			emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp);
134 static int32_t emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer,
135 			uint32_t len, uint32_t offline);
136 static uint32_t emlxs_be_version(caddr_t buffer, uint32_t size,
137 			uint32_t *plus_flag);
138 static uint32_t emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer,
139 			emlxs_fw_image_t *fw_image);
140 static uint32_t emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId);
141 
142 static void emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *image);
143 
144 static uint32_t emlxs_clean_flash(emlxs_hba_t *hba,
145 			PWAKE_UP_PARMS OldWakeUpParms,
146 			PWAKE_UP_PARMS NewWakeUpParms);
147 
148 /* ************************************************************************* */
149 
150 extern int32_t
151 emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
152     uint32_t offline)
153 {
154 	emlxs_port_t *port = &PPORT;
155 	uint32_t *Uptr;
156 	IMAGE_HDR ImageHdr;
157 	AIF_HDR AifHdr;
158 	uint32_t ImageType;
159 	WAKE_UP_PARMS WakeUpParms;
160 	uint32_t rval = 0;
161 	emlxs_fw_image_t fw_image;
162 	uint32_t i;
163 
164 #ifdef EMLXS_LITTLE_ENDIAN
165 	caddr_t local_buffer;
166 	uint32_t *bptr1;
167 	uint32_t *bptr2;
168 #endif /* EMLXS_LITTLE_ENDIAN */
169 
170 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
171 		rval = emlxs_sli4_fw_download(hba, buffer, len, offline);
172 		return (rval);
173 	}
174 
175 	if (buffer == NULL || len == 0) {
176 		return (EMLXS_IMAGE_BAD);
177 	}
178 
179 #ifdef EMLXS_LITTLE_ENDIAN
180 	/* We need to swap the image buffer before we start */
181 
182 	/*
183 	 * Use KM_SLEEP to allocate a temporary buffer
184 	 */
185 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
186 
187 	/* Perform a 32 bit swap of the image */
188 	bptr1 = (uint32_t *)local_buffer;
189 	bptr2 = (uint32_t *)buffer;
190 	for (i = 0; i < (len / 4); i++) {
191 		*bptr1 = LE_SWAP32(*bptr2);
192 		bptr1++;
193 		bptr2++;
194 	}
195 
196 	/* Replace the original buffer */
197 	buffer = local_buffer;
198 #endif /* EMLXS_LITTLE_ENDIAN */
199 
200 	bzero(&fw_image, sizeof (emlxs_fw_image_t));
201 	for (i = 0; i < MAX_PROG_TYPES; i++) {
202 		(void) strcpy(fw_image.prog[i].label, "none");
203 	}
204 
205 	/* Validate image */
206 	if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) {
207 		goto done;
208 	}
209 
210 	/* Verify image */
211 	emlxs_verify_image(hba, &fw_image);
212 
213 	/* Get image type */
214 	Uptr = (uint32_t *)buffer;
215 	ImageType = *Uptr;
216 
217 	/*
218 	 * Pegasus and beyond FW download is done differently
219 	 * for absolute download.
220 	 */
221 
222 	/* Check for absolute image */
223 	if ((ImageType == NOP_IMAGE_TYPE) &&
224 	    !(hba->model_info.chip &
225 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
226 		/*
227 		 * Because 2Mb flash download file format is different from
228 		 * 512k, it needs to be handled differently
229 		 */
230 		if (rval = emlxs_start_abs_download_2mb(hba, buffer, len,
231 		    offline, &fw_image)) {
232 			goto done;
233 		}
234 
235 		/* Offline already handled */
236 		offline = 0;
237 
238 		goto SLI_DOWNLOAD_EXIT;
239 	}
240 
241 	/* Pre-pegasus adapters only */
242 
243 	/* Initialize headers */
244 	if (ImageType == NOP_IMAGE_TYPE) {
245 		bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
246 		bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
247 	} else { /* PRG file */
248 		bzero((void *)&AifHdr, sizeof (AIF_HDR));
249 		bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
250 	}
251 
252 	/* Everything checks out, now to just do it */
253 
254 	if (offline) {
255 		if (emlxs_offline(hba) != FC_SUCCESS) {
256 			offline = 0;
257 
258 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
259 			    "Unable to take adapter offline.");
260 
261 			rval = EMLXS_OFFLINE_FAILED;
262 			goto SLI_DOWNLOAD_EXIT;
263 		}
264 
265 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
266 			offline = 0;
267 
268 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
269 			    "Unable to restart adapter.");
270 
271 			rval = EMLXS_OFFLINE_FAILED;
272 			goto SLI_DOWNLOAD_EXIT;
273 		}
274 	}
275 
276 	/* Pre-pegasus adapters */
277 
278 	if (ImageHdr.Id.Type == SBUS_FCODE) {
279 		/* Erase Flash */
280 		if (emlxs_erase_fcode_flash(hba)) {
281 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
282 			    "Unable to erase flash.");
283 
284 			rval = EMLXS_IMAGE_FAILED;
285 			goto SLI_DOWNLOAD_EXIT;
286 		}
287 
288 		/* Write FCODE */
289 		if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) {
290 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
291 			    "Unable to write flash.");
292 
293 			rval = EMLXS_IMAGE_FAILED;
294 			goto SLI_DOWNLOAD_EXIT;
295 		}
296 
297 		goto SLI_DOWNLOAD_EXIT;
298 	}
299 
300 	/* Pre-pegasus PCI adapters */
301 
302 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
303 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
304 		    "Unable to get parameters.");
305 
306 		rval = EMLXS_IMAGE_FAILED;
307 
308 		goto SLI_DOWNLOAD_EXIT;
309 	}
310 
311 	if (ImageType == NOP_IMAGE_TYPE) {
312 		if (emlxs_start_abs_download(hba, &AifHdr,
313 		    buffer, len, &WakeUpParms)) {
314 			EMLXS_MSGF(EMLXS_CONTEXT,
315 			    &emlxs_download_failed_msg,
316 			    "Failed to program flash.");
317 
318 			rval = EMLXS_IMAGE_FAILED;
319 
320 			goto SLI_DOWNLOAD_EXIT;
321 		}
322 
323 	} else { /* Relative PRG file */
324 		if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
325 		    &WakeUpParms, 0)) {
326 			EMLXS_MSGF(EMLXS_CONTEXT,
327 			    &emlxs_download_failed_msg,
328 			    "Failed to program flash.");
329 
330 			rval = EMLXS_IMAGE_FAILED;
331 
332 			goto SLI_DOWNLOAD_EXIT;
333 		}
334 	}
335 
336 SLI_DOWNLOAD_EXIT:
337 
338 	if (offline) {
339 		(void) emlxs_online(hba);
340 	}
341 
342 	if (rval == 0) {
343 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
344 		    "Status good.");
345 	}
346 
347 done:
348 
349 #ifdef EMLXS_LITTLE_ENDIAN
350 	/* Free the local buffer */
351 	kmem_free(local_buffer, len);
352 #endif /* EMLXS_LITTLE_ENDIAN */
353 
354 	return (rval);
355 
356 } /* emlxs_fw_download */
357 
358 
359 extern void
360 emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size)
361 {
362 	while (size--) {
363 		*buffer++ = value;
364 	}
365 
366 } /* emlxs_memset () */
367 
368 
369 static int32_t
370 emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
371     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
372 {
373 	emlxs_port_t *port = &PPORT;
374 	uint8_t *image_ptr;
375 	uint32_t *wptr;
376 	uint8_t *payload;
377 	MAILBOX4 *mb;
378 	IOCTL_COMMON_FLASHROM *flashrom;
379 	mbox_req_hdr_t	*hdr_req;
380 	uint32_t	image_size;
381 	uint32_t	block_size;
382 	uint32_t	xfer_size;
383 	uint32_t	block_offset;
384 	uint32_t	count;
385 	uint32_t	rval = 0;
386 
387 	if (file->image_size == 0) {
388 		return (0);
389 	}
390 
391 	image_ptr  = (uint8_t *)buffer + file->image_offset;
392 	image_size = file->image_size;
393 	block_size = file->block_size;
394 	block_offset = 0;
395 	mb = (MAILBOX4*)mbq;
396 
397 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
398 	    "%s: Downloading...", file->label);
399 
400 	while (block_size) {
401 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
402 		bzero((void *) mp->virt, mp->size);
403 
404 		xfer_size = min(BE_MAX_XFER_SIZE, block_size);
405 
406 		mb->un.varSLIConfig.be.embedded = 0;
407 		mbq->nonembed = (void *)mp;
408 		mbq->mbox_cmpl = NULL;
409 
410 		mb->mbxCommand = MBX_SLI_CONFIG;
411 		mb->mbxOwner = OWN_HOST;
412 
413 		hdr_req = (mbox_req_hdr_t *)mp->virt;
414 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
415 		hdr_req->opcode = COMMON_OPCODE_WRITE_FLASHROM;
416 		hdr_req->timeout = 0;
417 		hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
418 		    xfer_size;
419 
420 		flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
421 		flashrom->params.opcode = ((block_size == xfer_size)?
422 		    MGMT_FLASHROM_OPCODE_FLASH:MGMT_FLASHROM_OPCODE_SAVE);
423 		flashrom->params.optype = file->type;
424 		flashrom->params.data_buffer_size = xfer_size;
425 		flashrom->params.offset = block_offset;
426 
427 		/* Build data buffer payload */
428 		payload = (uint8_t *)(&flashrom->params.data_buffer);
429 		emlxs_memset(payload, 0xff, xfer_size);
430 
431 		/* Copy remaining image into payload */
432 		if (image_size) {
433 			count = min(image_size, xfer_size);
434 			BE_SWAP32_BCOPY(image_ptr, payload, count);
435 			image_size -= count;
436 			image_ptr  += count;
437 		}
438 
439 		if (flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) {
440 			wptr = (uint32_t *)&payload[(xfer_size - 12)];
441 
442 			wptr[0] = file->load_address;
443 			wptr[1] = file->image_size;
444 			wptr[2] = file->block_crc;
445 		}
446 
447 		/* Send write request */
448 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
449 		    MBX_SUCCESS) {
450 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
451 			    "%s: Unable to download image. status=%x",
452 			    file->label, mb->mbxStatus);
453 			rval = EMLXS_IMAGE_FAILED;
454 			goto done;
455 		}
456 
457 		block_size -= xfer_size;
458 		block_offset += xfer_size;
459 	}
460 
461 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
462 	    "%s: Download complete.", file->label);
463 done:
464 
465 	return (rval);
466 
467 } /* emlxs_sli4_flash_image() */
468 
469 
470 
471 
472 static int32_t
473 emlxs_sli4_verify_crc(emlxs_hba_t *hba,
474     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
475 {
476 	emlxs_port_t *port = &PPORT;
477 	uint32_t *wptr;
478 	uint8_t *payload;
479 	MAILBOX4 *mb;
480 	IOCTL_COMMON_FLASHROM *flashrom;
481 	mbox_req_hdr_t	*hdr_req;
482 	uint32_t	xfer_size;
483 	uint32_t	block_offset;
484 	uint32_t	rval = 0;
485 	uint32_t	value;
486 
487 	xfer_size = 8;
488 	block_offset = file->block_size - xfer_size;
489 	mb = (MAILBOX4*)mbq;
490 
491 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
492 	    "%s: Verifying CRC...", file->label);
493 
494 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
495 	bzero((void *) mp->virt, mp->size);
496 
497 	mb->un.varSLIConfig.be.embedded = 0;
498 	mbq->nonembed = (void *)mp;
499 	mbq->mbox_cmpl = NULL;
500 
501 	mb->mbxCommand = MBX_SLI_CONFIG;
502 	mb->mbxOwner = OWN_HOST;
503 
504 	hdr_req = (mbox_req_hdr_t *)mp->virt;
505 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
506 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
507 	hdr_req->timeout = 0;
508 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
509 	    xfer_size;
510 
511 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
512 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
513 	flashrom->params.optype = file->type;
514 	flashrom->params.data_buffer_size = xfer_size;
515 	flashrom->params.offset = block_offset;
516 
517 	/* Send read request */
518 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
519 	    MBX_SUCCESS) {
520 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
521 		    "%s: Unable to read CRC. status=%x",
522 		    file->label, mb->mbxStatus);
523 
524 		rval = 2;
525 		goto done;
526 	}
527 
528 	payload = (uint8_t *)(&flashrom->params.data_buffer);
529 	wptr = (uint32_t *)(payload + xfer_size - 8);
530 
531 	/* Verify image size */
532 	value = *wptr++;
533 	if (value != file->image_size) {
534 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
535 		    "%s: Image size mismatch. %08x != %08x",
536 		    file->label, value, file->image_size);
537 
538 		rval = 1;
539 		goto done;
540 	}
541 
542 	/* Verify block crc */
543 	value = *wptr;
544 	if (value != file->block_crc) {
545 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
546 		    "%s: CRC mismatch. %08x != %08x",
547 		    file->label, value, file->block_crc);
548 		rval = 1;
549 	}
550 
551 done:
552 
553 	if (rval == 0) {
554 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
555 		    "%s: CRC verified.", file->label);
556 	}
557 
558 	return (rval);
559 
560 } /* emlxs_sli4_verify_crc() */
561 
562 
563 extern int32_t
564 emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw)
565 {
566 	emlxs_port_t *port = &PPORT;
567 	MAILBOXQ *mbq = NULL;
568 	MATCHMAP *mp = NULL;
569 	MAILBOX4 *mb;
570 	uint32_t *wptr;
571 	uint8_t *payload;
572 	IOCTL_COMMON_FLASHROM *flashrom;
573 	mbox_req_hdr_t	*hdr_req;
574 	uint32_t	xfer_size;
575 	uint32_t	block_offset;
576 	uint32_t	rval = 0;
577 
578 	bzero((void *) fw, sizeof (emlxs_firmware_t));
579 
580 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
581 	    KM_SLEEP)) == NULL) {
582 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
583 		    "read_fw_version: Unable to allocate mailbox buffer.");
584 
585 		rval = 1;
586 		goto done;
587 	}
588 
589 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
590 	    sizeof (IOCTL_COMMON_FLASHROM) + 32))) == NULL) {
591 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
592 		    "read_fw_version: Unable to allocate payload buffer.");
593 
594 		rval = EMLXS_IMAGE_FAILED;
595 		goto done;
596 	}
597 
598 	mb = (MAILBOX4*)mbq;
599 
600 	/* Read CRC and size */
601 	xfer_size = 8;
602 	block_offset = 0x140000 - xfer_size;
603 
604 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
605 	bzero((void *) mp->virt, mp->size);
606 
607 	mb->un.varSLIConfig.be.embedded = 0;
608 	mbq->nonembed = (void *)mp;
609 	mbq->mbox_cmpl = NULL;
610 
611 	mb->mbxCommand = MBX_SLI_CONFIG;
612 	mb->mbxOwner = OWN_HOST;
613 
614 	hdr_req = (mbox_req_hdr_t *)mp->virt;
615 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
616 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
617 	hdr_req->timeout = 0;
618 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
619 	    xfer_size;
620 
621 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
622 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
623 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
624 	flashrom->params.data_buffer_size = xfer_size;
625 	flashrom->params.offset = block_offset;
626 
627 	/* Send read request */
628 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
629 	    MBX_SUCCESS) {
630 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
631 		    "read_fw_version: Unable to read CRC. status=%x",
632 		    mb->mbxStatus);
633 
634 		rval = 1;
635 		goto done;
636 	}
637 
638 	payload = (uint8_t *)(&flashrom->params.data_buffer);
639 
640 	wptr = (uint32_t *)payload;
641 	fw->size = *wptr++; /* image size */
642 	fw->sli4 = *wptr;   /* block crc */
643 	fw->kern = *wptr;
644 	fw->stub = *wptr;
645 
646 	/* Read version label */
647 	xfer_size = 32;
648 	block_offset = 0x30;
649 
650 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
651 	bzero((void *) mp->virt, mp->size);
652 
653 	mb->un.varSLIConfig.be.embedded = 0;
654 	mbq->nonembed = (void *)mp;
655 	mbq->mbox_cmpl = NULL;
656 
657 	mb->mbxCommand = MBX_SLI_CONFIG;
658 	mb->mbxOwner = OWN_HOST;
659 
660 	hdr_req = (mbox_req_hdr_t *)mp->virt;
661 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
662 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
663 	hdr_req->timeout = 0;
664 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
665 	    xfer_size;
666 
667 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
668 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
669 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
670 	flashrom->params.data_buffer_size = xfer_size;
671 	flashrom->params.offset = block_offset;
672 
673 	/* Send read request */
674 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
675 	    MBX_SUCCESS) {
676 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
677 		    "read_fw_version: Unable to read version string. status=%x",
678 		    mb->mbxStatus);
679 
680 		rval = 1;
681 		goto done;
682 	}
683 
684 	payload = (uint8_t *)(&flashrom->params.data_buffer);
685 	BE_SWAP32_BCOPY(payload, (uint8_t *)fw->label, 32);
686 
687 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
688 	    "FCOE FIRMWARE: size=%x version=%s (0x%08x)",
689 	    fw->size, fw->label, fw->sli4);
690 
691 done:
692 
693 	if (mbq) {
694 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
695 	}
696 
697 	if (mp) {
698 		emlxs_mem_buf_free(hba, mp);
699 	}
700 
701 	return (rval);
702 
703 } /* emlxs_sli4_read_fw_version() */
704 
705 
706 static uint32_t
707 emlxs_be_version(caddr_t buffer, uint32_t size, uint32_t *plus_flag)
708 {
709 	emlxs_be2_ufi_header_t *ufi_hdr;
710 	char signature[BE2_SIGNATURE_SIZE];
711 	uint32_t be_version = 0;
712 
713 	if (size < sizeof (emlxs_be2_ufi_header_t)) {
714 		return (0);
715 	}
716 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
717 
718 	(void) sprintf(signature, "%s+", BE_SIGNATURE);
719 
720 	/* Check if this is a UFI image */
721 	if (strncmp(signature, (char *)ufi_hdr->signature,
722 	    strlen(BE_SIGNATURE)) != 0) {
723 		return (0);
724 	}
725 
726 	/* Check if this is a UFI plus image */
727 	if (plus_flag) {
728 		/* Check if this is a UFI plus image */
729 		if (strncmp(signature, (char *)ufi_hdr->signature,
730 		    strlen(BE_SIGNATURE)+1) == 0) {
731 			*plus_flag = 1;
732 		} else {
733 			*plus_flag = 0;
734 		}
735 	}
736 
737 	if ((ufi_hdr->build[0] >= '1') && (ufi_hdr->build[0] <= '9')) {
738 		be_version = ufi_hdr->build[0] - '0';
739 	}
740 
741 	return (be_version);
742 
743 } /* emlxs_be_version() */
744 
745 
746 static uint32_t
747 emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
748     uint32_t len, emlxs_be_fw_image_t *fw_image)
749 {
750 	emlxs_port_t *port = &PPORT;
751 	emlxs_be2_ufi_header_t *ufi_hdr;
752 	emlxs_be2_flash_dir_t *flash_dir;
753 	emlxs_be2_flash_entry_t *entry;
754 	uint8_t *bptr;
755 	uint32_t *wptr;
756 	uint32_t i;
757 	uint32_t k;
758 	uint32_t mask;
759 	uint32_t value;
760 	uint32_t image_size;
761 	emlxs_be_fw_file_t *file;
762 	emlxs_be_fw_file_t *file2;
763 	uint32_t ufi_plus = 0;
764 	uint32_t be_version = 0;
765 	uint32_t found;
766 
767 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
768 
769 	if (hba->model_info.chip != EMLXS_BE2_CHIP) {
770 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
771 		    "Invalid adapter model.");
772 		return (EMLXS_IMAGE_INCOMPATIBLE);
773 	}
774 
775 	if (len < (sizeof (emlxs_be2_ufi_header_t) +
776 	    sizeof (emlxs_be2_flash_dir_t))) {
777 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
778 		    "Image too small. (%d < %d)",
779 		    len, (sizeof (emlxs_be2_ufi_header_t) +
780 		    sizeof (emlxs_be2_flash_dir_t)));
781 		return (EMLXS_IMAGE_BAD);
782 	}
783 
784 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
785 
786 	/* Check if this is a standard BE2 image */
787 	if (be_version != 2) {
788 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
789 		    "Invalid image provided.");
790 		return (EMLXS_IMAGE_INCOMPATIBLE);
791 	}
792 
793 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
794 
795 #ifdef EMLXS_BIG_ENDIAN
796 	/* Big Endian Swapping */
797 	/* Swap ufi header */
798 	ufi_hdr->checksum =
799 	    SWAP32(ufi_hdr->checksum);
800 	ufi_hdr->antidote =
801 	    SWAP32(ufi_hdr->antidote);
802 	ufi_hdr->controller.vendor_id =
803 	    SWAP32(ufi_hdr->controller.vendor_id);
804 	ufi_hdr->controller.device_id =
805 	    SWAP32(ufi_hdr->controller.device_id);
806 	ufi_hdr->controller.sub_vendor_id =
807 	    SWAP32(ufi_hdr->controller.sub_vendor_id);
808 	ufi_hdr->controller.sub_device_id =
809 	    SWAP32(ufi_hdr->controller.sub_device_id);
810 	ufi_hdr->file_length =
811 	    SWAP32(ufi_hdr->file_length);
812 	ufi_hdr->chunk_num =
813 	    SWAP32(ufi_hdr->chunk_num);
814 	ufi_hdr->chunk_cnt =
815 	    SWAP32(ufi_hdr->chunk_cnt);
816 	ufi_hdr->image_cnt =
817 	    SWAP32(ufi_hdr->image_cnt);
818 #endif /* EMLXS_BIG_ENDIAN */
819 
820 	if (len != ufi_hdr->file_length) {
821 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
822 		    "Invalid image size (%d != %d)",
823 		    len, ufi_hdr->file_length);
824 
825 		return (EMLXS_IMAGE_BAD);
826 	}
827 
828 	/* Scan for flash dir signature */
829 	bptr = (uint8_t *)buffer;
830 	flash_dir = NULL;
831 	for (i = 0; i < len; i++, bptr++) {
832 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
833 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
834 			flash_dir = (emlxs_be2_flash_dir_t *)bptr;
835 			break;
836 		}
837 	}
838 
839 	if (!flash_dir) {
840 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
841 		    "Unable to find flash directory.");
842 
843 		return (EMLXS_IMAGE_BAD);
844 	}
845 
846 #ifdef EMLXS_BIG_ENDIAN
847 	/* Big Endian Swapping */
848 	/* Swap flash dir */
849 	flash_dir->header.format_rev =
850 	    SWAP32(flash_dir->header.format_rev);
851 	flash_dir->header.checksum =
852 	    SWAP32(flash_dir->header.checksum);
853 	flash_dir->header.antidote =
854 	    SWAP32(flash_dir->header.antidote);
855 	flash_dir->header.build_num =
856 	    SWAP32(flash_dir->header.build_num);
857 	flash_dir->header.active_entry_mask =
858 	    SWAP32(flash_dir->header.active_entry_mask);
859 	flash_dir->header.valid_entry_mask =
860 	    SWAP32(flash_dir->header.valid_entry_mask);
861 	flash_dir->header.orig_content_mask =
862 	    SWAP32(flash_dir->header.orig_content_mask);
863 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
864 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
865 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
866 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
867 	flash_dir->header.resv4 = SWAP32(flash_dir->header.resv4);
868 
869 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
870 		flash_dir->header.controller[i].vendor_id =
871 		    SWAP32(flash_dir->header.controller[i].vendor_id);
872 		flash_dir->header.controller[i].device_id =
873 		    SWAP32(flash_dir->header.controller[i].device_id);
874 		flash_dir->header.controller[i].sub_vendor_id =
875 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
876 		flash_dir->header.controller[i].sub_device_id =
877 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
878 	}
879 
880 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++,  mask <<= 1) {
881 
882 		if (!(flash_dir->header.valid_entry_mask & mask)) {
883 			continue;
884 		}
885 
886 		entry = &flash_dir->entry[i];
887 
888 		if ((entry->type == 0) ||
889 		    (entry->type == (uint32_t)-1) ||
890 		    (entry->image_size == 0)) {
891 			continue;
892 		}
893 
894 		flash_dir->entry[i].type =
895 		    SWAP32(flash_dir->entry[i].type);
896 		flash_dir->entry[i].offset =
897 		    SWAP32(flash_dir->entry[i].offset);
898 		flash_dir->entry[i].pad_size =
899 		    SWAP32(flash_dir->entry[i].pad_size);
900 		flash_dir->entry[i].image_size =
901 		    SWAP32(flash_dir->entry[i].image_size);
902 		flash_dir->entry[i].checksum =
903 		    SWAP32(flash_dir->entry[i].checksum);
904 		flash_dir->entry[i].entry_point =
905 		    SWAP32(flash_dir->entry[i].entry_point);
906 		flash_dir->entry[i].resv0 =
907 		    SWAP32(flash_dir->entry[i].resv0);
908 		flash_dir->entry[i].resv1 =
909 		    SWAP32(flash_dir->entry[i].resv1);
910 	}
911 #endif /* EMLXS_BIG_ENDIAN */
912 
913 	/* Verify adapter model */
914 	found = 0;
915 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
916 		if (flash_dir->header.controller[i].device_id ==
917 		    hba->model_info.device_id) {
918 			found = 1;
919 		}
920 	}
921 
922 	if (!found) {
923 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
924 		    "Invalid adapter device id=0x%x.",
925 		    hba->model_info.device_id);
926 		return (EMLXS_IMAGE_INCOMPATIBLE);
927 	}
928 
929 	/* Build fw_image table */
930 	fw_image->be_version = 2;
931 	fw_image->ufi_plus = ufi_plus;
932 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) {
933 
934 		if (!(flash_dir->header.valid_entry_mask & mask)) {
935 			continue;
936 		}
937 
938 		entry = &flash_dir->entry[i];
939 
940 		if ((entry->type == 0) ||
941 		    (entry->type == (uint32_t)-1) ||
942 		    (entry->image_size == 0)) {
943 			continue;
944 		}
945 
946 		switch (entry->type) {
947 		case BE_FLASHTYPE_REDBOOT:
948 			file = &fw_image->file[REDBOOT_FLASHTYPE];
949 			(void) strcpy(file->label, "REDBOOT");
950 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
951 			break;
952 		case BE_FLASHTYPE_ISCSI_BIOS:
953 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
954 			(void) strcpy(file->label, "ISCSI BIOS");
955 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
956 			break;
957 		case BE_FLASHTYPE_PXE_BIOS:
958 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
959 			(void) strcpy(file->label, "PXE BIOS");
960 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
961 			break;
962 		case BE_FLASHTYPE_FCOE_BIOS:
963 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
964 			(void) strcpy(file->label, "FCOE BIOS");
965 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
966 			break;
967 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
968 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
969 			(void) strcpy(file->label, "ISCSI FIRMWARE");
970 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
971 			break;
972 		case BE_FLASHTYPE_FCOE_FIRMWARE:
973 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
974 			(void) strcpy(file->label, "FCOE FIRMWARE");
975 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
976 			break;
977 		case BE_FLASHTYPE_FCOE_BACKUP:
978 		case BE_FLASHTYPE_ISCSI_BACKUP:
979 			continue;
980 
981 		default:
982 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
983 			    "Unknown image type found.  type=%x",
984 			    entry->type);
985 			continue;
986 		}
987 
988 		file->be_version = fw_image->be_version;
989 		file->ufi_plus = fw_image->ufi_plus;
990 		file->image_size = entry->image_size;
991 		image_size = BE_SWAP32(entry->image_size);
992 
993 		if (ufi_plus) {
994 			file->image_offset = entry->offset;
995 			file->block_size   = entry->pad_size;
996 			file->block_crc    = entry->checksum;
997 			file->load_address = entry->entry_point;
998 
999 		} else {
1000 			file->image_offset = entry->offset +
1001 			    sizeof (emlxs_be2_ufi_header_t);
1002 
1003 			/* Get entry block size and crc */
1004 			k = file->image_offset + file->image_size;
1005 			k &= 0xFFFFFFFC;
1006 
1007 			wptr = (uint32_t *)(buffer +  k);
1008 			for (; k < len; k += 4) {
1009 				if (*wptr++ == image_size) {
1010 					/* Calculate block_size */
1011 					file->block_size = (k + 8) -
1012 					    file->image_offset;
1013 
1014 					/* Read load_address */
1015 					value = *(wptr - 2);
1016 					file->load_address = BE_SWAP32(value);
1017 
1018 					/* Read block_crc */
1019 					value = *wptr;
1020 					file->block_crc = BE_SWAP32(value);
1021 
1022 					break;
1023 				}
1024 			}
1025 
1026 			if (k >= len) {
1027 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1028 				    "%s: End of block not found. offset=%x",
1029 				    file->label, file->image_offset);
1030 
1031 				bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1032 				return (EMLXS_IMAGE_BAD);
1033 			}
1034 		}
1035 
1036 		/* Make sure image will fit in block specified */
1037 		if (file->image_size + 12 > file->block_size) {
1038 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1039 			    "%s: Image too large for block. image=%x block=%x",
1040 			    file->label, file->image_size, file->block_size);
1041 
1042 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1043 			return (EMLXS_IMAGE_BAD);
1044 		}
1045 
1046 		/* Automatically create a backup file entry for firmware */
1047 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1048 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1049 
1050 			bcopy((uint8_t *)file, (uint8_t *)file2,
1051 			    sizeof (emlxs_be_fw_file_t));
1052 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1053 			(void) strcpy(file2->label, "FCOE BACKUP");
1054 
1055 			/* Save FCOE version info */
1056 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1057 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
1058 			    BE_VERSION_SIZE);
1059 			fw_image->fcoe_version = file->block_crc;
1060 
1061 		} else if (file->type ==
1062 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1063 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1064 
1065 			bcopy((uint8_t *)file, (uint8_t *)file2,
1066 			    sizeof (emlxs_be_fw_file_t));
1067 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1068 			(void) strcpy(file2->label, "ISCSI BACKUP");
1069 
1070 			/* Save ISCSI version info */
1071 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1072 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1073 			    BE_VERSION_SIZE);
1074 			fw_image->iscsi_version = file->block_crc;
1075 		}
1076 	}
1077 
1078 	if (fw_image->fcoe_version == 0) {
1079 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1080 		    "Unable to find FCOE firmware component.");
1081 
1082 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1083 		return (EMLXS_IMAGE_BAD);
1084 	}
1085 
1086 	/* Display contents */
1087 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1088 	    "BE2 UFI Image: %08x, %s", fw_image->fcoe_version,
1089 	    fw_image->fcoe_label);
1090 
1091 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1092 		file = &fw_image->file[i];
1093 
1094 		if (file->image_size == 0) {
1095 			continue;
1096 		}
1097 
1098 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1099 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1100 		    "load=%x",
1101 		    file->label, file->be_version, (file->ufi_plus)?"+":"",
1102 		    file->type, file->block_size, file->image_size,
1103 		    file->image_offset, file->block_crc, file->load_address);
1104 	}
1105 
1106 	return (0);
1107 
1108 } /* emlxs_be2_validate_image() */
1109 
1110 
1111 static uint32_t
1112 emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
1113     uint32_t len, emlxs_be_fw_image_t *fw_image)
1114 {
1115 	emlxs_port_t *port = &PPORT;
1116 	emlxs_be3_ufi_header_t *ufi_hdr;
1117 	emlxs_be3_flash_dir_t *flash_dir;
1118 	emlxs_be3_flash_entry_t *entry;
1119 	emlxs_be3_image_header_t *flash_image_hdr;
1120 	emlxs_be3_image_header_t *image_hdr;
1121 	uint8_t *bptr;
1122 	uint32_t *wptr;
1123 	uint32_t i;
1124 	uint32_t value;
1125 	emlxs_be_fw_file_t *file;
1126 	emlxs_be_fw_file_t *file2;
1127 	uint32_t ufi_plus = 0;
1128 	uint32_t be_version = 0;
1129 	uint32_t found;
1130 
1131 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1132 
1133 	if (hba->model_info.chip != EMLXS_BE3_CHIP) {
1134 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1135 		    "Invalid adapter model.");
1136 		return (EMLXS_IMAGE_INCOMPATIBLE);
1137 	}
1138 
1139 	if (len < (sizeof (emlxs_be3_ufi_header_t) +
1140 	    sizeof (emlxs_be3_flash_dir_t))) {
1141 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1142 		    "Image too small. (%d < %d)",
1143 		    len, (sizeof (emlxs_be3_ufi_header_t) +
1144 		    sizeof (emlxs_be3_flash_dir_t)));
1145 		return (EMLXS_IMAGE_BAD);
1146 	}
1147 
1148 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
1149 
1150 	/* Check if this is a standard BE3 image */
1151 	if (be_version != 3) {
1152 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1153 		    "Invalid image provided.");
1154 		return (EMLXS_IMAGE_INCOMPATIBLE);
1155 	}
1156 
1157 	ufi_hdr = (emlxs_be3_ufi_header_t *)buffer;
1158 
1159 #ifdef EMLXS_BIG_ENDIAN
1160 	/* Big Endian Swapping */
1161 	/* Swap ufi header */
1162 	ufi_hdr->ufi_version =
1163 	    SWAP32(ufi_hdr->ufi_version);
1164 	ufi_hdr->file_length =
1165 	    SWAP32(ufi_hdr->file_length);
1166 	ufi_hdr->checksum =
1167 	    SWAP32(ufi_hdr->checksum);
1168 	ufi_hdr->antidote =
1169 	    SWAP32(ufi_hdr->antidote);
1170 	ufi_hdr->image_cnt =
1171 	    SWAP32(ufi_hdr->image_cnt);
1172 #endif /* EMLXS_BIG_ENDIAN */
1173 
1174 	if (len != ufi_hdr->file_length) {
1175 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1176 		    "Invalid image size (%d != %d)",
1177 		    len, ufi_hdr->file_length);
1178 
1179 		return (EMLXS_IMAGE_BAD);
1180 	}
1181 
1182 	flash_image_hdr = NULL;
1183 	image_hdr = (emlxs_be3_image_header_t *)(buffer +
1184 	    sizeof (emlxs_be3_ufi_header_t));
1185 	for (i = 0; i < ufi_hdr->image_cnt; i++, image_hdr++) {
1186 #ifdef EMLXS_BIG_ENDIAN
1187 		image_hdr->id = SWAP32(image_hdr->id);
1188 		image_hdr->offset = SWAP32(image_hdr->offset);
1189 		image_hdr->length = SWAP32(image_hdr->length);
1190 		image_hdr->checksum = SWAP32(image_hdr->checksum);
1191 #endif /* EMLXS_BIG_ENDIAN */
1192 
1193 		if (image_hdr->id == UFI_BE3_FLASH_ID) {
1194 			flash_image_hdr = image_hdr;
1195 		}
1196 	}
1197 
1198 	if (!flash_image_hdr) {
1199 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1200 		    "No flash image found.");
1201 
1202 		return (EMLXS_IMAGE_BAD);
1203 	}
1204 
1205 	/* Scan for flash dir signature */
1206 	bptr = (uint8_t *)buffer + flash_image_hdr->offset;
1207 	flash_dir = NULL;
1208 	for (i = 0; i < flash_image_hdr->length; i++, bptr++) {
1209 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
1210 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
1211 			flash_dir = (emlxs_be3_flash_dir_t *)bptr;
1212 			break;
1213 		}
1214 	}
1215 
1216 	if (!flash_dir) {
1217 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1218 		    "Unable to find flash directory.");
1219 
1220 		return (EMLXS_IMAGE_BAD);
1221 	}
1222 
1223 #ifdef EMLXS_BIG_ENDIAN
1224 	/* Big Endian Swapping */
1225 	/* Swap flash dir */
1226 	flash_dir->header.format_rev =
1227 	    SWAP32(flash_dir->header.format_rev);
1228 	flash_dir->header.checksum =
1229 	    SWAP32(flash_dir->header.checksum);
1230 	flash_dir->header.antidote =
1231 	    SWAP32(flash_dir->header.antidote);
1232 	flash_dir->header.entry_count =
1233 	    SWAP32(flash_dir->header.entry_count);
1234 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
1235 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
1236 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
1237 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
1238 
1239 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1240 		flash_dir->header.controller[i].vendor_id =
1241 		    SWAP32(flash_dir->header.controller[i].vendor_id);
1242 		flash_dir->header.controller[i].device_id =
1243 		    SWAP32(flash_dir->header.controller[i].device_id);
1244 		flash_dir->header.controller[i].sub_vendor_id =
1245 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
1246 		flash_dir->header.controller[i].sub_device_id =
1247 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
1248 	}
1249 
1250 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1251 		entry = &flash_dir->entry[i];
1252 
1253 		if ((entry->type == 0) ||
1254 		    (entry->type == (uint32_t)-1) ||
1255 		    (entry->image_size == 0)) {
1256 			continue;
1257 		}
1258 
1259 		flash_dir->entry[i].type =
1260 		    SWAP32(flash_dir->entry[i].type);
1261 		flash_dir->entry[i].offset =
1262 		    SWAP32(flash_dir->entry[i].offset);
1263 		flash_dir->entry[i].block_size =
1264 		    SWAP32(flash_dir->entry[i].block_size);
1265 		flash_dir->entry[i].image_size =
1266 		    SWAP32(flash_dir->entry[i].image_size);
1267 		flash_dir->entry[i].checksum =
1268 		    SWAP32(flash_dir->entry[i].checksum);
1269 		flash_dir->entry[i].entry_point =
1270 		    SWAP32(flash_dir->entry[i].entry_point);
1271 		flash_dir->entry[i].resv0 =
1272 		    SWAP32(flash_dir->entry[i].resv0);
1273 		flash_dir->entry[i].resv1 =
1274 		    SWAP32(flash_dir->entry[i].resv1);
1275 	}
1276 #endif /* EMLXS_BIG_ENDIAN */
1277 
1278 	/* Verify image checksum */
1279 	if (flash_dir->header.checksum != flash_image_hdr->checksum) {
1280 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1281 		    "Invalid flash directory checksum. (%x != %x)\n",
1282 		    flash_dir->header.checksum, flash_image_hdr->checksum);
1283 		return (EMLXS_IMAGE_BAD);
1284 	}
1285 
1286 	/* Verify adapter model */
1287 	found = 0;
1288 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1289 		if (flash_dir->header.controller[i].device_id ==
1290 		    hba->model_info.device_id) {
1291 			found = 1;
1292 		}
1293 	}
1294 
1295 	if (!found) {
1296 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1297 		    "Invalid adapter device id=0x%x.",
1298 		    hba->model_info.device_id);
1299 		return (EMLXS_IMAGE_INCOMPATIBLE);
1300 	}
1301 
1302 	/* Build fw_image table */
1303 	fw_image->be_version = 3;
1304 	fw_image->ufi_plus = ufi_plus;
1305 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1306 		entry = &flash_dir->entry[i];
1307 
1308 		if ((entry->type == 0) ||
1309 		    (entry->type == (uint32_t)-1) ||
1310 		    (entry->image_size == 0)) {
1311 			continue;
1312 		}
1313 
1314 		switch (entry->type) {
1315 		case BE_FLASHTYPE_REDBOOT:
1316 			file = &fw_image->file[REDBOOT_FLASHTYPE];
1317 			(void) strcpy(file->label, "REDBOOT");
1318 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
1319 			break;
1320 		case BE_FLASHTYPE_ISCSI_BIOS:
1321 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1322 			(void) strcpy(file->label, "ISCSI BIOS");
1323 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
1324 			break;
1325 		case BE_FLASHTYPE_PXE_BIOS:
1326 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1327 			(void) strcpy(file->label, "PXE BIOS");
1328 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
1329 			break;
1330 		case BE_FLASHTYPE_FCOE_BIOS:
1331 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1332 			(void) strcpy(file->label, "FCOE BIOS");
1333 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
1334 			break;
1335 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
1336 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1337 			(void) strcpy(file->label, "ISCSI FIRMWARE");
1338 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
1339 			break;
1340 		case BE_FLASHTYPE_FCOE_FIRMWARE:
1341 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1342 			(void) strcpy(file->label, "FCOE FIRMWARE");
1343 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
1344 			break;
1345 		case BE_FLASHTYPE_NCSI_FIRMWARE:
1346 			file = &fw_image->file[NCSI_FIRMWARE_FLASHTYPE];
1347 			(void) strcpy(file->label, "NCSI FIRMWARE");
1348 			file->type = MGMT_FLASHROM_OPTYPE_NCSI_FIRMWARE;
1349 			break;
1350 		case BE_FLASHTYPE_FLASH_ISM:
1351 		case BE_FLASHTYPE_FCOE_BACKUP:
1352 		case BE_FLASHTYPE_ISCSI_BACKUP:
1353 			continue;
1354 
1355 		default:
1356 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1357 			    "Unknown image type found.  type=%x",
1358 			    entry->type);
1359 			continue;
1360 		}
1361 
1362 		file->be_version = fw_image->be_version;
1363 		file->ufi_plus = fw_image->ufi_plus;
1364 		file->image_size = entry->image_size;
1365 
1366 		if (ufi_plus) {
1367 			file->image_offset = entry->offset;
1368 			file->block_size   = entry->block_size;
1369 			file->block_crc    = entry->checksum;
1370 			file->load_address = entry->entry_point;
1371 		} else {
1372 			file->image_offset = entry->offset +
1373 			    flash_image_hdr->offset;
1374 			file->block_size   = entry->block_size;
1375 
1376 			wptr = (uint32_t *)(buffer +  file->image_offset +
1377 			    file->block_size);
1378 
1379 			/* Read load address */
1380 			value = *(wptr - 3);
1381 			file->load_address = BE_SWAP32(value);
1382 
1383 			/* Read block_crc */
1384 			value = *(wptr - 1);
1385 			file->block_crc = BE_SWAP32(value);
1386 		}
1387 
1388 		/* Make sure image will fit in block specified */
1389 		if (file->image_size + 12 > file->block_size) {
1390 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1391 			    "%s: Image too large for block. image=%x block=%x",
1392 			    file->label, file->image_size, file->block_size);
1393 
1394 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1395 			return (EMLXS_IMAGE_BAD);
1396 		}
1397 
1398 		/* Automatically create a backup file entry for firmware */
1399 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1400 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1401 
1402 			bcopy((uint8_t *)file, (uint8_t *)file2,
1403 			    sizeof (emlxs_be_fw_file_t));
1404 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1405 			(void) strcpy(file2->label, "FCOE BACKUP");
1406 
1407 			/* Save FCOE version info */
1408 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1409 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
1410 			    BE_VERSION_SIZE);
1411 			fw_image->fcoe_version = file->block_crc;
1412 
1413 		} else if (file->type ==
1414 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1415 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1416 
1417 			bcopy((uint8_t *)file, (uint8_t *)file2,
1418 			    sizeof (emlxs_be_fw_file_t));
1419 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1420 			(void) strcpy(file2->label, "ISCSI BACKUP");
1421 
1422 			/* Save ISCSI version info */
1423 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1424 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1425 			    BE_VERSION_SIZE);
1426 			fw_image->iscsi_version = file->block_crc;
1427 		}
1428 	}
1429 
1430 	if (fw_image->fcoe_version == 0) {
1431 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1432 		    "Unable to find FCOE firmware component.");
1433 
1434 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1435 		return (EMLXS_IMAGE_BAD);
1436 	}
1437 
1438 	/* Display contents */
1439 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1440 	    "BE3 UFI Image: %08x, %s", fw_image->fcoe_version,
1441 	    fw_image->fcoe_label);
1442 
1443 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1444 		file = &fw_image->file[i];
1445 
1446 		if (file->image_size == 0) {
1447 			continue;
1448 		}
1449 
1450 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1451 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1452 		    "load=%x",
1453 		    file->label, file->be_version, (file->ufi_plus)? "+":"",
1454 		    file->type, file->block_size, file->image_size,
1455 		    file->image_offset, file->block_crc, file->load_address);
1456 	}
1457 
1458 	return (0);
1459 
1460 } /* emlxs_be3_validate_image() */
1461 
1462 
1463 static int32_t
1464 emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
1465     uint32_t offline)
1466 {
1467 	emlxs_port_t *port = &PPORT;
1468 	uint32_t i;
1469 	uint32_t update = 0;
1470 	uint32_t rval = 0;
1471 	MAILBOXQ *mbq = NULL;
1472 	MATCHMAP *mp = NULL;
1473 	emlxs_be_fw_image_t fw_image;
1474 	emlxs_be_fw_file_t *file;
1475 	uint32_t be_version;
1476 
1477 	/* For now we will not take the driver offline during a download */
1478 	offline = 0;
1479 
1480 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
1481 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1482 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
1483 		return (EMLXS_IMAGE_INCOMPATIBLE);
1484 	}
1485 
1486 	if (buffer == NULL || len == 0) {
1487 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1488 		    "Empty buffer provided. buf=%p size=%d", buffer, len);
1489 		return (EMLXS_IMAGE_BAD);
1490 	}
1491 
1492 	be_version = emlxs_be_version(buffer, len, 0);
1493 
1494 	switch (be_version) {
1495 	case 0:
1496 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1497 		    "Invalid image provided. Non-UFI format.");
1498 		return (EMLXS_IMAGE_INCOMPATIBLE);
1499 	case 2:
1500 		rval = emlxs_be2_validate_image(hba, buffer, len, &fw_image);
1501 		if (rval) {
1502 			return (rval);
1503 		}
1504 		break;
1505 	case 3:
1506 		rval = emlxs_be3_validate_image(hba, buffer, len, &fw_image);
1507 		if (rval) {
1508 			return (rval);
1509 		}
1510 		break;
1511 	default:
1512 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1513 		    "Invalid image provided. Unknown BE version. (%x)",
1514 		    be_version);
1515 		return (EMLXS_IMAGE_INCOMPATIBLE);
1516 	}
1517 
1518 	/* Allocate resources */
1519 
1520 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1521 	    KM_SLEEP)) == NULL) {
1522 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1523 		    "Unable to allocate mailbox buffer.");
1524 
1525 		offline = 0;
1526 		rval = EMLXS_IMAGE_FAILED;
1527 		goto done;
1528 	}
1529 
1530 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
1531 	    sizeof (IOCTL_COMMON_FLASHROM) + BE_MAX_XFER_SIZE))) == NULL) {
1532 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1533 		    "Unable to allocate flash buffer.");
1534 
1535 		offline = 0;
1536 		rval = EMLXS_IMAGE_FAILED;
1537 		goto done;
1538 	}
1539 
1540 	/* Check if update is required */
1541 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1542 		file = &fw_image.file[i];
1543 
1544 		if (file->image_size == 0) {
1545 			continue;
1546 		}
1547 
1548 		rval = emlxs_sli4_verify_crc(hba, file, mbq, mp);
1549 
1550 		if (rval == 0) {
1551 			/* Do not update */
1552 			file->image_size = 0;
1553 			continue;
1554 		}
1555 
1556 		update++;
1557 	}
1558 
1559 	if (!update) {
1560 		offline = 0;
1561 		rval = 0;
1562 		goto done;
1563 	}
1564 
1565 	/*
1566 	 * Everything checks out, now to just do it
1567 	 */
1568 	if (offline) {
1569 		if (emlxs_offline(hba) != FC_SUCCESS) {
1570 
1571 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1572 			    "Unable to take adapter offline.");
1573 
1574 			offline = 0;
1575 			rval = EMLXS_OFFLINE_FAILED;
1576 			goto done;
1577 		}
1578 	}
1579 
1580 	/* Download entries which require update */
1581 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1582 		file = &fw_image.file[i];
1583 
1584 		if (file->image_size == 0) {
1585 			continue;
1586 		}
1587 
1588 		rval = emlxs_sli4_flash_image(hba, buffer, file, mbq, mp);
1589 
1590 		if (rval != 0) {
1591 			goto done;
1592 		}
1593 	}
1594 
1595 done:
1596 	if (mbq) {
1597 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
1598 	}
1599 
1600 	if (mp) {
1601 		emlxs_mem_buf_free(hba, mp);
1602 	}
1603 
1604 	if (offline) {
1605 		(void) emlxs_online(hba);
1606 	}
1607 
1608 	if (rval == 0) {
1609 		if (update) {
1610 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1611 			    "Status good.");
1612 
1613 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
1614 			    "Please reboot system or power cycle adapter "
1615 			    "to activate new firmware: %s",
1616 			    fw_image.fcoe_label);
1617 
1618 		} else {
1619 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1620 			    "No firmware update required.");
1621 		}
1622 	}
1623 
1624 	return (rval);
1625 
1626 } /* emlxs_sli4_fw_download() */
1627 
1628 
1629 extern int32_t
1630 emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer,
1631     uint32_t len)
1632 {
1633 	emlxs_port_t *port = &PPORT;
1634 	MAILBOXQ *mbox = NULL;
1635 	MAILBOX *mb;
1636 	uint32_t rval = 0;
1637 	uint32_t region_id;
1638 	uint32_t id;
1639 #ifdef EMLXS_BIG_ENDIAN
1640 	caddr_t local_buffer;
1641 	uint32_t *bptr1;
1642 	uint32_t *bptr2;
1643 	uint32_t i;
1644 #endif /* EMLXS_BIG_ENDIAN */
1645 
1646 	if (buffer == NULL || len == 0) {
1647 		return (EMLXS_IMAGE_BAD);
1648 	}
1649 
1650 #ifdef EMLXS_BIG_ENDIAN
1651 	/* We need to swap the image buffer before we start */
1652 
1653 	/*
1654 	 * Use KM_SLEEP to allocate a temporary buffer
1655 	 */
1656 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
1657 
1658 	/* Perform a 32 bit swap of the image */
1659 	bptr1 = (uint32_t *)local_buffer;
1660 	bptr2 = (uint32_t *)buffer;
1661 
1662 	for (i = 0; i < (len / 4); i++) {
1663 		*bptr1 = SWAP32(*bptr2);
1664 		bptr1++;
1665 		bptr2++;
1666 	}
1667 
1668 	/* Replace the original buffer */
1669 	buffer = local_buffer;
1670 
1671 #endif /* EMLXS_BIG_ENDIAN */
1672 
1673 	if (len > 128) {
1674 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1675 		    "Invalid image length: 0x%x > 128", len);
1676 
1677 		return (EMLXS_IMAGE_BAD);
1678 	}
1679 
1680 	/* Check the region number */
1681 	if ((region > 2) && (region != 0xff)) {
1682 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1683 		    "Invalid region id: 0x%x", region);
1684 
1685 		return (EMLXS_IMAGE_BAD);
1686 
1687 	}
1688 
1689 	/* Check the image vendor id */
1690 	id = *(int32_t *)buffer;
1691 	if ((id & 0xffff) != 0x10df) {
1692 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1693 		    "Invalid image id: 0x%x", id);
1694 
1695 		return (EMLXS_IMAGE_BAD);
1696 	}
1697 
1698 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1699 	    KM_NOSLEEP)) == NULL) {
1700 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1701 		    "Unable to allocate mailbox buffer.");
1702 
1703 		rval = 1;
1704 
1705 		goto done;
1706 	}
1707 
1708 	mb = (MAILBOX *)mbox;
1709 
1710 	/*
1711 	 * Everything checks out, now to just do it
1712 	 */
1713 	if (emlxs_offline(hba) != FC_SUCCESS) {
1714 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1715 		    "Unable to take HBA offline.");
1716 
1717 		rval = EMLXS_OFFLINE_FAILED;
1718 
1719 		goto done;
1720 	}
1721 
1722 	if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
1723 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1724 		    "Unable to restart adapter.");
1725 
1726 		rval = EMLXS_OFFLINE_FAILED;
1727 
1728 		goto done;
1729 	}
1730 
1731 	/* Check if default region is requested */
1732 	if (region == 0xff) {
1733 		/*
1734 		 * Sun-branded Helios and Zypher have different
1735 		 * default PCI region
1736 		 */
1737 		if ((hba->model_info.flags & EMLXS_SUN_BRANDED) &&
1738 		    (hba->model_info.chip &
1739 		    (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
1740 			region = 2;
1741 		} else {
1742 			region = 0;
1743 		}
1744 	}
1745 
1746 	/* Set region id based on PCI region requested */
1747 	region_id = DEF_PCI_CFG_REGION_ID + region;
1748 
1749 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1750 	    "PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
1751 	    region_id, id, len);
1752 
1753 	/* Copy the data buffer to SLIM */
1754 	WRITE_SLIM_COPY(hba, (uint32_t *)buffer,
1755 	    (volatile uint32_t *)((volatile char *)hba->sli.sli3.slim_addr +
1756 	    sizeof (MAILBOX)), (len / sizeof (uint32_t)));
1757 
1758 #ifdef FMA_SUPPORT
1759 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
1760 	    != DDI_FM_OK) {
1761 		EMLXS_MSGF(EMLXS_CONTEXT,
1762 		    &emlxs_invalid_access_handle_msg, NULL);
1763 		rval = 1;
1764 	}
1765 #endif  /* FMA_SUPPORT */
1766 
1767 	emlxs_format_update_pci_cfg(hba, mbox, region_id, len);
1768 
1769 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
1770 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1771 		    "Unable to update PCI configuration: Mailbox cmd=%x "
1772 		    "status=%x info=%d", mb->mbxCommand, mb->mbxStatus,
1773 		    mb->un.varUpdateCfg.rsp_info);
1774 
1775 		rval = 1;
1776 	}
1777 
1778 	(void) emlxs_online(hba);
1779 
1780 	if (rval == 0) {
1781 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1782 		    "Status good.");
1783 	}
1784 
1785 done:
1786 
1787 	if (mbox) {
1788 		kmem_free(mbox, sizeof (MAILBOXQ));
1789 	}
1790 
1791 #ifdef EMLXS_BIG_ENDIAN
1792 	/* Free the local buffer */
1793 	kmem_free(local_buffer, len);
1794 #endif /* EMLXS_BIG_ENDIAN */
1795 
1796 	return (rval);
1797 
1798 } /* emlxs_cfl_download */
1799 
1800 
1801 static uint32_t
1802 emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr)
1803 {
1804 	uint32_t Temp;
1805 	uint32_t CkSum;
1806 
1807 	EndAddr++;
1808 	CkSum = SLI_CKSUM_SEED;
1809 
1810 	CkSum = (CkSum >> 1) | (CkSum << 31);
1811 	while (StartAddr != EndAddr) {
1812 		CkSum = (CkSum << 1) | (CkSum >> 31);
1813 		Temp = *StartAddr;
1814 
1815 		CkSum ^= Temp;
1816 		StartAddr++;
1817 	}
1818 
1819 	return (CkSum << 1) | (CkSum >> 31);
1820 
1821 } /* emlxs_valid_cksum() */
1822 
1823 
1824 static void
1825 emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr)
1826 {
1827 	emlxs_port_t *port = &PPORT;
1828 
1829 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: ");
1830 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1831 	    "AIF Header: compress_br = 0x%x", AifHdr->CompressBr);
1832 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1833 	    "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr);
1834 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1835 	    "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr);
1836 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1837 	    "AIF Header: entry_br = 0x%x", AifHdr->EntryBr);
1838 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1839 	    "AIF Header: area_id = 0x%x", AifHdr->Area_ID);
1840 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1841 	    "AIF Header: rosize = 0x%x", AifHdr->RoSize);
1842 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1843 	    "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize);
1844 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1845 	    "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize);
1846 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1847 	    "AIF Header: dbgtype = 0x%x", AifHdr->DbgType);
1848 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1849 	    "AIF Header: imagebase = 0x%x", AifHdr->ImageBase);
1850 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1851 	    "AIF Header: area_size = 0x%x", AifHdr->Area_Size);
1852 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1853 	    "AIF Header: address_mode = 0x%x", AifHdr->AddressMode);
1854 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1855 	    "AIF Header: database = 0x%x", AifHdr->DataBase);
1856 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1857 	    "AIF Header: aversion = 0x%x", AifHdr->AVersion);
1858 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1859 	    "AIF Header: spare2 = 0x%x", AifHdr->Spare2);
1860 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1861 	    "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi);
1862 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1863 	    "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]);
1864 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1865 	    "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]);
1866 
1867 } /* emlxs_disp_aif_header() */
1868 
1869 
1870 
1871 static void
1872 emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image)
1873 {
1874 	emlxs_port_t *port = &PPORT;
1875 
1876 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: ");
1877 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1878 	    "Img Header: BlockSize = 0x%x", image->BlockSize);
1879 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1880 	    "Img Header: PROG_ID Type = 0x%x", image->Id.Type);
1881 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1882 	    "Img Header: PROG_ID Id = 0x%x", image->Id.Id);
1883 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1884 	    "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver);
1885 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1886 	    "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev);
1887 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1888 	    "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp);
1889 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1890 	    "Img Header: Flags = 0x%x", image->Flags);
1891 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1892 	    "Img Header: EntryAdr = 0x%x", image->EntryAdr);
1893 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1894 	    "Img Header: InitAdr = 0x%x", image->InitAdr);
1895 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1896 	    "Img Header: ExitAdr = 0x%x", image->ExitAdr);
1897 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1898 	    "Img Header: ImageBase = 0x%x", image->ImageBase);
1899 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1900 	    "Img Header: ImageSize = 0x%x", image->ImageSize);
1901 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1902 	    "Img Header: ZinitSize = 0x%x", image->ZinitSize);
1903 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1904 	    "Img Header: RelocSize = 0x%x", image->RelocSize);
1905 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1906 	    "Img Header: HdrCks = 0x%x", image->HdrCks);
1907 
1908 } /* emlxs_dump_image_header() */
1909 
1910 
1911 static void
1912 emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t Type,
1913     uint32_t RegionId, uint32_t WordCount, uint32_t BaseAddr)
1914 {
1915 
1916 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1917 		MAILBOX4 *mb = (MAILBOX4 *)mbq;
1918 
1919 		/* Clear the local dump_region */
1920 		bzero(hba->sli.sli4.dump_region.virt,
1921 		    hba->sli.sli4.dump_region.size);
1922 
1923 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1924 
1925 		mb->mbxCommand = MBX_DUMP_MEMORY;
1926 		mb->un.varDmp4.type = Type;
1927 		mb->un.varDmp4.entry_index = BaseAddr;
1928 		mb->un.varDmp4.region_id = RegionId;
1929 
1930 		mb->un.varDmp4.available_cnt = min((WordCount*4),
1931 		    hba->sli.sli4.dump_region.size);
1932 		mb->un.varDmp4.addrHigh =
1933 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
1934 		mb->un.varDmp4.addrLow =
1935 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
1936 		mb->un.varDmp4.rsp_cnt = 0;
1937 
1938 		mb->mbxOwner = OWN_HOST;
1939 
1940 	} else {
1941 		MAILBOX *mb = (MAILBOX *)mbq;
1942 
1943 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1944 
1945 		mb->mbxCommand = MBX_DUMP_MEMORY;
1946 		mb->un.varDmp.type = Type;
1947 		mb->un.varDmp.region_id = RegionId;
1948 		mb->un.varDmp.word_cnt = WordCount;
1949 		mb->un.varDmp.base_adr = BaseAddr;
1950 		mb->mbxOwner = OWN_HOST;
1951 	}
1952 
1953 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1954 
1955 	return;
1956 
1957 } /* emlxs_format_dump() */
1958 
1959 
1960 /* ARGSUSED */
1961 static uint32_t
1962 emlxs_start_abs_download(emlxs_hba_t *hba,
1963     PAIF_HDR AifHdr,
1964     caddr_t Buffer,
1965     uint32_t len,
1966     PWAKE_UP_PARMS WakeUpParms)
1967 {
1968 	emlxs_port_t *port = &PPORT;
1969 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
1970 	uint32_t *Src;
1971 	uint32_t *Dst;
1972 	caddr_t DataBuffer = NULL;
1973 	MAILBOXQ *mbox;
1974 	MAILBOX *mb;
1975 	uint32_t rval = 1;
1976 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
1977 	uint32_t DlToAddr = AifHdr->ImageBase;
1978 	uint32_t DlCount;
1979 	uint32_t i;
1980 	WAKE_UP_PARMS AbsWakeUpParms;
1981 	int32_t AbsChangeParams;
1982 
1983 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1984 	    "Performing absolute download...");
1985 
1986 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
1987 	    KM_NOSLEEP)) == NULL) {
1988 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1989 		    "Unable to allocate data buffer.");
1990 
1991 		return (rval);
1992 	}
1993 
1994 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1995 	    KM_NOSLEEP)) == NULL) {
1996 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1997 		    "Unable to allocate mailbox buffer.");
1998 
1999 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2000 
2001 		return (rval);
2002 	}
2003 	mb = (MAILBOX *)mbox;
2004 
2005 	AbsChangeParams = emlxs_build_parms(Buffer,
2006 	    &AbsWakeUpParms, len, AifHdr);
2007 
2008 	Buffer += sizeof (AIF_HDR);
2009 
2010 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Erasing flash...");
2011 
2012 	if (AifHdr->ImageBase == 0x20000) {
2013 		/* DWC File */
2014 		emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0,
2015 		    0, 0, NULL, 0);
2016 	} else {
2017 		emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount,
2018 		    ERASE_FLASH, 0, 0, 0, NULL, 0);
2019 	}
2020 
2021 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2022 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2023 		    "Unable to erase Flash: Mailbox cmd=%x status=%x",
2024 		    mb->mbxCommand, mb->mbxStatus);
2025 
2026 		rval = 1;
2027 
2028 		goto EXIT_ABS_DOWNLOAD;
2029 	}
2030 
2031 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2032 	    "Programming flash...");
2033 
2034 	while (DlByteCount) {
2035 
2036 		if (DlByteCount > SegSize) {
2037 			DlCount = SegSize;
2038 		} else {
2039 			DlCount = DlByteCount;
2040 		}
2041 		DlByteCount -= DlCount;
2042 
2043 		Dst = (uint32_t *)DataBuffer;
2044 		Src = (uint32_t *)Buffer;
2045 
2046 		for (i = 0; i < (DlCount / 4); i++) {
2047 			*Dst = *Src;
2048 			Dst++;
2049 			Src++;
2050 		}
2051 
2052 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
2053 		    (volatile uint32_t *)
2054 		    ((volatile char *)hba->sli.sli3.slim_addr +
2055 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2056 
2057 		emlxs_format_prog_flash(mbox, DlToAddr, DlCount,
2058 		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL, 0);
2059 
2060 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2061 		    MBX_SUCCESS) {
2062 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2063 			    "Unable to program Flash: Mailbox cmd=%x status=%x",
2064 			    mb->mbxCommand, mb->mbxStatus);
2065 
2066 			rval = 1;
2067 
2068 			goto EXIT_ABS_DOWNLOAD;
2069 		}
2070 
2071 		Buffer += DlCount;
2072 		DlToAddr += DlCount;
2073 	}
2074 
2075 #ifdef FMA_SUPPORT
2076 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2077 	    != DDI_FM_OK) {
2078 		EMLXS_MSGF(EMLXS_CONTEXT,
2079 		    &emlxs_invalid_access_handle_msg, NULL);
2080 
2081 		rval = 1;
2082 
2083 		goto EXIT_ABS_DOWNLOAD;
2084 	}
2085 #endif  /* FMA_SUPPORT */
2086 
2087 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
2088 
2089 	if (AbsChangeParams) {
2090 		rval =
2091 		    emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
2092 		    WakeUpParms);
2093 	}
2094 
2095 EXIT_ABS_DOWNLOAD:
2096 	if (DataBuffer) {
2097 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2098 	}
2099 
2100 	if (mbox) {
2101 		kmem_free(mbox, sizeof (MAILBOXQ));
2102 	}
2103 
2104 	return (rval);
2105 
2106 } /* emlxs_start_abs_download() */
2107 
2108 
2109 /* ARGSUSED */
2110 static void
2111 emlxs_format_prog_flash(MAILBOXQ *mbq,
2112     uint32_t Base,
2113     uint32_t DlByteCount,
2114     uint32_t Function,
2115     uint32_t Complete,
2116     uint32_t BdeAddress,
2117     uint32_t BdeSize,
2118     PROG_ID *ProgId,
2119     uint32_t keep)
2120 {
2121 	MAILBOX *mb = (MAILBOX *)mbq;
2122 
2123 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2124 
2125 	if (ProgId) {
2126 		mb->mbxCommand = MBX_DOWN_LOAD;
2127 	} else {
2128 		mb->mbxCommand = MBX_LOAD_SM;
2129 	}
2130 
2131 	mb->un.varLdSM.load_cmplt = Complete;
2132 	mb->un.varLdSM.method = DL_FROM_SLIM;
2133 	mb->un.varLdSM.update_flash = 1;
2134 	mb->un.varLdSM.erase_or_prog = Function;
2135 	mb->un.varLdSM.dl_to_adr = Base;
2136 	mb->un.varLdSM.dl_len = DlByteCount;
2137 	mb->un.varLdSM.keep = keep;
2138 
2139 	if (BdeSize) {
2140 		mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
2141 	} else if (ProgId) {
2142 		mb->un.varLdSM.un.prog_id = *ProgId;
2143 	} else {
2144 		mb->un.varLdSM.un.dl_from_slim_offset = 0;
2145 	}
2146 
2147 	mb->mbxOwner = OWN_HOST;
2148 	mbq->mbox_cmpl = NULL;
2149 
2150 } /* emlxs_format_prog_flash() */
2151 
2152 
2153 static void
2154 emlxs_format_update_parms(MAILBOXQ *mbq, PWAKE_UP_PARMS WakeUpParms)
2155 {
2156 	MAILBOX *mb = (MAILBOX *)mbq;
2157 
2158 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2159 
2160 	mb->mbxCommand = MBX_UPDATE_CFG;
2161 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2162 	mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID;
2163 	mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS);
2164 	mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS);
2165 
2166 	bcopy((caddr_t)WakeUpParms,
2167 	    (caddr_t)&(mb->un.varUpdateCfg.cfg_data),
2168 	    sizeof (WAKE_UP_PARMS));
2169 	mbq->mbox_cmpl = NULL;
2170 
2171 } /* emlxs_format_update_parms () */
2172 
2173 
2174 /* ARGSUSED */
2175 static void
2176 emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
2177     uint32_t region_id, uint32_t size)
2178 {
2179 	MAILBOX *mb = (MAILBOX *)mbq;
2180 
2181 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2182 
2183 	mb->mbxCommand = MBX_UPDATE_CFG;
2184 	mb->un.varUpdateCfg.Vbit = 1;
2185 	mb->un.varUpdateCfg.Obit = 1;
2186 	mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET;
2187 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2188 	mb->un.varUpdateCfg.region_id = region_id;
2189 	mb->un.varUpdateCfg.entry_len = size;
2190 	mb->un.varUpdateCfg.byte_len = size;
2191 	mbq->mbox_cmpl = NULL;
2192 
2193 } /* emlxs_format_update_pci_cfg() */
2194 
2195 
2196 
2197 static uint32_t
2198 emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2199     PROG_ID * prog_id, uint32_t proc_erom)
2200 {
2201 	emlxs_port_t *port = &PPORT;
2202 	MAILBOX *mb;
2203 	MAILBOXQ *mbox;
2204 	uint32_t rval = 0;
2205 	PROG_ID old_prog_id;
2206 
2207 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2208 	    KM_NOSLEEP)) == NULL) {
2209 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2210 		    "Unable to allocate mailbox buffer.");
2211 
2212 		return (1);
2213 	}
2214 
2215 	mb = (MAILBOX *)mbox;
2216 
2217 	if (proc_erom && !(hba->model_info.chip &
2218 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2219 		WakeUpParms->u1.EROM_prog_id = *prog_id;
2220 		(void) emlxs_update_exp_rom(hba, WakeUpParms);
2221 	}
2222 
2223 	old_prog_id = WakeUpParms->u0.boot_bios_id;
2224 	WakeUpParms->u0.boot_bios_id = *prog_id;
2225 
2226 	emlxs_format_update_parms(mbox, WakeUpParms);
2227 
2228 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2229 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2230 		    "Unable to update boot wakeup parms: Mailbox cmd=%x "
2231 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2232 
2233 		WakeUpParms->u0.boot_bios_id = old_prog_id;
2234 		rval = 1;
2235 	}
2236 
2237 	if (mbox) {
2238 		kmem_free(mbox, sizeof (MAILBOXQ));
2239 	}
2240 
2241 	return (rval);
2242 
2243 } /* emlxs_update_boot_wakeup_parms() */
2244 
2245 
2246 
2247 static uint32_t
2248 emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2249     PROG_ID *prog_id)
2250 {
2251 	emlxs_port_t *port = &PPORT;
2252 	uint32_t rval = 0;
2253 	MAILBOXQ *mbox;
2254 	MAILBOX *mb;
2255 	PROG_ID old_prog_id;
2256 
2257 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2258 	    KM_NOSLEEP)) == NULL) {
2259 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2260 		    "Unable to allocate mailbox buffer.");
2261 
2262 		return (1);
2263 	}
2264 
2265 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2266 	    "FF: Updating parms...");
2267 
2268 	mb = (MAILBOX *)mbox;
2269 
2270 	old_prog_id = WakeUpParms->prog_id;
2271 	WakeUpParms->prog_id = *prog_id;
2272 
2273 	emlxs_format_update_parms(mbox, WakeUpParms);
2274 
2275 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2276 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2277 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
2278 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2279 
2280 		WakeUpParms->prog_id = old_prog_id;
2281 		rval = 1;
2282 	}
2283 
2284 	if (mbox) {
2285 		kmem_free(mbox, sizeof (MAILBOXQ));
2286 	}
2287 
2288 	return (rval);
2289 
2290 } /* emlxs_update_ff_wakeup_parms() */
2291 
2292 
2293 static uint32_t
2294 emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2295     PROG_ID * prog_id)
2296 {
2297 	emlxs_port_t *port = &PPORT;
2298 	uint32_t rval = 0;
2299 	MAILBOXQ *mbox;
2300 	MAILBOX *mb;
2301 	PROG_ID old_prog_id;
2302 
2303 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2304 	    KM_NOSLEEP)) == NULL) {
2305 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2306 		    "Unable to allocate mailbox buffer.");
2307 
2308 		return (1);
2309 	}
2310 
2311 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2312 	    "SLI1: Updating parms...");
2313 
2314 	mb = (MAILBOX *)mbox;
2315 
2316 	old_prog_id = WakeUpParms->sli1_prog_id;
2317 	WakeUpParms->sli1_prog_id = *prog_id;
2318 
2319 	emlxs_format_update_parms(mbox, WakeUpParms);
2320 
2321 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2322 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2323 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2324 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2325 
2326 		WakeUpParms->sli1_prog_id = old_prog_id;
2327 		rval = 1;
2328 	}
2329 
2330 	if (mbox) {
2331 		kmem_free(mbox, sizeof (MAILBOXQ));
2332 	}
2333 
2334 	return (rval);
2335 
2336 } /* emlxs_update_sli1_wakeup_parms() */
2337 
2338 
2339 static uint32_t
2340 emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2341     PROG_ID * prog_id)
2342 {
2343 	emlxs_port_t *port = &PPORT;
2344 	uint32_t rval = 0;
2345 	MAILBOXQ *mbox;
2346 	MAILBOX *mb;
2347 	PROG_ID old_prog_id;
2348 
2349 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2350 	    KM_NOSLEEP)) == NULL) {
2351 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2352 		    "Unable to allocate mailbox buffer.");
2353 
2354 		return (1);
2355 	}
2356 
2357 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2358 	    "SLI2: Updating parms...");
2359 
2360 	mb = (MAILBOX *)mbox;
2361 
2362 	old_prog_id = WakeUpParms->sli2_prog_id;
2363 	WakeUpParms->sli2_prog_id = *prog_id;
2364 
2365 	emlxs_format_update_parms(mbox, WakeUpParms);
2366 
2367 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2368 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2369 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2370 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2371 
2372 		WakeUpParms->sli2_prog_id = old_prog_id;
2373 		rval = 1;
2374 	}
2375 
2376 	if (mbox) {
2377 		kmem_free(mbox, sizeof (MAILBOXQ));
2378 	}
2379 
2380 	return (rval);
2381 
2382 } /* emlxs_update_sli2_wakeup_parms() */
2383 
2384 
2385 static uint32_t
2386 emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2387     PROG_ID *prog_id)
2388 {
2389 	emlxs_port_t *port = &PPORT;
2390 	uint32_t rval = 0;
2391 	MAILBOXQ *mbox;
2392 	MAILBOX *mb;
2393 	PROG_ID old_prog_id;
2394 
2395 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2396 	    KM_NOSLEEP)) == NULL) {
2397 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2398 		    "Unable to allocate mailbox buffer.");
2399 
2400 		return (1);
2401 	}
2402 
2403 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2404 	    "SLI3: Updating parms...");
2405 
2406 	mb = (MAILBOX *)mbox;
2407 
2408 	old_prog_id = WakeUpParms->sli3_prog_id;
2409 	WakeUpParms->sli3_prog_id = *prog_id;
2410 
2411 	emlxs_format_update_parms(mbox, WakeUpParms);
2412 
2413 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2414 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2415 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2416 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2417 
2418 		WakeUpParms->sli3_prog_id = old_prog_id;
2419 		rval = 1;
2420 	}
2421 
2422 	if (mbox) {
2423 		kmem_free(mbox, sizeof (MAILBOXQ));
2424 	}
2425 
2426 	return (rval);
2427 
2428 } /* emlxs_update_sli3_wakeup_parms() */
2429 
2430 
2431 static uint32_t
2432 emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2433     PROG_ID *prog_id)
2434 {
2435 	emlxs_port_t *port = &PPORT;
2436 	uint32_t rval = 0;
2437 	MAILBOXQ *mbox;
2438 	MAILBOX *mb;
2439 	PROG_ID old_prog_id;
2440 
2441 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2442 	    KM_NOSLEEP)) == NULL) {
2443 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2444 		    "Unable to allocate mailbox buffer.");
2445 
2446 		return (1);
2447 	}
2448 
2449 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2450 	    "SLI4: Updating parms...");
2451 
2452 	mb = (MAILBOX *)mbox;
2453 
2454 	old_prog_id = WakeUpParms->sli4_prog_id;
2455 	WakeUpParms->sli4_prog_id = *prog_id;
2456 
2457 	emlxs_format_update_parms(mbox, WakeUpParms);
2458 
2459 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2460 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2461 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2462 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2463 
2464 		WakeUpParms->sli4_prog_id = old_prog_id;
2465 		rval = 1;
2466 	}
2467 
2468 	if (mbox) {
2469 		kmem_free(mbox, sizeof (MAILBOXQ));
2470 	}
2471 
2472 	return (rval);
2473 
2474 } /* emlxs_update_sli4_wakeup_parms() */
2475 
2476 
2477 static uint32_t
2478 emlxs_clean_flash(emlxs_hba_t *hba,
2479     PWAKE_UP_PARMS OldWakeUpParms, PWAKE_UP_PARMS NewWakeUpParms)
2480 {
2481 	emlxs_port_t *port = &PPORT;
2482 	PROG_ID load_list[MAX_LOAD_ENTRY];
2483 	PROG_ID *wakeup_list[MAX_LOAD_ENTRY];
2484 	uint32_t count;
2485 	uint32_t i;
2486 	uint32_t j;
2487 	uint32_t k = 0;
2488 	uint32_t *wptr;
2489 
2490 	if (!NewWakeUpParms) {
2491 		return (1);
2492 	}
2493 
2494 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2495 	    "Cleaning flash...");
2496 
2497 	/* If old wakeup parameter list is available, */
2498 	/* then cleanup old entries */
2499 	if (OldWakeUpParms) {
2500 		if (bcmp(&OldWakeUpParms->prog_id, &NewWakeUpParms->prog_id,
2501 		    sizeof (PROG_ID))) {
2502 
2503 			wptr = (uint32_t *)&OldWakeUpParms->prog_id;
2504 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2505 			    "OLD:      prog_id: 0x%08x 0x%08x  Removing.",
2506 			    wptr[0], wptr[1]);
2507 
2508 			(void) emlxs_delete_load_entry(hba,
2509 			    &OldWakeUpParms->prog_id);
2510 		}
2511 
2512 		if (bcmp(&OldWakeUpParms->u0.boot_bios_id,
2513 		    &NewWakeUpParms->u0.boot_bios_id, sizeof (PROG_ID))) {
2514 
2515 			wptr = (uint32_t *)&OldWakeUpParms->u0.boot_bios_id;
2516 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2517 			    "OLD: boot_bios_id: 0x%08x 0x%08x  Removing.",
2518 			    wptr[0], wptr[1]);
2519 
2520 			(void) emlxs_delete_load_entry(hba,
2521 			    &OldWakeUpParms->u0.boot_bios_id);
2522 		}
2523 
2524 		if (bcmp(&OldWakeUpParms->sli1_prog_id,
2525 		    &NewWakeUpParms->sli1_prog_id, sizeof (PROG_ID))) {
2526 
2527 			wptr = (uint32_t *)&OldWakeUpParms->sli1_prog_id;
2528 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2529 			    "OLD: sli1_prog_id: 0x%08x 0x%08x  Removing.",
2530 			    wptr[0], wptr[1]);
2531 
2532 			(void) emlxs_delete_load_entry(hba,
2533 			    &OldWakeUpParms->sli1_prog_id);
2534 		}
2535 
2536 		if (bcmp(&OldWakeUpParms->sli2_prog_id,
2537 		    &NewWakeUpParms->sli2_prog_id, sizeof (PROG_ID))) {
2538 
2539 			wptr = (uint32_t *)&OldWakeUpParms->sli2_prog_id;
2540 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2541 			    "OLD: sli2_prog_id: 0x%08x 0x%08x  Removing.",
2542 			    wptr[0], wptr[1]);
2543 
2544 			(void) emlxs_delete_load_entry(hba,
2545 			    &OldWakeUpParms->sli2_prog_id);
2546 		}
2547 
2548 		if (bcmp(&OldWakeUpParms->sli3_prog_id,
2549 		    &NewWakeUpParms->sli3_prog_id, sizeof (PROG_ID))) {
2550 
2551 			wptr = (uint32_t *)&OldWakeUpParms->sli3_prog_id;
2552 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2553 			    "OLD: sli3_prog_id: 0x%08x 0x%08x  Removing.",
2554 			    wptr[0], wptr[1]);
2555 
2556 			(void) emlxs_delete_load_entry(hba,
2557 			    &OldWakeUpParms->sli3_prog_id);
2558 		}
2559 
2560 		if (bcmp(&OldWakeUpParms->sli4_prog_id,
2561 		    &NewWakeUpParms->sli4_prog_id, sizeof (PROG_ID))) {
2562 
2563 			wptr = (uint32_t *)&OldWakeUpParms->sli4_prog_id;
2564 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2565 			    "OLD: sli4_prog_id: 0x%08x 0x%08x  Removing.",
2566 			    wptr[0], wptr[1]);
2567 
2568 			(void) emlxs_delete_load_entry(hba,
2569 			    &OldWakeUpParms->sli4_prog_id);
2570 		}
2571 
2572 		return (0);
2573 	}
2574 
2575 	/* Otherwise use the current load list */
2576 	count = emlxs_get_load_list(hba, load_list);
2577 
2578 	if (!count) {
2579 		return (1);
2580 	}
2581 
2582 	/* Init the wakeup list */
2583 	wptr = (uint32_t *)&NewWakeUpParms->prog_id;
2584 	if (*wptr) {
2585 		wakeup_list[k++] = &NewWakeUpParms->prog_id;
2586 	}
2587 
2588 	wptr = (uint32_t *)&NewWakeUpParms->u0.boot_bios_id;
2589 	if (*wptr) {
2590 		wakeup_list[k++] = &NewWakeUpParms->u0.boot_bios_id;
2591 	}
2592 
2593 	wptr = (uint32_t *)&NewWakeUpParms->sli1_prog_id;
2594 	if (*wptr) {
2595 		wakeup_list[k++] = &NewWakeUpParms->sli1_prog_id;
2596 	}
2597 
2598 	wptr = (uint32_t *)&NewWakeUpParms->sli2_prog_id;
2599 	if (*wptr) {
2600 		wakeup_list[k++] = &NewWakeUpParms->sli2_prog_id;
2601 	}
2602 
2603 	wptr = (uint32_t *)&NewWakeUpParms->sli3_prog_id;
2604 	if (*wptr) {
2605 		wakeup_list[k++] = &NewWakeUpParms->sli3_prog_id;
2606 	}
2607 
2608 	wptr = (uint32_t *)&NewWakeUpParms->sli4_prog_id;
2609 	if (*wptr) {
2610 		wakeup_list[k++] = &NewWakeUpParms->sli4_prog_id;
2611 	}
2612 
2613 	if (k == 0) {
2614 		return (0);
2615 	}
2616 
2617 	/* Match load list to wakeup list */
2618 	for (i = 0; i < count; i++) {
2619 
2620 		wptr = (uint32_t *)&load_list[i];
2621 
2622 		for (j = 0; j < k; j++) {
2623 			if (bcmp((uint8_t *)wakeup_list[j],
2624 			    (uint8_t *)&load_list[i], sizeof (PROG_ID)) == 0) {
2625 				break;
2626 			}
2627 		}
2628 
2629 		/* No match */
2630 		if (j == k) {
2631 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2632 			    "Load List[%d]: %08x %08x  Removing.",
2633 			    i, wptr[0], wptr[1]);
2634 
2635 			(void) emlxs_delete_load_entry(hba, &load_list[i]);
2636 		} else {
2637 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2638 			    "Load List[%d]: %08x %08x  Preserving.",
2639 			    i, wptr[0], wptr[1]);
2640 		}
2641 	}
2642 
2643 	return (0);
2644 
2645 } /* emlxs_clean_flash() */
2646 
2647 
2648 /* ARGSUSED */
2649 static uint32_t
2650 emlxs_start_rel_download(emlxs_hba_t *hba,
2651     PIMAGE_HDR ImageHdr,
2652     caddr_t Buffer,
2653     PWAKE_UP_PARMS WakeUpParms,
2654     uint32_t dwc_flag)
2655 {
2656 	emlxs_port_t *port = &PPORT;
2657 	MAILBOXQ *mbox;
2658 	MAILBOX *mb;
2659 	uint32_t *Src;
2660 	uint32_t *Dst;
2661 	caddr_t DataBuffer = NULL;
2662 	uint32_t rval = 0;
2663 	uint32_t DlByteCount;
2664 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
2665 	uint32_t DlCount;
2666 	uint32_t i;
2667 	uint32_t *wptr;
2668 
2669 	wptr = (uint32_t *)&ImageHdr->Id;
2670 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2671 	    "Relative download: %08x %08x", wptr[0], wptr[1]);
2672 
2673 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
2674 	    KM_NOSLEEP)) == NULL) {
2675 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2676 		    "Unable to allocate data buffer.");
2677 
2678 		return (1);
2679 	}
2680 
2681 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2682 	    KM_NOSLEEP)) == NULL) {
2683 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2684 		    "Unable to allocate mailbox buffer.");
2685 
2686 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2687 
2688 		return (1);
2689 	}
2690 
2691 	mb = (MAILBOX *)mbox;
2692 
2693 	DlByteCount = ImageHdr->BlockSize;
2694 
2695 	emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
2696 	    &ImageHdr->Id, 0);
2697 
2698 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2699 	    "  Erasing flash...");
2700 
2701 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
2702 
2703 	if (rval) {
2704 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2705 		    "Unable to erase flash. Mailbox cmd=%x status=%x",
2706 		    mb->mbxCommand, mb->mbxStatus);
2707 
2708 		goto EXIT_REL_DOWNLOAD;
2709 	}
2710 
2711 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2712 	    "  Programming flash...");
2713 
2714 	while (DlByteCount) {
2715 		if (DlByteCount > SegSize) {
2716 			DlCount = SegSize;
2717 		} else {
2718 			DlCount = DlByteCount;
2719 		}
2720 		DlByteCount -= DlCount;
2721 
2722 		Dst = (uint32_t *)DataBuffer;
2723 		Src = (uint32_t *)Buffer;
2724 
2725 		for (i = 0; i < (DlCount / 4); i++) {
2726 			*Dst = *Src;
2727 			Dst++;
2728 			Src++;
2729 		}
2730 
2731 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
2732 		    (volatile uint32_t *)
2733 		    ((volatile char *)hba->sli.sli3.slim_addr +
2734 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2735 
2736 		emlxs_format_prog_flash(mbox,
2737 		    0,
2738 		    DlCount,
2739 		    PROGRAM_FLASH,
2740 		    (DlByteCount) ? 0 : 1,
2741 		    0, DlCount, &ImageHdr->Id, dwc_flag);
2742 
2743 		rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
2744 
2745 		if (rval) {
2746 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2747 			    "Unable to program flash. Mailbox cmd=%x status=%x",
2748 			    mb->mbxCommand, mb->mbxStatus);
2749 
2750 			goto EXIT_REL_DOWNLOAD;
2751 		}
2752 
2753 		Buffer += DlCount;
2754 	}
2755 
2756 #ifdef FMA_SUPPORT
2757 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2758 	    != DDI_FM_OK) {
2759 		EMLXS_MSGF(EMLXS_CONTEXT,
2760 		    &emlxs_invalid_access_handle_msg, NULL);
2761 
2762 		rval = 1;
2763 
2764 		goto EXIT_REL_DOWNLOAD;
2765 	}
2766 #endif  /* FMA_SUPPORT */
2767 
2768 	/* Update wakeup parameters */
2769 	switch (ImageHdr->Id.Type) {
2770 	case TEST_PROGRAM:
2771 		break;
2772 
2773 	case FUNC_FIRMWARE:
2774 		if (!dwc_flag) {
2775 			rval = emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
2776 			    &ImageHdr->Id);
2777 		} else {
2778 			WakeUpParms->prog_id = ImageHdr->Id;
2779 		}
2780 		break;
2781 
2782 	case BOOT_BIOS:
2783 		if (!dwc_flag) {
2784 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2785 			    "BOOT: Updating parms...");
2786 
2787 			rval = emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
2788 			    &ImageHdr->Id, 1);
2789 		} else {
2790 			if (hba->wakeup_parms.u0.boot_bios_wd[0]) {
2791 				WakeUpParms->u0.boot_bios_id = ImageHdr->Id;
2792 			}
2793 
2794 			if (!(hba->model_info.chip &
2795 			    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2796 				WakeUpParms->u1.EROM_prog_id = ImageHdr->Id;
2797 			}
2798 		}
2799 		break;
2800 
2801 	case SLI1_OVERLAY:
2802 		if (!dwc_flag) {
2803 			rval = emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
2804 			    &ImageHdr->Id);
2805 		} else {
2806 			WakeUpParms->sli1_prog_id = ImageHdr->Id;
2807 		}
2808 		break;
2809 
2810 	case SLI2_OVERLAY:
2811 		if (!dwc_flag) {
2812 			rval = emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
2813 			    &ImageHdr->Id);
2814 		} else {
2815 			WakeUpParms->sli2_prog_id = ImageHdr->Id;
2816 		}
2817 		break;
2818 
2819 	case SLI3_OVERLAY:
2820 		if (!dwc_flag) {
2821 			rval = emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
2822 			    &ImageHdr->Id);
2823 		} else {
2824 			WakeUpParms->sli3_prog_id = ImageHdr->Id;
2825 		}
2826 		break;
2827 
2828 	case SLI4_OVERLAY:
2829 		if (!dwc_flag) {
2830 			rval = emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
2831 			    &ImageHdr->Id);
2832 		} else {
2833 			WakeUpParms->sli4_prog_id = ImageHdr->Id;
2834 		}
2835 		break;
2836 
2837 	default:
2838 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2839 		    "Image type not supported. Type=%x", ImageHdr->Id.Type);
2840 
2841 		break;
2842 	}
2843 
2844 EXIT_REL_DOWNLOAD:
2845 	if (DataBuffer) {
2846 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2847 	}
2848 
2849 	if (mbox) {
2850 		kmem_free(mbox, sizeof (MAILBOXQ));
2851 	}
2852 
2853 	return (rval);
2854 
2855 } /* emlxs_start_rel_download() */
2856 
2857 
2858 static uint32_t
2859 emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer, emlxs_fw_image_t *fw_image)
2860 {
2861 	emlxs_port_t *port = &PPORT;
2862 	uint32_t rval = 0;
2863 	WAKE_UP_PARMS RelWakeUpParms;
2864 	WAKE_UP_PARMS WakeUpParms;
2865 	uint32_t i;
2866 	IMAGE_HDR ImageHdr;
2867 	caddr_t bptr;
2868 	uint32_t flash_cleaned = 0;
2869 
2870 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 0)) {
2871 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2872 		    "Unable to get wakeup parameters.");
2873 
2874 		return (EMLXS_IMAGE_FAILED);
2875 	}
2876 
2877 download:
2878 
2879 	bcopy(&WakeUpParms, &RelWakeUpParms, sizeof (WAKE_UP_PARMS));
2880 
2881 	for (i = 0; i < MAX_PROG_TYPES; i++) {
2882 		if (!fw_image->prog[i].version) {
2883 			continue;
2884 		}
2885 
2886 		bptr = buffer + fw_image->prog[i].offset;
2887 
2888 		bcopy(bptr, &ImageHdr, sizeof (IMAGE_HDR));
2889 
2890 		rval = emlxs_start_rel_download(hba, &ImageHdr, bptr,
2891 		    &RelWakeUpParms, 1);
2892 
2893 		if (rval) {
2894 			EMLXS_MSGF(EMLXS_CONTEXT,
2895 			    &emlxs_download_failed_msg,
2896 			    "Failed to program flash.");
2897 
2898 			if ((rval == NO_FLASH_MEM_AVAIL) && !flash_cleaned) {
2899 				/* Cleanup using current load list */
2900 				(void) emlxs_clean_flash(hba, 0, &WakeUpParms);
2901 
2902 				flash_cleaned = 1;
2903 				goto download;
2904 			}
2905 
2906 			return (EMLXS_IMAGE_FAILED);
2907 		}
2908 	}
2909 
2910 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2911 	    "Updating wakeup parameters.");
2912 
2913 	if (emlxs_update_wakeup_parms(hba, &RelWakeUpParms,
2914 	    &RelWakeUpParms)) {
2915 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2916 		    "Unable to update parameters.");
2917 
2918 		return (EMLXS_IMAGE_FAILED);
2919 	}
2920 
2921 	/* Cleanup using old wakeup paramters */
2922 	(void) emlxs_clean_flash(hba, &WakeUpParms, &RelWakeUpParms);
2923 
2924 	return (0);
2925 
2926 } /* emlxs_proc_rel_2mb() */
2927 
2928 
2929 #define	FLASH_POLLING_BIT	0x80
2930 #define	FLASH_ERROR_BIT		0x20
2931 
2932 typedef struct _flash_t
2933 {
2934 	uint32_t	offset;
2935 	uint8_t		val;
2936 } flash_t;
2937 
2938 
2939 
2940 static uint32_t
2941 emlxs_write_fcode_flash(emlxs_hba_t *hba,
2942     PIMAGE_HDR ImageHdr, caddr_t Buffer)
2943 {
2944 	emlxs_port_t *port = &PPORT;
2945 	uint8_t bb;
2946 	uint8_t cc;
2947 	uint8_t *src;
2948 	uint32_t DlByteCount = ImageHdr->BlockSize;
2949 	uint32_t i;
2950 	uint32_t j;
2951 	uint32_t k;
2952 
2953 	flash_t wr[3] = {
2954 		{0x555, 0xaa},
2955 		{0x2aa, 0x55},
2956 		{0x555, 0xa0}
2957 	};
2958 
2959 	/* Load Fcode */
2960 	src = (uint8_t *)Buffer + sizeof (IMAGE_HDR);
2961 	for (i = 0; i < DlByteCount; i++) {
2962 		for (k = 0; k < 3; k++) {
2963 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
2964 		}
2965 
2966 		/* Reverse Endian word alignment */
2967 		j = (i & 3) ^ 3;
2968 
2969 		bb = src[j];
2970 
2971 		if (j == 0) {
2972 			src += 4;
2973 		}
2974 
2975 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
2976 
2977 		/* check for complete */
2978 		for (;;) {
2979 			DELAYUS(20);
2980 
2981 			cc = SBUS_READ_FLASH_COPY(hba, i);
2982 
2983 			/* If data matches then continue */
2984 			if (cc == bb) {
2985 				break;
2986 			}
2987 
2988 			/* Polling bit will be inverse final value */
2989 			/* while active */
2990 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
2991 				/* Still busy */
2992 
2993 				/* Check for error bit */
2994 				if (cc & FLASH_ERROR_BIT) {
2995 					/* Read data one more time */
2996 					cc = SBUS_READ_FLASH_COPY(hba, i);
2997 
2998 					/* Check if data matches */
2999 					if (cc == bb) {
3000 						break;
3001 					}
3002 
3003 					EMLXS_MSGF(EMLXS_CONTEXT,
3004 					    &emlxs_download_failed_msg,
3005 					    "FCode write error: offset:%x "
3006 					    "wrote:%x read:%x\n", i, bb, cc);
3007 
3008 					return (1);
3009 				}
3010 			}
3011 		}
3012 	}
3013 
3014 	/* Load Header */
3015 	src = (uint8_t *)ImageHdr;
3016 
3017 	for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) {
3018 		for (k = 0; k < 3; k++) {
3019 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
3020 		}
3021 
3022 		/* Reverse Endian word alignment */
3023 		j = (i & 3) ^ 3;
3024 
3025 		bb = src[j];
3026 
3027 		if (j == 0) {
3028 			src += 4;
3029 		}
3030 
3031 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
3032 
3033 		/* check for complete */
3034 		for (;;) {
3035 			DELAYUS(20);
3036 
3037 			cc = SBUS_READ_FLASH_COPY(hba, i);
3038 
3039 			/* If data matches then continue */
3040 			if (cc == bb) {
3041 				break;
3042 			}
3043 
3044 			/* Polling bit will be inverse final value */
3045 			/* while active */
3046 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
3047 				/* Still busy */
3048 
3049 				/* Check for error bit */
3050 				if (cc & FLASH_ERROR_BIT) {
3051 					/* Read data one more time */
3052 					cc = SBUS_READ_FLASH_COPY(hba, i);
3053 
3054 					/* Check if data matches */
3055 					if (cc == bb) {
3056 						break;
3057 					}
3058 
3059 					EMLXS_MSGF(EMLXS_CONTEXT,
3060 					    &emlxs_download_failed_msg,
3061 					    "FCode write error: offset:%x "
3062 					    "wrote:%x read:%x\n", i, bb, cc);
3063 
3064 					return (1);
3065 				}
3066 			}
3067 		}
3068 	}
3069 
3070 #ifdef FMA_SUPPORT
3071 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
3072 	    != DDI_FM_OK) {
3073 		EMLXS_MSGF(EMLXS_CONTEXT,
3074 		    &emlxs_invalid_access_handle_msg, NULL);
3075 		return (1);
3076 	}
3077 #endif  /* FMA_SUPPORT */
3078 
3079 	return (0);
3080 
3081 } /* emlxs_write_fcode_flash() */
3082 
3083 
3084 
3085 static uint32_t
3086 emlxs_erase_fcode_flash(emlxs_hba_t *hba)
3087 {
3088 	emlxs_port_t *port = &PPORT;
3089 	int32_t i, j;
3090 	uint8_t cc;
3091 	uint32_t offset;
3092 
3093 	flash_t ef[6] = {
3094 		{0x555, 0xaa},
3095 		{0x2aa, 0x55},
3096 		{0x555, 0x80},
3097 		{0x555, 0xaa},
3098 		{0x2aa, 0x55},
3099 		{0x555, 0x10}
3100 	};
3101 
3102 	/* Auto select */
3103 	flash_t as[3] = {
3104 		{0x555, 0xaa},
3105 		{0x2aa, 0x55},
3106 		{0x555, 0x90}
3107 	};
3108 
3109 
3110 	/* Check Manufacturers Code */
3111 	for (i = 0; i < 3; i++) {
3112 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3113 	}
3114 
3115 	cc = SBUS_READ_FLASH_COPY(hba, 0);
3116 
3117 	/* Check Device Code */
3118 	for (i = 0; i < 3; i++) {
3119 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3120 	}
3121 
3122 	cc = SBUS_READ_FLASH_COPY(hba, 1);
3123 
3124 
3125 	/* Check block protections (up to 4 16K blocks = 64K) */
3126 	for (j = 0; j < 4; j++) {
3127 		for (i = 0; i < 3; i++) {
3128 			SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3129 		}
3130 
3131 		offset = (j << 14) | 0x2;
3132 
3133 		cc = SBUS_READ_FLASH_COPY(hba, offset);
3134 
3135 		if (cc == 0x01) {
3136 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3137 			    "Block %d is protected and can't be erased.", j);
3138 		}
3139 	}
3140 
3141 	/* Write erase flash sequence */
3142 	for (i = 0; i < 6; i++) {
3143 		SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val);
3144 	}
3145 
3146 	/* check for complete */
3147 	for (;;) {
3148 		/* Delay 3 seconds */
3149 		DELAYMS(3000);
3150 
3151 		cc = SBUS_READ_FLASH_COPY(hba, 0);
3152 
3153 
3154 		/* If data matches then continue; */
3155 		if (cc == 0xff) {
3156 			break;
3157 		}
3158 
3159 		/* Polling bit will be inverse final value while active */
3160 		if ((cc ^ 0xff) & FLASH_POLLING_BIT) {
3161 			/* Still busy */
3162 
3163 			/* Check for error bit */
3164 			if (cc & FLASH_ERROR_BIT) {
3165 				/* Read data one more time */
3166 				cc = SBUS_READ_FLASH_COPY(hba, 0);
3167 
3168 				/* Check if data matches */
3169 				if (cc == 0xff) {
3170 					break;
3171 				}
3172 
3173 				EMLXS_MSGF(EMLXS_CONTEXT,
3174 				    &emlxs_download_failed_msg,
3175 				    "FCode write error: offset:%x wrote:%x "
3176 				    "read:%x\n", i, 0xff, cc);
3177 
3178 				return (1);
3179 			}
3180 		}
3181 	}
3182 
3183 #ifdef FMA_SUPPORT
3184 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
3185 	    != DDI_FM_OK) {
3186 		EMLXS_MSGF(EMLXS_CONTEXT,
3187 		    &emlxs_invalid_access_handle_msg, NULL);
3188 		return (1);
3189 	}
3190 #endif  /* FMA_SUPPORT */
3191 
3192 	return (0);
3193 
3194 } /* emlxs_erase_fcode_flash() */
3195 
3196 
3197 static uint32_t
3198 emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId)
3199 {
3200 	emlxs_port_t *port = &PPORT;
3201 	MAILBOXQ *mbox = NULL;
3202 	MAILBOX *mb;
3203 	uint32_t rval = 0;
3204 
3205 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3206 	    KM_NOSLEEP)) == NULL) {
3207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3208 		    "Unable to allocate mailbox buffer.");
3209 
3210 		return (1);
3211 	}
3212 
3213 	mb = (MAILBOX *)mbox;
3214 	mb->mbxCommand = MBX_DEL_LD_ENTRY;
3215 	mb->un.varDelLdEntry.list_req = FLASH_LOAD_LIST;
3216 	mb->un.varDelLdEntry.prog_id = *progId;
3217 
3218 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3220 		    "Unable to delete load entry: Mailbox cmd=%x status=%x",
3221 		    mb->mbxCommand, mb->mbxStatus);
3222 
3223 		rval = 1;
3224 	}
3225 
3226 done:
3227 
3228 	if (mbox) {
3229 		kmem_free(mbox, sizeof (MAILBOXQ));
3230 	}
3231 
3232 	return (rval);
3233 
3234 } /* emlxs_delete_load_entry() */
3235 
3236 
3237 extern uint32_t
3238 emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
3239 {
3240 	emlxs_port_t *port = &PPORT;
3241 	LOAD_ENTRY *LoadEntry;
3242 	LOAD_LIST *LoadList = NULL;
3243 	uint32_t i;
3244 	uint32_t count = 0;
3245 
3246 	bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
3247 
3248 	if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST),
3249 	    KM_NOSLEEP)) == NULL) {
3250 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3251 		    "Unable to allocate LOADLIST buffer.");
3252 
3253 		goto done;
3254 	}
3255 
3256 	if (emlxs_read_load_list(hba, LoadList)) {
3257 		goto done;
3258 	}
3259 
3260 	for (i = 0; i < LoadList->entry_cnt; i++) {
3261 		LoadEntry = &LoadList->load_entry[i];
3262 		if ((LoadEntry->un.wd[0] != 0) &&
3263 		    (LoadEntry->un.wd[0] != 0xffffffff)) {
3264 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3265 			    "Load List[%d]: %08x %08x", count,
3266 			    LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
3267 
3268 			load_list[count++] = LoadEntry->un.id;
3269 		}
3270 	}
3271 
3272 done:
3273 
3274 	if (LoadList) {
3275 		kmem_free(LoadList, sizeof (LOAD_LIST));
3276 	}
3277 
3278 	return (count);
3279 
3280 } /* emlxs_get_load_list() */
3281 
3282 
3283 extern uint32_t
3284 emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
3285     uint32_t verbose)
3286 {
3287 	emlxs_port_t *port = &PPORT;
3288 	MAILBOXQ *mbox;
3289 	MAILBOX *mb;
3290 	uint32_t rval = 0;
3291 	uint32_t *wd;
3292 
3293 	bzero(WakeUpParms, sizeof (WAKE_UP_PARMS));
3294 
3295 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3296 	    KM_NOSLEEP)) == NULL) {
3297 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3298 		    "Unable to allocate mailbox buffer.");
3299 
3300 		return (1);
3301 	}
3302 
3303 	mb = (MAILBOX *)mbox;
3304 
3305 	emlxs_format_dump(hba, mbox,
3306 	    DMP_NV_PARAMS,
3307 	    WAKE_UP_PARMS_REGION_ID,
3308 	    sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
3309 
3310 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3311 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3312 		    "Unable to get parameters: Mailbox cmd=%x status=%x",
3313 		    mb->mbxCommand, mb->mbxStatus);
3314 
3315 		if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) {
3316 			rval = (uint32_t)CFG_DATA_NO_REGION;
3317 		} else {
3318 			rval = 1;
3319 		}
3320 	} else {
3321 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3322 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
3323 			    0, hba->sli.sli4.dump_region.size,
3324 			    DDI_DMA_SYNC_FORKERNEL);
3325 
3326 			bcopy((caddr_t)hba->sli.sli4.dump_region.virt,
3327 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
3328 		} else {
3329 			bcopy((caddr_t)&mb->un.varDmp.resp_offset,
3330 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
3331 		}
3332 
3333 		if (verbose) {
3334 			wd = (uint32_t *)&WakeUpParms->prog_id;
3335 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3336 			    "Wakeup:      prog_id=%08x %08x", wd[0], wd[1]);
3337 
3338 			wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id;
3339 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3340 			    "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]);
3341 
3342 			wd = (uint32_t *)&WakeUpParms->sli1_prog_id;
3343 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3344 			    "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]);
3345 
3346 			wd = (uint32_t *)&WakeUpParms->sli2_prog_id;
3347 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3348 			    "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]);
3349 
3350 			wd = (uint32_t *)&WakeUpParms->sli3_prog_id;
3351 			if (wd[0] || wd[1]) {
3352 				EMLXS_MSGF(EMLXS_CONTEXT,
3353 				    &emlxs_init_debug_msg,
3354 				    "Wakeup: sli3_prog_id=%08x %08x", wd[0],
3355 				    wd[1]);
3356 			}
3357 
3358 			wd = (uint32_t *)&WakeUpParms->sli4_prog_id;
3359 			if (wd[0] || wd[1]) {
3360 				EMLXS_MSGF(EMLXS_CONTEXT,
3361 				    &emlxs_init_debug_msg,
3362 				    "Wakeup: sli4_prog_id=%08x %08x", wd[0],
3363 				    wd[1]);
3364 			}
3365 
3366 			wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id;
3367 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3368 			    "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]);
3369 
3370 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3371 			    "Wakeup: pci_cfg_rsvd=%x",
3372 			    WakeUpParms->pci_cfg_rsvd);
3373 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3374 			    "Wakeup:  use_hdw_def=%x",
3375 			    WakeUpParms->use_hdw_def);
3376 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3377 			    "Wakeup:  pci_cfg_sel=%x",
3378 			    WakeUpParms->pci_cfg_sel);
3379 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3380 			    "Wakeup:   cfg_lookup=%x",
3381 			    WakeUpParms->pci_cfg_lookup_sel);
3382 		}
3383 	}
3384 
3385 done:
3386 
3387 	if (mbox) {
3388 		kmem_free(mbox, sizeof (MAILBOXQ));
3389 	}
3390 
3391 #ifdef FMA_SUPPORT
3392 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3393 		if (emlxs_fm_check_dma_handle(hba,
3394 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3395 			EMLXS_MSGF(EMLXS_CONTEXT,
3396 			    &emlxs_invalid_dma_handle_msg,
3397 			    "emlxs_read_wakeup_parms: hdl=%p",
3398 			    hba->sli.sli4.dump_region.dma_handle);
3399 			rval = 1;
3400 		}
3401 	}
3402 #endif  /* FMA_SUPPORT */
3403 
3404 	return (rval);
3405 
3406 } /* emlxs_read_wakeup_parms() */
3407 
3408 
3409 static uint32_t
3410 emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
3411 {
3412 	emlxs_port_t *port = &PPORT;
3413 	LOAD_ENTRY *LoadEntry;
3414 	uint32_t *Uptr;
3415 	uint32_t CurEntryAddr;
3416 	MAILBOXQ *mbox = NULL;
3417 	MAILBOX *mb;
3418 
3419 	bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
3420 
3421 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3422 	    KM_NOSLEEP)) == NULL) {
3423 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3424 		    "Unable to allocate mailbox buffer.");
3425 
3426 		return (1);
3427 	}
3428 
3429 	mb = (MAILBOX *)mbox;
3430 
3431 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
3432 
3433 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3434 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3435 		    "Unable to get load list: Mailbox cmd=%x status=%x",
3436 		    mb->mbxCommand, mb->mbxStatus);
3437 
3438 		goto done;
3439 	}
3440 
3441 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3442 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
3443 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
3444 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
3445 	} else {
3446 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
3447 	}
3448 
3449 	LoadList->head = Uptr[0];
3450 	LoadList->tail = Uptr[1];
3451 
3452 	CurEntryAddr = LoadList->head;
3453 
3454 	while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
3455 	    (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
3456 		LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
3457 		LoadList->entry_cnt++;
3458 
3459 		emlxs_format_dump(hba, mbox,
3460 		    DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
3461 
3462 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3463 		    MBX_SUCCESS) {
3464 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3465 			    "Unable to get load list (%d): Mailbox cmd=%x "
3466 			    "status=%x", LoadList->entry_cnt, mb->mbxCommand,
3467 			    mb->mbxStatus);
3468 
3469 			goto done;
3470 		}
3471 
3472 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3473 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
3474 			    0, hba->sli.sli4.dump_region.size,
3475 			    DDI_DMA_SYNC_FORKERNEL);
3476 			Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
3477 		} else {
3478 			Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
3479 		}
3480 
3481 		LoadEntry->next = Uptr[0];
3482 		LoadEntry->prev = Uptr[1];
3483 		LoadEntry->start_adr = Uptr[2];
3484 		LoadEntry->len = Uptr[3];
3485 		LoadEntry->un.wd[0] = Uptr[4];
3486 		LoadEntry->un.wd[1] = Uptr[5];
3487 
3488 		/* update next current load entry address */
3489 		CurEntryAddr = LoadEntry->next;
3490 
3491 	}	/* end of while (not end of list) */
3492 
3493 done:
3494 
3495 	if (mbox) {
3496 		kmem_free(mbox, sizeof (MAILBOXQ));
3497 	}
3498 
3499 #ifdef FMA_SUPPORT
3500 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3501 		if (emlxs_fm_check_dma_handle(hba,
3502 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3503 			EMLXS_MSGF(EMLXS_CONTEXT,
3504 			    &emlxs_invalid_dma_handle_msg,
3505 			    "emlxs_read_load_list: hdl=%p",
3506 			    hba->sli.sli4.dump_region.dma_handle);
3507 			return (1);
3508 		}
3509 	}
3510 #endif  /* FMA_SUPPORT */
3511 
3512 	return (0);
3513 
3514 } /* emlxs_read_load_list() */
3515 
3516 
3517 
3518 
3519 static int
3520 emlxs_build_parms(caddr_t Buffer,
3521     PWAKE_UP_PARMS AbsWakeUpParms,
3522     uint32_t BufferSize, PAIF_HDR AifHeader)
3523 {
3524 	IMAGE_HDR ImageHdr;
3525 	uint32_t NextImage;
3526 	uint32_t i;
3527 	int32_t ChangeParams = FALSE;
3528 	caddr_t Sptr;
3529 	caddr_t Dptr;
3530 
3531 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
3532 
3533 	if ((AifHeader->ImageBase != 0x20000) &&
3534 	    ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
3535 		return (FALSE);
3536 	}
3537 
3538 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
3539 
3540 	while (BufferSize > NextImage) {
3541 		Sptr = &Buffer[NextImage];
3542 		Dptr = (caddr_t)&ImageHdr;
3543 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
3544 			Dptr[i] = Sptr[i];
3545 		}
3546 
3547 		if (ImageHdr.BlockSize == 0xffffffff)
3548 			break;
3549 
3550 		switch (ImageHdr.Id.Type) {
3551 		case TEST_PROGRAM:
3552 			break;
3553 		case FUNC_FIRMWARE:
3554 			AbsWakeUpParms->prog_id = ImageHdr.Id;
3555 			ChangeParams = TRUE;
3556 			break;
3557 		case BOOT_BIOS:
3558 			AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
3559 			ChangeParams = TRUE;
3560 			break;
3561 		case SLI1_OVERLAY:
3562 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
3563 			ChangeParams = TRUE;
3564 			break;
3565 		case SLI2_OVERLAY:
3566 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
3567 			ChangeParams = TRUE;
3568 			break;
3569 		case SLI3_OVERLAY:
3570 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
3571 			ChangeParams = TRUE;
3572 			break;
3573 		case SLI4_OVERLAY:
3574 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
3575 			ChangeParams = TRUE;
3576 			break;
3577 		default:
3578 			break;
3579 		}
3580 
3581 		NextImage += ImageHdr.BlockSize;
3582 	}
3583 
3584 	return (ChangeParams);
3585 
3586 } /* emlxs_build_parms() */
3587 
3588 
3589 static uint32_t
3590 emlxs_update_wakeup_parms(emlxs_hba_t *hba,
3591     PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
3592 {
3593 	emlxs_port_t *port = &PPORT;
3594 	MAILBOX *mb;
3595 	MAILBOXQ *mbox;
3596 	uint32_t rval = 0;
3597 
3598 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3599 	    KM_NOSLEEP)) == NULL) {
3600 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3601 		    "Unable to allocate mailbox buffer.");
3602 
3603 		return (1);
3604 	}
3605 
3606 	mb = (MAILBOX *)mbox;
3607 
3608 	WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
3609 	WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
3610 	WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
3611 	WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
3612 	WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
3613 	WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
3614 
3615 	emlxs_format_update_parms(mbox, WakeUpParms);
3616 
3617 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3618 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3619 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
3620 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
3621 
3622 		rval = 1;
3623 	}
3624 
3625 	if (mbox) {
3626 		kmem_free(mbox, sizeof (MAILBOXQ));
3627 	}
3628 
3629 	return (rval);
3630 
3631 } /* emlxs_update_wakeup_parms() */
3632 
3633 
3634 static uint32_t
3635 emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
3636     uint32_t type, char *file_type)
3637 {
3638 	emlxs_port_t *port = &PPORT;
3639 
3640 	/* Create the version label */
3641 	emlxs_decode_version(file->version, file->label);
3642 
3643 	/* Process the DWC type */
3644 	switch (type) {
3645 	case TEST_PROGRAM:
3646 
3647 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3648 		    "%s: TEST: offset=%08x  version=%08x, %s", file_type,
3649 		    file->offset, file->version, file->label);
3650 
3651 		break;
3652 
3653 	case BOOT_BIOS:
3654 
3655 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3656 		    "%s: BOOT: offset=%08x  version=%08x, %s", file_type,
3657 		    file->offset, file->version, file->label);
3658 
3659 		if (!emlxs_bios_check(hba, id)) {
3660 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3661 			    "BOOT Check: Image not compatible with %s. id=%02x",
3662 			    hba->model_info.model, id);
3663 
3664 			return (EMLXS_IMAGE_INCOMPATIBLE);
3665 		}
3666 
3667 		break;
3668 
3669 	case FUNC_FIRMWARE:	/* Stub */
3670 
3671 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3672 		    "%s: STUB: offset=%08x  version=%08x, %s", file_type,
3673 		    file->offset, file->version, file->label);
3674 
3675 		if (!emlxs_stub_check(hba, id)) {
3676 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3677 			    "STUB Check: Image not compatible with %s. id=%02x",
3678 			    hba->model_info.model, id);
3679 
3680 			return (EMLXS_IMAGE_INCOMPATIBLE);
3681 		}
3682 
3683 		break;
3684 
3685 	case SLI1_OVERLAY:
3686 
3687 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3688 		    "%s: SLI1: offset=%08x  version=%08x, %s", file_type,
3689 		    file->offset, file->version, file->label);
3690 
3691 		if (!emlxs_sli1_check(hba, id)) {
3692 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3693 			    "SLI1 Check: Image not compatible with %s. id=%02x",
3694 			    hba->model_info.model, id);
3695 
3696 			return (EMLXS_IMAGE_INCOMPATIBLE);
3697 		}
3698 
3699 		break;
3700 
3701 	case SLI2_OVERLAY:
3702 
3703 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3704 		    "%s: SLI2: offset=%08x  version=%08x, %s", file_type,
3705 		    file->offset, file->version, file->label);
3706 
3707 		if (!emlxs_sli2_check(hba, id)) {
3708 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3709 			    "SLI2 Check: Image not compatible with %s. id=%02x",
3710 			    hba->model_info.model, id);
3711 
3712 			return (EMLXS_IMAGE_INCOMPATIBLE);
3713 		}
3714 
3715 		break;
3716 
3717 	case SLI3_OVERLAY:
3718 
3719 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3720 		    "%s: SLI3: offset=%08x  version=%08x, %s", file_type,
3721 		    file->offset, file->version, file->label);
3722 
3723 		if (!emlxs_sli3_check(hba, id)) {
3724 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3725 			    "SLI3 Check: Image not compatible with %s. id=%02x",
3726 			    hba->model_info.model, id);
3727 
3728 			return (EMLXS_IMAGE_INCOMPATIBLE);
3729 		}
3730 
3731 		break;
3732 
3733 	case SLI4_OVERLAY:
3734 
3735 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3736 		    "%s: SLI4: offset=%08x  version=%08x, %s", file_type,
3737 		    file->offset, file->version, file->label);
3738 
3739 		if (!emlxs_sli4_check(hba, id)) {
3740 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3741 			    "SLI4 Check: Image not compatible with %s. id=%02x",
3742 			    hba->model_info.model, id);
3743 
3744 			return (EMLXS_IMAGE_INCOMPATIBLE);
3745 		}
3746 
3747 		break;
3748 
3749 	case SBUS_FCODE:
3750 
3751 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3752 		    "%s: SBUS FCODE: offset=%08x  version=%08x, %s",
3753 		    file_type, file->offset, file->version, file->label);
3754 
3755 		if (!emlxs_sbus_fcode_check(hba, id)) {
3756 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3757 			    "SBUS FCODE Check: Image not compatible with %s. "
3758 			    "id=%02x", hba->model_info.model, id);
3759 
3760 			return (EMLXS_IMAGE_INCOMPATIBLE);
3761 		}
3762 
3763 		break;
3764 
3765 	case KERNEL_CODE:
3766 
3767 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3768 		    "%s: KERN: offset=%08x  version=%08x, %s", file_type,
3769 		    file->offset, file->version, file->label);
3770 
3771 		if (!emlxs_kern_check(hba, id)) {
3772 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3773 			    "KERN Check: Image not compatible with %s. id=%02x",
3774 			    hba->model_info.model, id);
3775 
3776 			return (EMLXS_IMAGE_INCOMPATIBLE);
3777 		}
3778 
3779 		break;
3780 
3781 	default:
3782 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3783 		    "%s: Image type not supported. type=%x", file_type, type);
3784 
3785 		return (EMLXS_IMAGE_BAD);
3786 	}
3787 
3788 	return (0);
3789 
3790 } /* emlxs_validate_version() */
3791 
3792 
3793 static void
3794 emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *fw_image)
3795 {
3796 	emlxs_port_t *port = &PPORT;
3797 	emlxs_vpd_t *vpd = &VPD;
3798 	uint32_t i;
3799 	uint32_t count;
3800 
3801 	/* Check for AWC file */
3802 	if (fw_image->awc.version) {
3803 		if (fw_image->awc.version == vpd->postKernRev) {
3804 			fw_image->awc.version = 0;
3805 		}
3806 
3807 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3808 		    "AWC file: KERN: old=%s  new=%s  %s.",
3809 		    vpd->postKernName,
3810 		    fw_image->awc.label,
3811 		    (fw_image->awc.version)? "Update":"Skip");
3812 	}
3813 
3814 	/* Check for BWC file */
3815 	if (fw_image->bwc.version) {
3816 		if (strcmp(vpd->fcode_version, fw_image->bwc.label) == 0) {
3817 			fw_image->bwc.version = 0;
3818 		}
3819 
3820 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3821 		    "BWC file: BOOT: old=%s  new=%s  %s.",
3822 		    vpd->fcode_version,
3823 		    fw_image->bwc.label,
3824 		    (fw_image->bwc.version)? "Update":"Skip");
3825 	}
3826 
3827 	/* Check for DWC file */
3828 	if (fw_image->dwc.version) {
3829 		/* Check for program files */
3830 		count = 0;
3831 		for (i = 0; i < MAX_PROG_TYPES; i++) {
3832 			if (!fw_image->prog[i].version) {
3833 				continue;
3834 			}
3835 
3836 			/* Skip components that don't need updating */
3837 			switch (i) {
3838 			case TEST_PROGRAM:
3839 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3840 				    "DWC file: TEST:             new=%s  "
3841 				    "Update.",
3842 				    fw_image->prog[i].label);
3843 				break;
3844 
3845 			case BOOT_BIOS:
3846 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3847 				    "DWC file: BOOT:             new=%s  "
3848 				    "Update.",
3849 				    fw_image->prog[i].label);
3850 				break;
3851 
3852 			case FUNC_FIRMWARE:
3853 				if (vpd->opFwRev &&
3854 				    (fw_image->prog[i].version ==
3855 				    vpd->opFwRev)) {
3856 					fw_image->prog[i].version = 0;
3857 				}
3858 
3859 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3860 				    "DWC file: STUB: old=%s  new=%s  %s.",
3861 				    vpd->opFwName,
3862 				    fw_image->prog[i].label,
3863 				    (fw_image->prog[i].version)?
3864 				    "Update":"Skip");
3865 				break;
3866 
3867 			case SLI1_OVERLAY:
3868 				if (vpd->sli1FwRev &&
3869 				    (fw_image->prog[i].version ==
3870 				    vpd->sli1FwRev)) {
3871 					fw_image->prog[i].version = 0;
3872 				}
3873 
3874 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3875 				    "DWC file: SLI1: old=%s  new=%s  %s.",
3876 				    vpd->sli1FwName,
3877 				    fw_image->prog[i].label,
3878 				    (fw_image->prog[i].version)?
3879 				    "Update":"Skip");
3880 				break;
3881 
3882 			case SLI2_OVERLAY:
3883 				if (vpd->sli2FwRev &&
3884 				    (fw_image->prog[i].version ==
3885 				    vpd->sli2FwRev)) {
3886 					fw_image->prog[i].version = 0;
3887 				}
3888 
3889 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3890 				    "DWC file: SLI2: old=%s  new=%s  %s.",
3891 				    vpd->sli2FwName,
3892 				    fw_image->prog[i].label,
3893 				    (fw_image->prog[i].version)?
3894 				    "Update":"Skip");
3895 				break;
3896 
3897 			case SLI3_OVERLAY:
3898 				if (vpd->sli3FwRev &&
3899 				    (fw_image->prog[i].version ==
3900 				    vpd->sli3FwRev)) {
3901 					fw_image->prog[i].version = 0;
3902 				}
3903 
3904 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3905 				    "DWC file: SLI3: old=%s  new=%s  %s.",
3906 				    vpd->sli3FwName,
3907 				    fw_image->prog[i].label,
3908 				    (fw_image->prog[i].version)?
3909 				    "Update":"Skip");
3910 				break;
3911 
3912 			case SLI4_OVERLAY:
3913 				if (vpd->sli4FwRev &&
3914 				    (fw_image->prog[i].version ==
3915 				    vpd->sli4FwRev)) {
3916 					fw_image->prog[i].version = 0;
3917 				}
3918 
3919 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3920 				    "DWC file: SLI4: old=%s  new=%s  %s.",
3921 				    vpd->sli4FwRev,
3922 				    fw_image->prog[i].label,
3923 				    (fw_image->prog[i].version)?
3924 				    "Update":"Skip");
3925 				break;
3926 
3927 			default:
3928 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3929 				    "DWC file: type=%x version=%x label=%s  "
3930 				    "Update.",
3931 				    i,
3932 				    fw_image->prog[i].version,
3933 				    fw_image->prog[i].label);
3934 			}
3935 
3936 			if (fw_image->prog[i].version) {
3937 				count++;
3938 			}
3939 		}
3940 
3941 		if (!count) {
3942 			fw_image->dwc.version = 0;
3943 		}
3944 	}
3945 
3946 	return;
3947 
3948 } /* emlxs_verify_image() */
3949 
3950 
3951 static uint32_t
3952 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
3953     emlxs_fw_image_t *image)
3954 {
3955 	emlxs_port_t *port = &PPORT;
3956 	uint32_t ImageType;
3957 	AIF_HDR AifHdr;
3958 	IMAGE_HDR ImageHdr;
3959 	uint32_t NextImage;
3960 	uint32_t count;
3961 	uint32_t FileType;
3962 	uint32_t FileLen = 0;
3963 	uint32_t TotalLen = 0;
3964 	uint32_t *CkSumEnd;
3965 	uint32_t id;
3966 	uint32_t type;
3967 	uint32_t ver;
3968 	uint32_t ImageLength;
3969 	uint32_t BufferSize;
3970 	uint32_t rval = 0;
3971 	caddr_t bptr;
3972 	emlxs_vpd_t *vpd;
3973 
3974 	vpd = &VPD;
3975 
3976 	/* Get image type */
3977 	ImageType = *((uint32_t *)Buffer);
3978 
3979 	/* Pegasus and beyond adapters */
3980 	if ((ImageType == NOP_IMAGE_TYPE) &&
3981 	    !(hba->model_info.chip &
3982 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
3983 		bptr = Buffer;
3984 		TotalLen = sizeof (uint32_t);
3985 
3986 		while (TotalLen < Size) {
3987 			if (Size < sizeof (AIF_HDR)) {
3988 				EMLXS_MSGF(EMLXS_CONTEXT,
3989 				    &emlxs_image_bad_msg,
3990 				    "Invalid image header length: 0x%x < 0x%x",
3991 				    Size, sizeof (AIF_HDR));
3992 
3993 				return (EMLXS_IMAGE_BAD);
3994 			}
3995 
3996 			bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
3997 			emlxs_disp_aif_header(hba, &AifHdr);
3998 
3999 			ImageLength = AifHdr.RoSize;
4000 
4001 			/* Validate checksum */
4002 			CkSumEnd =
4003 			    (uint32_t *)(bptr + ImageLength +
4004 			    sizeof (AIF_HDR));
4005 			if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
4006 				EMLXS_MSGF(EMLXS_CONTEXT,
4007 				    &emlxs_image_bad_msg,
4008 				    "Invalid checksum found.");
4009 
4010 				return (EMLXS_IMAGE_BAD);
4011 			}
4012 
4013 			FileType = AifHdr.ZinitBr;
4014 			switch (FileType) {
4015 			case FILE_TYPE_AWC:
4016 				image->awc.offset =
4017 				    (uint32_t)((uintptr_t)bptr -
4018 				    (uintptr_t)Buffer);
4019 				image->awc.version = AifHdr.AVersion;
4020 				image->awc.revcomp = 0;
4021 
4022 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4023 				type = emlxs_type_check(
4024 				    (AifHdr.AVersion & 0xff000000) >> 24);
4025 
4026 				/* Validate the file version */
4027 				if ((rval = emlxs_validate_version(hba,
4028 				    &image->awc, id, type, "AWC file"))) {
4029 					return (rval);
4030 				}
4031 
4032 				break;
4033 
4034 			case FILE_TYPE_BWC:
4035 				image->bwc.offset =
4036 				    (uint32_t)((uintptr_t)bptr -
4037 				    (uintptr_t)Buffer);
4038 				image->bwc.version = AifHdr.AVersion;
4039 				image->bwc.revcomp = 0;
4040 
4041 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4042 				type = emlxs_type_check(
4043 				    (AifHdr.AVersion & 0xff000000) >> 24);
4044 
4045 				/* Validate the file version */
4046 				if ((rval = emlxs_validate_version(hba,
4047 				    &image->bwc, id, type, "BWC file"))) {
4048 					return (rval);
4049 				}
4050 
4051 				break;
4052 
4053 			case FILE_TYPE_DWC:
4054 				image->dwc.offset =
4055 				    (uint32_t)((uintptr_t)bptr -
4056 				    (uintptr_t)Buffer);
4057 				image->dwc.version = AifHdr.AVersion;
4058 				image->dwc.revcomp = 0;
4059 
4060 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4061 				type = emlxs_type_check(
4062 				    (AifHdr.AVersion & 0xff000000) >> 24);
4063 
4064 				/* Validate the file version */
4065 				if ((rval = emlxs_validate_version(hba,
4066 				    &image->dwc, id, type, "DWC file"))) {
4067 					return (rval);
4068 				}
4069 
4070 				/* Scan for program types */
4071 				NextImage = sizeof (AIF_HDR) + 4;
4072 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
4073 
4074 				count = 0;
4075 				while (BufferSize > NextImage) {
4076 					bcopy(&bptr[NextImage], &ImageHdr,
4077 					    sizeof (IMAGE_HDR));
4078 					emlxs_dump_image_header(hba,
4079 					    &ImageHdr);
4080 
4081 					/* Validate block size */
4082 					if (ImageHdr.BlockSize == 0xffffffff) {
4083 						break;
4084 					}
4085 
4086 					type = emlxs_type_check(
4087 					    ImageHdr.Id.Type);
4088 
4089 					/* Calculate the program offset */
4090 					image->prog[type].offset =
4091 					    (uint32_t)((uintptr_t)
4092 					    &bptr[NextImage] -
4093 					    (uintptr_t)Buffer);
4094 
4095 					/* Acquire the versions */
4096 					image->prog[type].version =
4097 					    (ImageHdr.Id.Type << 24) |
4098 					    (ImageHdr.Id.Id << 16) |
4099 					    (ImageHdr.Id.Ver << 8) |
4100 					    ImageHdr.Id.Rev;
4101 
4102 					image->prog[type].revcomp =
4103 					    ImageHdr.Id.un.revcomp;
4104 
4105 					/* Validate the file version */
4106 					if ((rval = emlxs_validate_version(hba,
4107 					    &image->prog[type], ImageHdr.Id.Id,
4108 					    type, "DWC prog"))) {
4109 						return (rval);
4110 					}
4111 
4112 					count++;
4113 					NextImage += ImageHdr.BlockSize;
4114 
4115 				}	/* while () */
4116 
4117 				if (count == 0) {
4118 					EMLXS_MSGF(EMLXS_CONTEXT,
4119 					    &emlxs_image_bad_msg,
4120 					    "DWC file has no PRG images.");
4121 
4122 					return (EMLXS_IMAGE_BAD);
4123 				}
4124 
4125 				break;
4126 			}
4127 
4128 			FileLen =
4129 			    sizeof (AIF_HDR) + ImageLength +
4130 			    sizeof (uint32_t);
4131 			TotalLen += FileLen;
4132 			bptr += FileLen;
4133 		}
4134 	}
4135 
4136 	/* Pre-pegasus adapters */
4137 
4138 	else if (ImageType == NOP_IMAGE_TYPE) {
4139 		if (Size < sizeof (AIF_HDR)) {
4140 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4141 			    "Invalid image header length: 0x%x < 0x%x", Size,
4142 			    sizeof (AIF_HDR));
4143 
4144 			return (EMLXS_IMAGE_BAD);
4145 		}
4146 
4147 		bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
4148 		emlxs_disp_aif_header(hba, &AifHdr);
4149 
4150 		ImageLength = AifHdr.RoSize + AifHdr.RwSize;
4151 
4152 		if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
4153 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4154 			    "Image length incorrect: 0x%x != 0x%x", Size,
4155 			    sizeof (AIF_HDR) + ImageLength +
4156 			    sizeof (uint32_t));
4157 
4158 			return (EMLXS_IMAGE_BAD);
4159 		}
4160 
4161 		if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
4162 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4163 			    "Invalid imageBase value %x != 0x20000",
4164 			    AifHdr.ImageBase);
4165 
4166 			return (EMLXS_IMAGE_BAD);
4167 		}
4168 
4169 		CkSumEnd =
4170 		    (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
4171 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4172 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4173 			    "Invalid checksum found.");
4174 
4175 			return (EMLXS_IMAGE_BAD);
4176 		}
4177 
4178 		image->dwc.offset = 0;
4179 		image->dwc.version = AifHdr.AVersion;
4180 		image->dwc.revcomp = 0;
4181 
4182 		id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4183 		type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
4184 
4185 		/* Validate the file version */
4186 		if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
4187 		    "DWC file"))) {
4188 			return (rval);
4189 		}
4190 
4191 		NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
4192 		while (Size > NextImage) {
4193 			bcopy(&Buffer[NextImage], &ImageHdr,
4194 			    sizeof (IMAGE_HDR));
4195 			emlxs_dump_image_header(hba, &ImageHdr);
4196 
4197 			/* Validate block size */
4198 			if (ImageHdr.BlockSize == 0xffffffff) {
4199 				break;
4200 			}
4201 
4202 			type = emlxs_type_check(ImageHdr.Id.Type);
4203 
4204 			/* Calculate the program offset */
4205 			image->prog[type].offset = NextImage;
4206 
4207 			/* Acquire the versions */
4208 			image->prog[type].version =
4209 			    (ImageHdr.Id.Type << 24) |
4210 			    (ImageHdr.Id.Id << 16) |
4211 			    (ImageHdr.Id.Ver << 8) |
4212 			    ImageHdr.Id.Rev;
4213 
4214 			image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4215 
4216 			/* Validate the file version */
4217 			if ((rval = emlxs_validate_version(hba,
4218 			    &image->prog[type], ImageHdr.Id.Id, type,
4219 			    "DWC prog"))) {
4220 				return (rval);
4221 			}
4222 
4223 			NextImage += ImageHdr.BlockSize;
4224 		}
4225 
4226 	} else { /* PRG File */
4227 
4228 		/* Precheck image size */
4229 		if (Size < sizeof (IMAGE_HDR)) {
4230 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4231 			    "Invalid image header length: 0x%x < 0x%x", Size,
4232 			    sizeof (IMAGE_HDR));
4233 
4234 			return (EMLXS_IMAGE_BAD);
4235 		}
4236 
4237 		bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
4238 		emlxs_dump_image_header(hba, &ImageHdr);
4239 
4240 		/* Validate block size */
4241 		if (ImageHdr.BlockSize == 0xffffffff) {
4242 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4243 			    "Invalid block size.");
4244 
4245 			return (EMLXS_IMAGE_BAD);
4246 		}
4247 
4248 		ImageLength = ImageHdr.BlockSize;
4249 
4250 		/* Validate image length */
4251 		if (Size != ImageLength) {
4252 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4253 			    "Invalid image length: 0x%x != 0x%x", Size,
4254 			    ImageLength);
4255 
4256 			return (EMLXS_IMAGE_BAD);
4257 		}
4258 
4259 		/* Validate Checksum */
4260 		CkSumEnd =
4261 		    (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
4262 		    1;
4263 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4264 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4265 			    "Invalid checksum found.");
4266 
4267 			return (EMLXS_IMAGE_BAD);
4268 		}
4269 
4270 		type = emlxs_type_check(ImageHdr.Id.Type);
4271 
4272 		/* Calculate the program offset */
4273 		image->prog[type].offset = 0;
4274 
4275 		/* Acquire the versions */
4276 		image->prog[type].version =
4277 		    (ImageHdr.Id.Type << 24) |
4278 		    (ImageHdr.Id.Id << 16) |
4279 		    (ImageHdr.Id.Ver << 8) |
4280 		    ImageHdr.Id.Rev;
4281 
4282 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4283 
4284 		/* Validate the file version */
4285 		if ((rval = emlxs_validate_version(hba, &image->prog[type],
4286 		    ImageHdr.Id.Id, type, "DWC file"))) {
4287 			return (rval);
4288 		}
4289 	}
4290 
4291 	/*
4292 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
4293 	 * image file is < version 3.8
4294 	 */
4295 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
4296 		ver = (image->prog[SLI2_OVERLAY].version &
4297 		    0x0000ff00) >> 8;
4298 
4299 		if (ver >= 0x38) {
4300 			EMLXS_MSGF(EMLXS_CONTEXT,
4301 			    &emlxs_image_incompat_msg,
4302 			    "ASIC Check: Image requires DragonFly "
4303 			    "V2 ASIC");
4304 
4305 			return (EMLXS_IMAGE_INCOMPATIBLE);
4306 		}
4307 	}
4308 
4309 	return (0);
4310 
4311 } /* emlxs_validate_image() */
4312 
4313 
4314 static uint32_t
4315 emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
4316 {
4317 	emlxs_port_t *port = &PPORT;
4318 	MAILBOXQ *mbox;
4319 	MAILBOX *mb;
4320 	uint32_t next_address;
4321 	uint32_t rval = 0;
4322 
4323 	if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
4324 		return (1);
4325 	}
4326 
4327 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4328 	    KM_NOSLEEP)) == NULL) {
4329 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4330 		    "Unable to allocate mailbox buffer.");
4331 
4332 		return (1);
4333 	}
4334 
4335 	bzero(mbox, sizeof (MAILBOXQ));
4336 
4337 	mb = (MAILBOX *)mbox;
4338 	mb->mbxCommand = MBX_LOAD_EXP_ROM;
4339 	mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
4340 	mb->un.varLdExpRom.progress = 0;
4341 	mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4342 	mbox->mbox_cmpl = NULL;
4343 
4344 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4345 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4346 		    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4347 		    mb->mbxCommand, mb->mbxStatus);
4348 
4349 		rval = 1;
4350 
4351 		goto SLI_DOWNLOAD_EXIT;
4352 	}
4353 
4354 	if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
4355 		(void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4356 
4357 		rval = 1;
4358 		goto SLI_DOWNLOAD_EXIT;
4359 	}
4360 
4361 	if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
4362 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4363 		    "Invalid exp ROM progress. progress=%x",
4364 		    mb->un.varLdExpRom.progress);
4365 
4366 		rval = 1;
4367 
4368 		goto SLI_DOWNLOAD_EXIT;
4369 	}
4370 
4371 	/*
4372 	 * continue Erase
4373 	 */
4374 	while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
4375 
4376 		next_address = mb->un.varLdExpRom.dl_to_adr;
4377 
4378 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
4379 
4380 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
4381 		mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
4382 		mb->un.varLdExpRom.dl_to_adr = next_address;
4383 		mb->un.varLdExpRom.progress = 0;
4384 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4385 		mbox->mbox_cmpl = NULL;
4386 
4387 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4388 		    MBX_SUCCESS) {
4389 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4390 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4391 			    mb->mbxCommand, mb->mbxStatus);
4392 
4393 			rval = 1;
4394 			goto SLI_DOWNLOAD_EXIT;
4395 		}
4396 
4397 	}
4398 
4399 	while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
4400 		next_address = mb->un.varLdExpRom.dl_to_adr;
4401 
4402 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
4403 
4404 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
4405 		mb->un.varLdExpRom.step = EROM_CMD_COPY;
4406 		mb->un.varLdExpRom.dl_to_adr = next_address;
4407 		mb->un.varLdExpRom.progress = 0;
4408 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4409 		mbox->mbox_cmpl = NULL;
4410 
4411 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4412 		    MBX_SUCCESS) {
4413 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4414 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4415 			    mb->mbxCommand, mb->mbxStatus);
4416 
4417 			rval = 1;
4418 
4419 			goto SLI_DOWNLOAD_EXIT;
4420 		}
4421 	}
4422 
4423 	rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4424 
4425 SLI_DOWNLOAD_EXIT:
4426 
4427 	if (mbox) {
4428 		kmem_free(mbox, sizeof (MAILBOXQ));
4429 	}
4430 
4431 	return (rval);
4432 
4433 } /* emlxs_update_exp_rom() */
4434 
4435 
4436 /*
4437  *
4438  * FUNCTION NAME: emlxs_start_abs_download_2mb
4439  *
4440  * DESCRIPTION: Perform absolute download for 2 MB flash.  A incoming
4441  *              buffer may consist of more than 1 file.  This function
4442  *              will parse the buffer to find all the files.
4443  *
4444  *
4445  * PARAMETERS:
4446  *
4447  *
4448  * RETURNS:
4449  *
4450  */
4451 /* ARGSUSED */
4452 static uint32_t
4453 emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
4454     uint32_t offline, emlxs_fw_image_t *fw_image)
4455 {
4456 	emlxs_port_t *port = &PPORT;
4457 	uint32_t rval = 0;
4458 
4459 	/* If nothing to download then quit now */
4460 	if (!fw_image->awc.version &&
4461 	    !fw_image->dwc.version &&
4462 	    !fw_image->bwc.version) {
4463 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4464 		    "Nothing new to update.  Exiting.");
4465 		return (0);
4466 	}
4467 
4468 	/*
4469 	 * Everything checks out, now to just do it
4470 	 */
4471 	if (offline) {
4472 		if (emlxs_offline(hba) != FC_SUCCESS) {
4473 			return (EMLXS_OFFLINE_FAILED);
4474 		}
4475 
4476 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
4477 			return (EMLXS_OFFLINE_FAILED);
4478 		}
4479 	}
4480 
4481 	if (fw_image->awc.version) {
4482 		rval = emlxs_proc_abs_2mb(hba,
4483 		    (buffer + fw_image->awc.offset),
4484 		    FILE_TYPE_AWC, 0);
4485 
4486 		if (rval) {
4487 			goto SLI_DOWNLOAD_2MB_EXIT;
4488 		}
4489 	}
4490 
4491 	if (fw_image->bwc.version) {
4492 		rval = emlxs_proc_abs_2mb(hba,
4493 		    (buffer + fw_image->bwc.offset),
4494 		    FILE_TYPE_BWC,
4495 		    (fw_image->dwc.version)? ALLext:BWCext);
4496 
4497 		if (rval) {
4498 			goto SLI_DOWNLOAD_2MB_EXIT;
4499 		}
4500 	}
4501 
4502 	if (fw_image->dwc.version) {
4503 		rval = emlxs_proc_rel_2mb(hba, buffer, fw_image);
4504 
4505 		if (rval) {
4506 			goto SLI_DOWNLOAD_2MB_EXIT;
4507 		}
4508 	}
4509 
4510 SLI_DOWNLOAD_2MB_EXIT:
4511 
4512 	if (offline) {
4513 		(void) emlxs_online(hba);
4514 	}
4515 
4516 	return (rval);
4517 
4518 } /* emlxs_start_abs_download_2mb() */
4519 
4520 
4521 /*
4522  *
4523  * FUNCTION NAME: emlxs_proc_abs_2mb
4524  *
4525  * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
4526  *              the port and download the file with sliIssueMbCommand()
4527  *
4528  *
4529  * PARAMETERS:
4530  *
4531  *
4532  * RETURNS:
4533  *
4534  */
4535 static uint32_t
4536 emlxs_proc_abs_2mb(emlxs_hba_t *hba, caddr_t EntireBuffer,
4537     uint32_t FileType, uint32_t extType)
4538 {
4539 	emlxs_port_t *port = &PPORT;
4540 	PAIF_HDR AifHdr;
4541 	caddr_t Buffer = NULL;
4542 	caddr_t DataBuffer = NULL;
4543 	uint32_t *Src;
4544 	uint32_t *Dst;
4545 	MAILBOXQ *mbox;
4546 	MAILBOX *mb;
4547 	uint32_t DlByteCount;
4548 	uint32_t rval = 0;
4549 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
4550 	uint32_t DlToAddr;
4551 	uint32_t DlCount;
4552 	WAKE_UP_PARMS AbsWakeUpParms;
4553 	uint32_t i;
4554 	uint32_t NextAddr;
4555 	uint32_t EraseByteCount;
4556 	uint32_t AreaId;
4557 	uint32_t RspProgress = 0;
4558 	uint32_t ParamsChg;
4559 
4560 	AifHdr = (PAIF_HDR)EntireBuffer;
4561 	DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
4562 	DlToAddr = AifHdr->ImageBase;
4563 
4564 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
4565 	    KM_NOSLEEP)) == NULL) {
4566 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4567 		    "%x: Unable to allocate data buffer.", FileType);
4568 
4569 		return (EMLXS_IMAGE_FAILED);
4570 	}
4571 
4572 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4573 	    KM_NOSLEEP)) == NULL) {
4574 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4575 		    "%x: Unable to allocate mailbox buffer.", FileType);
4576 
4577 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4578 
4579 		return (EMLXS_IMAGE_FAILED);
4580 	}
4581 
4582 	mb = (MAILBOX *)mbox;
4583 
4584 	Buffer = EntireBuffer + sizeof (AIF_HDR);
4585 
4586 	switch (FileType) {
4587 	case FILE_TYPE_AWC:
4588 		ParamsChg = 0;
4589 		break;
4590 
4591 	case FILE_TYPE_BWC:
4592 		rval = emlxs_build_parms_2mb_bwc(hba,
4593 		    AifHdr, extType, &AbsWakeUpParms);
4594 
4595 		if (rval == FALSE) {
4596 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4597 			    "BWC build parms failed.");
4598 
4599 			rval = EMLXS_IMAGE_FAILED;
4600 
4601 			goto EXIT_ABS_DOWNLOAD;
4602 		}
4603 		ParamsChg = 1;
4604 		break;
4605 
4606 	default:
4607 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4608 		    "Invalid file type: %x", FileType);
4609 
4610 		rval = EMLXS_IMAGE_BAD;
4611 
4612 		goto EXIT_ABS_DOWNLOAD;
4613 	}
4614 
4615 	EraseByteCount = AifHdr->Area_Size;
4616 	AreaId = AifHdr->Area_ID;
4617 
4618 	emlxs_format_load_area_cmd(mbox,
4619 	    DlToAddr,
4620 	    EraseByteCount,
4621 	    ERASE_FLASH,
4622 	    0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
4623 
4624 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4625 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4626 		    "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
4627 		    FileType, mb->mbxCommand, mb->mbxStatus);
4628 
4629 		rval = EMLXS_IMAGE_FAILED;
4630 
4631 		goto EXIT_ABS_DOWNLOAD;
4632 	}
4633 
4634 	while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
4635 		NextAddr = mb->un.varLdArea.dl_to_adr;
4636 
4637 		emlxs_format_load_area_cmd(mbox,
4638 		    NextAddr,
4639 		    EraseByteCount,
4640 		    ERASE_FLASH,
4641 		    0,
4642 		    DL_FROM_SLIM_OFFSET,
4643 		    AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
4644 
4645 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4646 		    MBX_SUCCESS) {
4647 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4648 			    "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
4649 			    "status=%x", FileType, mb->mbxCommand,
4650 			    mb->mbxStatus);
4651 
4652 			rval = EMLXS_IMAGE_FAILED;
4653 
4654 			goto EXIT_ABS_DOWNLOAD;
4655 		}
4656 	}
4657 
4658 	while (DlByteCount) {
4659 		if (DlByteCount >= SegSize)
4660 			DlCount = SegSize;
4661 		else
4662 			DlCount = DlByteCount;
4663 
4664 		DlByteCount -= DlCount;
4665 
4666 		Dst = (uint32_t *)DataBuffer;
4667 		Src = (uint32_t *)Buffer;
4668 
4669 		for (i = 0; i < (DlCount / 4); i++) {
4670 			*Dst = *Src;
4671 			Dst++;
4672 			Src++;
4673 		}
4674 
4675 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
4676 		    (volatile uint32_t *)((volatile char *)
4677 		    hba->sli.sli3.slim_addr + sizeof (MAILBOX)),
4678 		    (DlCount / sizeof (uint32_t)));
4679 
4680 		if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
4681 			emlxs_format_load_area_cmd(mbox,
4682 			    DlToAddr,
4683 			    DlCount,
4684 			    PROGRAM_FLASH,
4685 			    (DlByteCount) ? 0 : 1,
4686 			    DL_FROM_SLIM_OFFSET,
4687 			    AreaId,
4688 			    MBX_LOAD_AREA,
4689 			    (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
4690 
4691 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4692 			    MBX_SUCCESS) {
4693 				EMLXS_MSGF(EMLXS_CONTEXT,
4694 				    &emlxs_download_failed_msg,
4695 				    "%x: Could not program 2MB Flash: Mailbox "
4696 				    "cmd=%x status=%x", FileType,
4697 				    mb->mbxCommand, mb->mbxStatus);
4698 
4699 				rval = EMLXS_IMAGE_FAILED;
4700 
4701 				goto EXIT_ABS_DOWNLOAD;
4702 			}
4703 		}
4704 
4705 		RspProgress = mb->un.varLdArea.progress;
4706 
4707 		Buffer += DlCount;
4708 		DlToAddr += DlCount;
4709 	}
4710 
4711 #ifdef FMA_SUPPORT
4712 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
4713 	    != DDI_FM_OK) {
4714 		EMLXS_MSGF(EMLXS_CONTEXT,
4715 		    &emlxs_invalid_access_handle_msg, NULL);
4716 
4717 		rval = EMLXS_IMAGE_FAILED;
4718 
4719 		goto EXIT_ABS_DOWNLOAD;
4720 	}
4721 #endif  /* FMA_SUPPORT */
4722 
4723 	if (RspProgress != RSP_DOWNLOAD_DONE) {
4724 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4725 		    "%x: Failed download response received. %x", FileType,
4726 		    RspProgress);
4727 
4728 		rval = EMLXS_IMAGE_FAILED;
4729 
4730 		goto EXIT_ABS_DOWNLOAD;
4731 	}
4732 
4733 	if (ParamsChg) {
4734 		if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
4735 		    &AbsWakeUpParms)) {
4736 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4737 			    "%x: Unable to update parms.", FileType);
4738 
4739 			rval = EMLXS_IMAGE_FAILED;
4740 		}
4741 	}
4742 
4743 EXIT_ABS_DOWNLOAD:
4744 
4745 	if (DataBuffer) {
4746 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4747 	}
4748 
4749 	if (mbox) {
4750 		kmem_free(mbox, sizeof (MAILBOXQ));
4751 	}
4752 
4753 	return (rval);
4754 
4755 } /* emlxs_proc_abs_2mb() */
4756 
4757 
4758 static void
4759 emlxs_format_load_area_cmd(MAILBOXQ * mbq,
4760     uint32_t Base,
4761     uint32_t DlByteCount,
4762     uint32_t Function,
4763     uint32_t Complete,
4764     uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
4765 {
4766 	MAILBOX *mb = (MAILBOX *)mbq;
4767 
4768 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
4769 
4770 	mb->mbxCommand = MbxCmd;
4771 	mb->mbxOwner = OWN_HOST;
4772 	mb->un.varLdArea.update_flash = 1;
4773 	mb->un.varLdArea.erase_or_prog = Function;
4774 	mb->un.varLdArea.dl_to_adr = Base;
4775 	mb->un.varLdArea.dl_len = DlByteCount;
4776 	mb->un.varLdArea.load_cmplt = Complete;
4777 	mb->un.varLdArea.method = DL_FROM_SLIM;
4778 	mb->un.varLdArea.area_id = AreaId;
4779 	mb->un.varLdArea.step = StepCmd;
4780 	mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
4781 	mbq->mbox_cmpl = NULL;
4782 
4783 } /* emlxs_format_load_area_cmd() */
4784 
4785 
4786 /* ARGSUSED */
4787 static uint32_t
4788 emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
4789     PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
4790 {
4791 	emlxs_port_t *port = &PPORT;
4792 	uint32_t pId[2];
4793 	uint32_t returnStat;
4794 
4795 	/* Read wakeup paramters */
4796 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
4797 	    (uint32_t)CFG_DATA_NO_REGION) {
4798 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4799 		    "Unable to get BWC parameters.");
4800 		return (FALSE);
4801 	}
4802 
4803 	pId[0] = AifHdr->AVersion;
4804 	pId[1] = 0;
4805 
4806 	if (extType == BWCext) {
4807 		AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4808 		AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4809 		AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4810 		AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4811 	}
4812 
4813 	else if (extType == ALLext) {
4814 		if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
4815 			/* case of EROM inactive */
4816 			AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4817 			AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4818 		} else {
4819 			/* case of EROM active */
4820 			if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
4821 				/* same ID */
4822 				AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4823 				AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4824 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4825 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4826 			} else {
4827 				/* different ID */
4828 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4829 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4830 
4831 				returnStat =
4832 				    emlxs_update_exp_rom(hba, AbsWakeUpParms);
4833 
4834 				if (returnStat) {
4835 					AbsWakeUpParms->u0.boot_bios_wd[0] =
4836 					    pId[0];
4837 					AbsWakeUpParms->u0.boot_bios_wd[1] =
4838 					    pId[1];
4839 				}
4840 			}
4841 		}
4842 	}
4843 
4844 	return (TRUE);
4845 
4846 } /* emlxs_build_parms_2mb_bwc() */
4847 
4848 
4849 extern uint32_t
4850 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
4851     uint32_t *MaxIbusSize)
4852 {
4853 	emlxs_port_t *port = &PPORT;
4854 	MAILBOXQ *mbox;
4855 	MAILBOX *mb;
4856 	uint32_t *Uptr;
4857 	uint32_t rval = 0;
4858 
4859 	if (MaxRbusSize) {
4860 		*MaxRbusSize = 0;
4861 	}
4862 
4863 	if (MaxIbusSize) {
4864 		*MaxIbusSize = 0;
4865 	}
4866 
4867 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4868 	    KM_NOSLEEP)) == NULL) {
4869 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4870 		    "Unable to allocate mailbox buffer.");
4871 
4872 		return (1);
4873 	}
4874 
4875 	mb = (MAILBOX *)mbox;
4876 
4877 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
4878 
4879 	if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) !=
4880 	    MBX_SUCCESS) {
4881 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4882 		    "Unable to get SRAM size: Mailbox cmd=%x status=%x",
4883 		    mb->mbxCommand, mb->mbxStatus);
4884 
4885 		rval = 1;
4886 
4887 		goto Exit_Function;
4888 	}
4889 
4890 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4891 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
4892 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
4893 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
4894 	} else {
4895 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
4896 	}
4897 
4898 	if (MaxRbusSize) {
4899 		*MaxRbusSize = Uptr[0];
4900 	}
4901 
4902 	if (MaxIbusSize) {
4903 		*MaxIbusSize = Uptr[1];
4904 	}
4905 
4906 Exit_Function:
4907 
4908 	if (mbox) {
4909 		kmem_free(mbox, sizeof (MAILBOXQ));
4910 	}
4911 
4912 #ifdef FMA_SUPPORT
4913 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4914 		if (emlxs_fm_check_dma_handle(hba,
4915 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
4916 			EMLXS_MSGF(EMLXS_CONTEXT,
4917 			    &emlxs_invalid_dma_handle_msg,
4918 			    "emlxs_get_max_sram: hdl=%p",
4919 			    hba->sli.sli4.dump_region.dma_handle);
4920 			rval = 1;
4921 		}
4922 	}
4923 #endif  /* FMA_SUPPORT */
4924 
4925 	return (rval);
4926 
4927 } /* emlxs_get_max_sram() */
4928 
4929 
4930 static uint32_t
4931 emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
4932 {
4933 	uint8_t *ptr;
4934 	uint8_t ver;
4935 
4936 	ver = version & 0xff;
4937 	ptr = hba->model_info.pt_FF;
4938 
4939 	while (*ptr) {
4940 		if (*ptr++ == ver) {
4941 			return (1);
4942 		}
4943 	}
4944 
4945 	return (0);
4946 
4947 } /* emlxs_kern_check() */
4948 
4949 static uint32_t
4950 emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
4951 {
4952 	uint8_t *ptr;
4953 	uint8_t ver;
4954 
4955 	ver = version & 0xff;
4956 	ptr = hba->model_info.pt_2;
4957 
4958 	while (*ptr) {
4959 		if (*ptr++ == ver) {
4960 			return (1);
4961 		}
4962 	}
4963 
4964 	return (0);
4965 
4966 } /* emlxs_stub_check() */
4967 
4968 static uint32_t
4969 emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
4970 {
4971 	uint8_t *ptr;
4972 	uint8_t ver;
4973 
4974 	ver = version & 0xff;
4975 	ptr = hba->model_info.pt_3;
4976 
4977 	while (*ptr) {
4978 		if (*ptr++ == ver) {
4979 			return (1);
4980 		}
4981 	}
4982 
4983 	return (0);
4984 
4985 } /* emlxs_bios_check() */
4986 
4987 static uint32_t
4988 emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
4989 {
4990 	uint8_t *ptr;
4991 	uint8_t ver;
4992 
4993 	ver = version & 0xff;
4994 	ptr = hba->model_info.pt_6;
4995 
4996 	while (*ptr) {
4997 		if (*ptr++ == ver) {
4998 			return (1);
4999 		}
5000 	}
5001 
5002 	return (0);
5003 
5004 } /* emlxs_sli1_check() */
5005 
5006 static uint32_t
5007 emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version)
5008 {
5009 	uint8_t *ptr;
5010 	uint8_t ver;
5011 
5012 	ver = version & 0xff;
5013 	ptr = hba->model_info.pt_7;
5014 
5015 	while (*ptr) {
5016 		if (*ptr++ == ver) {
5017 			return (1);
5018 		}
5019 	}
5020 
5021 	return (0);
5022 
5023 } /* emlxs_sli2_check() */
5024 
5025 static uint32_t
5026 emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
5027 {
5028 	uint8_t *ptr;
5029 	uint8_t ver;
5030 
5031 	ver = version & 0xff;
5032 	ptr = hba->model_info.pt_B;
5033 
5034 	while (*ptr) {
5035 		if (*ptr++ == ver) {
5036 			return (1);
5037 		}
5038 	}
5039 
5040 	return (0);
5041 
5042 } /* emlxs_sli3_check() */
5043 
5044 
5045 static uint32_t
5046 emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
5047 {
5048 	uint8_t *ptr;
5049 	uint8_t ver;
5050 
5051 	ver = version & 0xff;
5052 	ptr = hba->model_info.pt_E;
5053 
5054 	while (*ptr) {
5055 		if (*ptr++ == ver) {
5056 			return (1);
5057 		}
5058 	}
5059 
5060 	return (0);
5061 
5062 } /* emlxs_sli4_check() */
5063 
5064 
5065 static uint32_t
5066 emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
5067 {
5068 	uint8_t *ptr;
5069 	uint8_t ver;
5070 
5071 	ver = version & 0xff;
5072 	ptr = hba->model_info.pt_A;
5073 
5074 	while (*ptr) {
5075 		if (*ptr++ == ver) {
5076 			return (1);
5077 		}
5078 	}
5079 
5080 	return (0);
5081 
5082 } /* emlxs_sbus_fcode_check() */
5083 
5084 
5085 static uint32_t
5086 emlxs_type_check(uint32_t type)
5087 {
5088 	if (type == 0xff) {
5089 		return (KERNEL_CODE);
5090 	}
5091 
5092 	if (type >= MAX_PROG_TYPES) {
5093 		return (RESERVED_D);
5094 	}
5095 
5096 	return (type);
5097 
5098 } /* emlxs_type_check() */
5099 
5100 
5101 extern int32_t
5102 emlxs_boot_code_disable(emlxs_hba_t *hba)
5103 {
5104 	emlxs_port_t *port = &PPORT;
5105 	PROG_ID Id;
5106 	emlxs_vpd_t *vpd;
5107 
5108 	vpd = &VPD;
5109 
5110 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5111 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5112 		return (EMLXS_OP_NOT_SUP);
5113 	}
5114 
5115 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5116 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5117 		    "emlxs_boot_code_disable: Unable to read wake up parms.");
5118 
5119 		return (FC_FAILURE);
5120 	}
5121 
5122 	/* Check if boot code is already disabled */
5123 	if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
5124 		return (FC_SUCCESS);
5125 	}
5126 
5127 	/* Make sure EROM entry has copy of boot bios entry */
5128 	if (!(hba->model_info.chip &
5129 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
5130 	    (hba->wakeup_parms.u0.boot_bios_wd[0] !=
5131 	    hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
5132 	    (hba->wakeup_parms.u0.boot_bios_wd[1] !=
5133 	    hba->wakeup_parms.u1.EROM_prog_wd[1])) {
5134 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
5135 		    &hba->wakeup_parms.u0.boot_bios_id, 1);
5136 	}
5137 
5138 	/* Update the bios id with a zero id */
5139 	/* Don't load the EROM this time */
5140 	bzero(&Id, sizeof (PROG_ID));
5141 	(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0);
5142 
5143 	/* Now read the parms again to verify */
5144 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5145 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5146 	    vpd->boot_version);
5147 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5148 
5149 	/* Return the result */
5150 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
5151 	    FC_SUCCESS : FC_FAILURE);
5152 
5153 } /* emlxs_boot_code_disable() */
5154 
5155 
5156 extern int32_t
5157 emlxs_boot_code_enable(emlxs_hba_t *hba)
5158 {
5159 	emlxs_port_t *port = &PPORT;
5160 	emlxs_vpd_t *vpd;
5161 	PROG_ID load_list[MAX_LOAD_ENTRY];
5162 	uint32_t i;
5163 	uint32_t count;
5164 
5165 	vpd = &VPD;
5166 
5167 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5168 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5169 		return (FC_SUCCESS);
5170 	}
5171 
5172 	/* Read the wakeup parms */
5173 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5174 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5175 		    "emlxs_boot_code_enable: Unable to read wake up parms.");
5176 
5177 		return (FC_FAILURE);
5178 	}
5179 
5180 	/* Check if boot code is already enabled */
5181 	if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
5182 		return (FC_SUCCESS);
5183 	}
5184 
5185 	if (!(hba->model_info.chip &
5186 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
5187 		if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) {
5188 			return (EMLXS_NO_BOOT_CODE);
5189 		}
5190 
5191 		/* Update the parms with the boot image id */
5192 		/* Don't load the EROM this time */
5193 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
5194 		    &hba->wakeup_parms.u1.EROM_prog_id, 0);
5195 	} else {	/* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
5196 
5197 		count = emlxs_get_load_list(hba, load_list);
5198 
5199 		if (!count) {
5200 			return (FC_FAILURE);
5201 		}
5202 
5203 		/* Scan load list for a boot image */
5204 		for (i = 0; i < count; i++) {
5205 			if (load_list[i].Type == BOOT_BIOS) {
5206 				/* Update the parms with the boot image id */
5207 				/* Don't load the EROM this time */
5208 				(void) emlxs_update_boot_wakeup_parms(hba,
5209 				    &hba->wakeup_parms, &load_list[i], 0);
5210 
5211 				break;
5212 			}
5213 		}
5214 
5215 		if (i == count) {
5216 			return (EMLXS_NO_BOOT_CODE);
5217 		}
5218 	}
5219 
5220 	/* Now read the parms again to verify */
5221 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5222 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5223 	    vpd->boot_version);
5224 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5225 
5226 	/* return the result */
5227 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5228 	    FC_SUCCESS : FC_FAILURE);
5229 
5230 } /* emlxs_boot_code_enable() */
5231 
5232 
5233 
5234 extern int32_t
5235 emlxs_boot_code_state(emlxs_hba_t *hba)
5236 {
5237 	emlxs_port_t *port = &PPORT;
5238 
5239 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5240 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5241 		return (FC_SUCCESS);
5242 	}
5243 
5244 	/* Read the wakeup parms */
5245 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
5246 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5247 		    "emlxs_boot_code_state: Unable to read wake up parms.");
5248 
5249 		return (FC_FAILURE);
5250 	}
5251 
5252 	/* return the result */
5253 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5254 	    FC_SUCCESS : FC_FAILURE);
5255 
5256 } /* emlxs_boot_code_state() */
5257