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