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_BE_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 #ifdef FMA_SUPPORT
2798 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2799 		if (emlxs_fm_check_dma_handle(hba,
2800 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
2801 			EMLXS_MSGF(EMLXS_CONTEXT,
2802 			    &emlxs_invalid_dma_handle_msg,
2803 			    "emlxs_read_wakeup_parms: hdl=%p",
2804 			    hba->sli.sli4.dump_region.dma_handle);
2805 			rval = 1;
2806 		}
2807 	}
2808 #endif  /* FMA_SUPPORT */
2809 
2810 	return (rval);
2811 
2812 } /* emlxs_read_wakeup_parms() */
2813 
2814 
2815 static uint32_t
2816 emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
2817 {
2818 	emlxs_port_t *port = &PPORT;
2819 	LOAD_ENTRY *LoadEntry;
2820 	uint32_t *Uptr;
2821 	uint32_t CurEntryAddr;
2822 	MAILBOXQ *mbox = NULL;
2823 	MAILBOX *mb;
2824 
2825 	bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
2826 
2827 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2828 	    KM_NOSLEEP)) == NULL) {
2829 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2830 		    "Unable to allocate mailbox buffer.");
2831 
2832 		return (1);
2833 	}
2834 
2835 	mb = (MAILBOX *)mbox;
2836 
2837 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
2838 
2839 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2840 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2841 		    "Unable to get load list: Mailbox cmd=%x status=%x",
2842 		    mb->mbxCommand, mb->mbxStatus);
2843 
2844 		goto done;
2845 	}
2846 
2847 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2848 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
2849 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
2850 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
2851 	} else {
2852 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
2853 	}
2854 
2855 	LoadList->head = Uptr[0];
2856 	LoadList->tail = Uptr[1];
2857 
2858 	CurEntryAddr = LoadList->head;
2859 
2860 	while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
2861 	    (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
2862 		LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
2863 		LoadList->entry_cnt++;
2864 
2865 		emlxs_format_dump(hba, mbox,
2866 		    DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
2867 
2868 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2869 		    MBX_SUCCESS) {
2870 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2871 			    "Unable to get load list (%d): Mailbox cmd=%x "
2872 			    "status=%x", LoadList->entry_cnt, mb->mbxCommand,
2873 			    mb->mbxStatus);
2874 
2875 			goto done;
2876 		}
2877 
2878 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2879 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
2880 			    0, hba->sli.sli4.dump_region.size,
2881 			    DDI_DMA_SYNC_FORKERNEL);
2882 			Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
2883 		} else {
2884 			Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
2885 		}
2886 
2887 		LoadEntry->next = Uptr[0];
2888 		LoadEntry->prev = Uptr[1];
2889 		LoadEntry->start_adr = Uptr[2];
2890 		LoadEntry->len = Uptr[3];
2891 		LoadEntry->un.wd[0] = Uptr[4];
2892 		LoadEntry->un.wd[1] = Uptr[5];
2893 
2894 		/* update next current load entry address */
2895 		CurEntryAddr = LoadEntry->next;
2896 
2897 	}	/* end of while (not end of list) */
2898 
2899 done:
2900 
2901 	if (mbox) {
2902 		kmem_free(mbox, sizeof (MAILBOXQ));
2903 	}
2904 
2905 #ifdef FMA_SUPPORT
2906 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2907 		if (emlxs_fm_check_dma_handle(hba,
2908 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
2909 			EMLXS_MSGF(EMLXS_CONTEXT,
2910 			    &emlxs_invalid_dma_handle_msg,
2911 			    "emlxs_read_load_list: hdl=%p",
2912 			    hba->sli.sli4.dump_region.dma_handle);
2913 			return (1);
2914 		}
2915 	}
2916 #endif  /* FMA_SUPPORT */
2917 
2918 	return (0);
2919 
2920 } /* emlxs_read_load_list() */
2921 
2922 
2923 static uint32_t
2924 emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize)
2925 {
2926 	uint32_t Version;
2927 
2928 	if (BufferSize < (SLI_VERSION_LOC + 4))
2929 		return (0xffffffff);
2930 
2931 	Buffer += SLI_VERSION_LOC;
2932 	Version = *((uint32_t *)Buffer);
2933 
2934 	return (Version);
2935 
2936 } /* emlxs_get_abs_image_type() */
2937 
2938 
2939 static uint32_t
2940 emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer,
2941     uint32_t BufferSize, PAIF_HDR AifHeader)
2942 {
2943 	emlxs_port_t *port = &PPORT;
2944 	IMAGE_HDR ImageHdr;
2945 	uint32_t NextImage;
2946 	uint32_t i;
2947 	uint8_t *Sptr;
2948 	uint8_t *Dptr;
2949 	uint32_t HwId = 0xffffffff;
2950 
2951 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
2952 
2953 	while (BufferSize > NextImage) {
2954 		Sptr = (uint8_t *)&Buffer[NextImage];
2955 		Dptr = (uint8_t *)&ImageHdr;
2956 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
2957 			Dptr[i] = Sptr[i];
2958 		}
2959 
2960 		if (ImageHdr.BlockSize == 0xffffffff)
2961 			break;
2962 
2963 		switch (ImageHdr.Id.Type) {
2964 		case 6:
2965 		case 7:
2966 			if (HwId == 0xffffffff) {
2967 				HwId = ImageHdr.Id.Id;
2968 			}
2969 
2970 			if (HwId != ImageHdr.Id.Id) {
2971 				EMLXS_MSGF(EMLXS_CONTEXT,
2972 				    &emlxs_image_bad_msg,
2973 				    "Invalid hardware id. %x %x", HwId,
2974 				    ImageHdr.Id.Id);
2975 			}
2976 			break;
2977 		}
2978 
2979 		NextImage += ImageHdr.BlockSize;
2980 	}
2981 
2982 	return (HwId);
2983 
2984 } /* emlxs_get_dwc_image_type() */
2985 
2986 
2987 static int
2988 emlxs_build_parms(caddr_t Buffer,
2989     PWAKE_UP_PARMS AbsWakeUpParms,
2990     uint32_t BufferSize, PAIF_HDR AifHeader, int32_t DwcFile)
2991 {
2992 	IMAGE_HDR ImageHdr;
2993 	uint32_t NextImage;
2994 	uint32_t i;
2995 	int32_t ChangeParams = FALSE;
2996 	caddr_t Sptr;
2997 	caddr_t Dptr;
2998 
2999 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
3000 
3001 	if (!DwcFile && ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
3002 		return (FALSE);
3003 	}
3004 
3005 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
3006 
3007 	while (BufferSize > NextImage) {
3008 		Sptr = &Buffer[NextImage];
3009 		Dptr = (caddr_t)&ImageHdr;
3010 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
3011 			Dptr[i] = Sptr[i];
3012 		}
3013 
3014 		if (ImageHdr.BlockSize == 0xffffffff)
3015 			break;
3016 
3017 		switch (ImageHdr.Id.Type) {
3018 		case TEST_PROGRAM:
3019 			break;
3020 		case FUNC_FIRMWARE:
3021 			AbsWakeUpParms->prog_id = ImageHdr.Id;
3022 			ChangeParams = TRUE;
3023 			break;
3024 		case BOOT_BIOS:
3025 			AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
3026 			ChangeParams = TRUE;
3027 			break;
3028 		case SLI1_OVERLAY:
3029 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
3030 			ChangeParams = TRUE;
3031 			break;
3032 		case SLI2_OVERLAY:
3033 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
3034 			ChangeParams = TRUE;
3035 			break;
3036 		case SLI3_OVERLAY:
3037 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
3038 			ChangeParams = TRUE;
3039 			break;
3040 		case SLI4_OVERLAY:
3041 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
3042 			ChangeParams = TRUE;
3043 			break;
3044 		default:
3045 			break;
3046 		}
3047 
3048 		NextImage += ImageHdr.BlockSize;
3049 	}
3050 
3051 	return (ChangeParams);
3052 
3053 } /* emlxs_build_parms() */
3054 
3055 
3056 static uint32_t
3057 emlxs_update_wakeup_parms(emlxs_hba_t *hba,
3058     PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
3059 {
3060 	emlxs_port_t *port = &PPORT;
3061 	MAILBOX *mb;
3062 	MAILBOXQ *mbox;
3063 	uint32_t rval = 0;
3064 
3065 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3066 	    KM_NOSLEEP)) == NULL) {
3067 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3068 		    "Unable to allocate mailbox buffer.");
3069 
3070 		return (1);
3071 	}
3072 
3073 	mb = (MAILBOX *)mbox;
3074 
3075 	WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
3076 	WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
3077 	WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
3078 	WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
3079 	WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
3080 	WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
3081 
3082 	emlxs_format_update_parms(mbox, WakeUpParms);
3083 
3084 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3085 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3086 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
3087 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
3088 
3089 		rval = 1;
3090 	}
3091 
3092 	if (mbox) {
3093 		kmem_free(mbox, sizeof (MAILBOXQ));
3094 	}
3095 
3096 	return (rval);
3097 
3098 } /* emlxs_update_wakeup_parms() */
3099 
3100 
3101 static uint32_t
3102 emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
3103     uint32_t type, char *file_type)
3104 {
3105 	emlxs_port_t *port = &PPORT;
3106 
3107 	/* Create the version label */
3108 	emlxs_decode_version(file->version, file->label);
3109 
3110 	/* Process the DWC type */
3111 	switch (type) {
3112 	case TEST_PROGRAM:
3113 
3114 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3115 		    "%s: TEST: offset=%08x  version=%08x, %s", file_type,
3116 		    file->offset, file->version, file->label);
3117 
3118 		break;
3119 
3120 	case BOOT_BIOS:
3121 
3122 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3123 		    "%s: BOOT: offset=%08x  version=%08x, %s", file_type,
3124 		    file->offset, file->version, file->label);
3125 
3126 		if (!emlxs_bios_check(hba, id)) {
3127 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3128 			    "BOOT Check: Image not compatible with %s. id=%02x",
3129 			    hba->model_info.model, id);
3130 
3131 			return (EMLXS_IMAGE_INCOMPATIBLE);
3132 		}
3133 
3134 		break;
3135 
3136 	case FUNC_FIRMWARE:	/* Stub */
3137 
3138 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3139 		    "%s: STUB: offset=%08x  version=%08x, %s", file_type,
3140 		    file->offset, file->version, file->label);
3141 
3142 		if (!emlxs_stub_check(hba, id)) {
3143 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3144 			    "STUB Check: Image not compatible with %s. id=%02x",
3145 			    hba->model_info.model, id);
3146 
3147 			return (EMLXS_IMAGE_INCOMPATIBLE);
3148 		}
3149 
3150 		break;
3151 
3152 	case SLI1_OVERLAY:
3153 
3154 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3155 		    "%s: SLI1: offset=%08x  version=%08x, %s", file_type,
3156 		    file->offset, file->version, file->label);
3157 
3158 		if (!emlxs_sli1_check(hba, id)) {
3159 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3160 			    "SLI1 Check: Image not compatible with %s. id=%02x",
3161 			    hba->model_info.model, id);
3162 
3163 			return (EMLXS_IMAGE_INCOMPATIBLE);
3164 		}
3165 
3166 		break;
3167 
3168 	case SLI2_OVERLAY:
3169 
3170 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3171 		    "%s: SLI2: offset=%08x  version=%08x, %s", file_type,
3172 		    file->offset, file->version, file->label);
3173 
3174 		if (!emlxs_sli2_check(hba, id)) {
3175 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3176 			    "SLI2 Check: Image not compatible with %s. id=%02x",
3177 			    hba->model_info.model, id);
3178 
3179 			return (EMLXS_IMAGE_INCOMPATIBLE);
3180 		}
3181 
3182 		break;
3183 
3184 	case SLI3_OVERLAY:
3185 
3186 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3187 		    "%s: SLI3: offset=%08x  version=%08x, %s", file_type,
3188 		    file->offset, file->version, file->label);
3189 
3190 		if (!emlxs_sli3_check(hba, id)) {
3191 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3192 			    "SLI3 Check: Image not compatible with %s. id=%02x",
3193 			    hba->model_info.model, id);
3194 
3195 			return (EMLXS_IMAGE_INCOMPATIBLE);
3196 		}
3197 
3198 		break;
3199 
3200 	case SLI4_OVERLAY:
3201 
3202 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3203 		    "%s: SLI4: offset=%08x  version=%08x, %s", file_type,
3204 		    file->offset, file->version, file->label);
3205 
3206 		if (!emlxs_sli4_check(hba, id)) {
3207 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3208 			    "SLI4 Check: Image not compatible with %s. id=%02x",
3209 			    hba->model_info.model, id);
3210 
3211 			return (EMLXS_IMAGE_INCOMPATIBLE);
3212 		}
3213 
3214 		break;
3215 
3216 	case SBUS_FCODE:
3217 
3218 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3219 		    "%s: SBUS FCODE: offset=%08x  version=%08x, %s",
3220 		    file_type, file->offset, file->version, file->label);
3221 
3222 		if (!emlxs_sbus_fcode_check(hba, id)) {
3223 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3224 			    "SBUS FCODE Check: Image not compatible with %s. "
3225 			    "id=%02x", hba->model_info.model, id);
3226 
3227 			return (EMLXS_IMAGE_INCOMPATIBLE);
3228 		}
3229 
3230 		break;
3231 
3232 	case KERNEL_CODE:
3233 
3234 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3235 		    "%s: KERN: offset=%08x  version=%08x, %s", file_type,
3236 		    file->offset, file->version, file->label);
3237 
3238 		if (!emlxs_kern_check(hba, id)) {
3239 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3240 			    "KERN Check: Image not compatible with %s. id=%02x",
3241 			    hba->model_info.model, id);
3242 
3243 			return (EMLXS_IMAGE_INCOMPATIBLE);
3244 		}
3245 
3246 		break;
3247 
3248 	default:
3249 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3250 		    "%s: Image type not supported. type=%x", file_type, type);
3251 
3252 		return (EMLXS_IMAGE_BAD);
3253 	}
3254 
3255 	return (0);
3256 
3257 } /* emlxs_validate_version() */
3258 
3259 
3260 static uint32_t
3261 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
3262     emlxs_fw_image_t *image)
3263 {
3264 	emlxs_port_t *port = &PPORT;
3265 	uint32_t ImageType;
3266 	AIF_HDR AifHdr;
3267 	IMAGE_HDR ImageHdr;
3268 	uint32_t NextImage;
3269 	uint32_t FileType;
3270 	uint32_t FileLen = 0;
3271 	uint32_t TotalLen = 0;
3272 	uint32_t *CkSumEnd;
3273 	uint32_t id;
3274 	uint32_t type;
3275 	uint32_t ver;
3276 	uint32_t ImageLength;
3277 	uint32_t BufferSize;
3278 	uint32_t rval = 0;
3279 	caddr_t bptr;
3280 	emlxs_vpd_t *vpd;
3281 
3282 	vpd = &VPD;
3283 
3284 	/* Get image type */
3285 	ImageType = *((uint32_t *)Buffer);
3286 
3287 	/* Pegasus and beyond adapters */
3288 	if ((ImageType == NOP_IMAGE_TYPE) &&
3289 	    !(hba->model_info.chip &
3290 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
3291 		bptr = Buffer;
3292 		TotalLen = sizeof (uint32_t);
3293 
3294 		while (TotalLen < Size) {
3295 			if (Size < sizeof (AIF_HDR)) {
3296 				EMLXS_MSGF(EMLXS_CONTEXT,
3297 				    &emlxs_image_bad_msg,
3298 				    "Invalid image header length: 0x%x < 0x%x",
3299 				    Size, sizeof (AIF_HDR));
3300 
3301 				return (EMLXS_IMAGE_BAD);
3302 			}
3303 
3304 			bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
3305 			emlxs_disp_aif_header(hba, &AifHdr);
3306 
3307 			ImageLength = AifHdr.RoSize;
3308 
3309 			/* Validate checksum */
3310 			CkSumEnd =
3311 			    (uint32_t *)(bptr + ImageLength +
3312 			    sizeof (AIF_HDR));
3313 			if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
3314 				EMLXS_MSGF(EMLXS_CONTEXT,
3315 				    &emlxs_image_bad_msg,
3316 				    "Invalid checksum found.");
3317 
3318 				return (EMLXS_IMAGE_BAD);
3319 			}
3320 
3321 			FileType = AifHdr.ZinitBr;
3322 			switch (FileType) {
3323 			case FILE_TYPE_AWC:
3324 				image->awc.offset =
3325 				    (uint32_t)((uintptr_t)bptr -
3326 				    (uintptr_t)Buffer);
3327 				image->awc.version = AifHdr.AVersion;
3328 				image->awc.revcomp = 0;
3329 
3330 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3331 				type = emlxs_type_check(
3332 				    (AifHdr.AVersion & 0xff000000) >> 24);
3333 
3334 				/* Validate the file version */
3335 				if ((rval = emlxs_validate_version(hba,
3336 				    &image->awc, id, type, "AWC file"))) {
3337 					return (rval);
3338 				}
3339 
3340 				break;
3341 
3342 			case FILE_TYPE_BWC:
3343 				image->bwc.offset =
3344 				    (uint32_t)((uintptr_t)bptr -
3345 				    (uintptr_t)Buffer);
3346 				image->bwc.version = AifHdr.AVersion;
3347 				image->bwc.revcomp = 0;
3348 
3349 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3350 				type = emlxs_type_check(
3351 				    (AifHdr.AVersion & 0xff000000) >> 24);
3352 
3353 				/* Validate the file version */
3354 				if ((rval = emlxs_validate_version(hba,
3355 				    &image->bwc, id, type, "BWC file"))) {
3356 					return (rval);
3357 				}
3358 
3359 				break;
3360 
3361 			case FILE_TYPE_DWC:
3362 				image->dwc.offset =
3363 				    (uint32_t)((uintptr_t)bptr -
3364 				    (uintptr_t)Buffer);
3365 				image->dwc.version = AifHdr.AVersion;
3366 				image->dwc.revcomp = 0;
3367 
3368 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3369 				type = emlxs_type_check(
3370 				    (AifHdr.AVersion & 0xff000000) >> 24);
3371 
3372 				/* Validate the file version */
3373 				if ((rval = emlxs_validate_version(hba,
3374 				    &image->dwc, id, type, "DWC file"))) {
3375 					return (rval);
3376 				}
3377 
3378 				/* Scan for program types */
3379 				NextImage = sizeof (AIF_HDR) + 4;
3380 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
3381 
3382 				while (BufferSize > NextImage) {
3383 					bcopy(&bptr[NextImage], &ImageHdr,
3384 					    sizeof (IMAGE_HDR));
3385 					emlxs_dump_image_header(hba,
3386 					    &ImageHdr);
3387 
3388 					/* Validate block size */
3389 					if (ImageHdr.BlockSize == 0xffffffff) {
3390 						break;
3391 					}
3392 
3393 					type = emlxs_type_check(
3394 					    ImageHdr.Id.Type);
3395 
3396 					/* Calculate the program offset */
3397 					image->prog[type].offset =
3398 					    (uint32_t)((uintptr_t)
3399 					    &bptr[NextImage] -
3400 					    (uintptr_t)Buffer);
3401 
3402 					/* Acquire the versions */
3403 					image->prog[type].version =
3404 					    (ImageHdr.Id.Type << 24) |
3405 					    (ImageHdr.Id.Id << 16) |
3406 					    (ImageHdr.Id.Ver << 8) |
3407 					    ImageHdr.Id.Rev;
3408 
3409 					image->prog[type].revcomp =
3410 					    ImageHdr.Id.un.revcomp;
3411 
3412 					/* Validate the file version */
3413 					if ((rval = emlxs_validate_version(hba,
3414 					    &image->prog[type], ImageHdr.Id.Id,
3415 					    type, "DWC prog"))) {
3416 						return (rval);
3417 					}
3418 
3419 					NextImage += ImageHdr.BlockSize;
3420 
3421 				}	/* while () */
3422 
3423 				break;
3424 			}
3425 
3426 			FileLen =
3427 			    sizeof (AIF_HDR) + ImageLength +
3428 			    sizeof (uint32_t);
3429 			TotalLen += FileLen;
3430 			bptr += FileLen;
3431 		}
3432 	}
3433 
3434 	/* Pre-pegasus adapters */
3435 
3436 	else if (ImageType == NOP_IMAGE_TYPE) {
3437 		if (Size < sizeof (AIF_HDR)) {
3438 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3439 			    "Invalid image header length: 0x%x < 0x%x", Size,
3440 			    sizeof (AIF_HDR));
3441 
3442 			return (EMLXS_IMAGE_BAD);
3443 		}
3444 
3445 		bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
3446 		emlxs_disp_aif_header(hba, &AifHdr);
3447 
3448 		ImageLength = AifHdr.RoSize + AifHdr.RwSize;
3449 
3450 		if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
3451 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3452 			    "Image length incorrect: 0x%x != 0x%x", Size,
3453 			    sizeof (AIF_HDR) + ImageLength +
3454 			    sizeof (uint32_t));
3455 
3456 			return (EMLXS_IMAGE_BAD);
3457 		}
3458 
3459 		if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
3460 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3461 			    "Invalid imageBase value %x != 0x20000",
3462 			    AifHdr.ImageBase);
3463 
3464 			return (EMLXS_IMAGE_BAD);
3465 		}
3466 
3467 		CkSumEnd =
3468 		    (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
3469 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
3470 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3471 			    "Invalid checksum found.");
3472 
3473 			return (EMLXS_IMAGE_BAD);
3474 		}
3475 
3476 		image->dwc.offset = 0;
3477 		image->dwc.version = AifHdr.AVersion;
3478 		image->dwc.revcomp = 0;
3479 
3480 		id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3481 		type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
3482 
3483 		/* Validate the file version */
3484 		if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
3485 		    "DWC file"))) {
3486 			return (rval);
3487 		}
3488 
3489 		NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
3490 		while (Size > NextImage) {
3491 			bcopy(&Buffer[NextImage], &ImageHdr,
3492 			    sizeof (IMAGE_HDR));
3493 			emlxs_dump_image_header(hba, &ImageHdr);
3494 
3495 			/* Validate block size */
3496 			if (ImageHdr.BlockSize == 0xffffffff) {
3497 				break;
3498 			}
3499 
3500 			type = emlxs_type_check(ImageHdr.Id.Type);
3501 
3502 			/* Calculate the program offset */
3503 			image->prog[type].offset = NextImage;
3504 
3505 			/* Acquire the versions */
3506 			image->prog[type].version =
3507 			    (ImageHdr.Id.Type << 24) |
3508 			    (ImageHdr.Id.Id << 16) |
3509 			    (ImageHdr.Id.Ver << 8) |
3510 			    ImageHdr.Id.Rev;
3511 
3512 			image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
3513 
3514 			/* Validate the file version */
3515 			if ((rval = emlxs_validate_version(hba,
3516 			    &image->prog[type], ImageHdr.Id.Id, type,
3517 			    "DWC prog"))) {
3518 				return (rval);
3519 			}
3520 
3521 			NextImage += ImageHdr.BlockSize;
3522 		}
3523 	} else {
3524 		/* Precheck image size */
3525 		if (Size < sizeof (IMAGE_HDR)) {
3526 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3527 			    "Invalid image header length: 0x%x < 0x%x", Size,
3528 			    sizeof (IMAGE_HDR));
3529 
3530 			return (EMLXS_IMAGE_BAD);
3531 		}
3532 
3533 		bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
3534 		emlxs_dump_image_header(hba, &ImageHdr);
3535 
3536 		/* Validate block size */
3537 		if (ImageHdr.BlockSize == 0xffffffff) {
3538 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3539 			    "Invalid block size.");
3540 
3541 			return (EMLXS_IMAGE_BAD);
3542 		}
3543 
3544 		ImageLength = ImageHdr.BlockSize;
3545 
3546 		/* Validate image length */
3547 		if (Size != ImageLength) {
3548 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3549 			    "Invalid image length: 0x%x != 0x%x", Size,
3550 			    ImageLength);
3551 
3552 			return (EMLXS_IMAGE_BAD);
3553 		}
3554 
3555 		/* Validate Checksum */
3556 		CkSumEnd =
3557 		    (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
3558 		    1;
3559 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
3560 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3561 			    "Invalid checksum found.");
3562 
3563 			return (EMLXS_IMAGE_BAD);
3564 		}
3565 
3566 		type = emlxs_type_check(ImageHdr.Id.Type);
3567 
3568 		/* Calculate the program offset */
3569 		image->prog[type].offset = 0;
3570 
3571 		/* Acquire the versions */
3572 		image->prog[type].version =
3573 		    (ImageHdr.Id.Type << 24) | (ImageHdr.Id.
3574 		    Id << 16) | (ImageHdr.Id.Ver << 8) | ImageHdr.Id.Rev;
3575 
3576 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
3577 
3578 		/* Validate the file version */
3579 		if ((rval = emlxs_validate_version(hba, &image->prog[type],
3580 		    ImageHdr.Id.Id, type, "DWC file"))) {
3581 			return (rval);
3582 		}
3583 	}
3584 
3585 	/*
3586 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
3587 	 * image file is greater than version 3.8
3588 	 */
3589 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
3590 		if (image->prog[SLI2_OVERLAY].version != 0) {
3591 			ver = (image->prog[SLI2_OVERLAY].version &
3592 			    0x0000ff00) >> 8;
3593 
3594 			if ((((ver & 0xf0) == 0x30) &&
3595 			    ((ver & 0x0f) >= 0x08)) ||
3596 			    ((ver & 0xf0) > 0x30)) {
3597 				EMLXS_MSGF(EMLXS_CONTEXT,
3598 				    &emlxs_image_incompat_msg,
3599 				    "ASIC Check: Image requires DragonFly "
3600 				    "V2 ASIC");
3601 
3602 				return (EMLXS_IMAGE_INCOMPATIBLE);
3603 			}
3604 		}
3605 	}
3606 
3607 	return (0);
3608 
3609 } /* emlxs_validate_image() */
3610 
3611 
3612 static uint32_t
3613 emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
3614 {
3615 	emlxs_port_t *port = &PPORT;
3616 	MAILBOXQ *mbox;
3617 	MAILBOX *mb;
3618 	uint32_t next_address;
3619 	uint32_t rval = 0;
3620 
3621 	if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
3622 		return (1);
3623 	}
3624 
3625 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3626 	    KM_NOSLEEP)) == NULL) {
3627 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3628 		    "Unable to allocate mailbox buffer.");
3629 
3630 		return (1);
3631 	}
3632 
3633 	bzero(mbox, sizeof (MAILBOXQ));
3634 
3635 	mb = (MAILBOX *)mbox;
3636 	mb->mbxCommand = MBX_LOAD_EXP_ROM;
3637 	mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
3638 	mb->un.varLdExpRom.progress = 0;
3639 	mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
3640 	mbox->mbox_cmpl = NULL;
3641 
3642 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3643 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3644 		    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
3645 		    mb->mbxCommand, mb->mbxStatus);
3646 
3647 		rval = 1;
3648 
3649 		goto SLI_DOWNLOAD_EXIT;
3650 	}
3651 
3652 	if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
3653 		(void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
3654 
3655 		rval = 1;
3656 		goto SLI_DOWNLOAD_EXIT;
3657 	}
3658 
3659 	if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
3660 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3661 		    "Invalid exp ROM progress. progress=%x",
3662 		    mb->un.varLdExpRom.progress);
3663 
3664 		rval = 1;
3665 
3666 		goto SLI_DOWNLOAD_EXIT;
3667 	}
3668 
3669 	/*
3670 	 * continue Erase
3671 	 */
3672 	while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
3673 
3674 		next_address = mb->un.varLdExpRom.dl_to_adr;
3675 
3676 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3677 
3678 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
3679 		mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
3680 		mb->un.varLdExpRom.dl_to_adr = next_address;
3681 		mb->un.varLdExpRom.progress = 0;
3682 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
3683 		mbox->mbox_cmpl = NULL;
3684 
3685 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3686 		    MBX_SUCCESS) {
3687 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3688 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
3689 			    mb->mbxCommand, mb->mbxStatus);
3690 
3691 			rval = 1;
3692 			goto SLI_DOWNLOAD_EXIT;
3693 		}
3694 
3695 	}
3696 
3697 	while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
3698 		next_address = mb->un.varLdExpRom.dl_to_adr;
3699 
3700 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3701 
3702 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
3703 		mb->un.varLdExpRom.step = EROM_CMD_COPY;
3704 		mb->un.varLdExpRom.dl_to_adr = next_address;
3705 		mb->un.varLdExpRom.progress = 0;
3706 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
3707 		mbox->mbox_cmpl = NULL;
3708 
3709 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3710 		    MBX_SUCCESS) {
3711 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3712 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
3713 			    mb->mbxCommand, mb->mbxStatus);
3714 
3715 			rval = 1;
3716 
3717 			goto SLI_DOWNLOAD_EXIT;
3718 		}
3719 	}
3720 
3721 	rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
3722 
3723 SLI_DOWNLOAD_EXIT:
3724 
3725 	if (mbox) {
3726 		kmem_free(mbox, sizeof (MAILBOXQ));
3727 	}
3728 
3729 	return (rval);
3730 
3731 } /* emlxs_update_exp_rom() */
3732 
3733 
3734 /*
3735  *
3736  * FUNCTION NAME: emlxs_start_abs_download_2mb
3737  *
3738  * DESCRIPTION: Perform absolute download for 2 MB flash.  A incoming
3739  *              buffer may consist of more than 1 file.  This function
3740  *              will parse the buffer to find all the files.
3741  *
3742  *
3743  * PARAMETERS:
3744  *
3745  *
3746  * RETURNS:
3747  *
3748  */
3749 /* ARGSUSED */
3750 static uint32_t
3751 emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
3752     uint32_t offline, emlxs_fw_image_t *fw_image)
3753 {
3754 	emlxs_port_t *port = &PPORT;
3755 	caddr_t AwcBuffer = NULL;
3756 	caddr_t BwcBuffer = NULL;
3757 	caddr_t DwcBuffer = NULL;
3758 	AIF_HDR *AwcAifHdr;
3759 	AIF_HDR *BwcAifHdr;
3760 	AIF_HDR *DwcAifHdr;
3761 	uint32_t BWCflag;
3762 	emlxs_vpd_t *vpd;
3763 	uint32_t i;
3764 	uint32_t count;
3765 	uint32_t extType = 0;
3766 	uint32_t rval = 0;
3767 
3768 	vpd = &VPD;
3769 
3770 	/* Check for AWC file */
3771 	if (fw_image->awc.version) {
3772 		AwcBuffer = buffer + fw_image->awc.offset;
3773 		AwcAifHdr = (AIF_HDR *)AwcBuffer;
3774 	}
3775 
3776 	/* Check for BWC file */
3777 	if (fw_image->bwc.version) {
3778 		extType = BWCext;
3779 		BwcBuffer = buffer + fw_image->bwc.offset;
3780 		BwcAifHdr = (AIF_HDR *)BwcBuffer;
3781 	}
3782 
3783 	/* Check for DWC file */
3784 	if (fw_image->dwc.version) {
3785 		extType = DWCext;
3786 		DwcBuffer = buffer + fw_image->dwc.offset;
3787 		DwcAifHdr = (AIF_HDR *)DwcBuffer;
3788 	}
3789 
3790 	/* Check for program files */
3791 	count = 0;
3792 	for (i = 0; i < MAX_PROG_TYPES; i++) {
3793 		if (fw_image->prog[i].version) {
3794 			count++;
3795 		}
3796 	}
3797 
3798 	if (count > 1) {
3799 		extType = ALLext;
3800 
3801 		if (fw_image->bwc.version) {
3802 			BWCflag = ALL_WITH_BWC;
3803 		} else {
3804 			BWCflag = ALL_WITHOUT_BWC;
3805 		}
3806 	} else {
3807 		BWCflag = NO_ALL;
3808 	}
3809 
3810 	/* If nothing to download then quit now */
3811 	if (!AwcBuffer && !DwcBuffer && !BwcBuffer) {
3812 		return (0);
3813 	}
3814 
3815 	/*
3816 	 * Everything checks out, now to just do it
3817 	 */
3818 	if (offline) {
3819 		if (emlxs_offline(hba) != FC_SUCCESS) {
3820 			return (EMLXS_OFFLINE_FAILED);
3821 		}
3822 
3823 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
3824 			return (EMLXS_OFFLINE_FAILED);
3825 		}
3826 	}
3827 
3828 	if (AwcBuffer) {
3829 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3830 		    "AWC file: KERN: old=%s  new=%s ", vpd->postKernName,
3831 		    fw_image->awc.label);
3832 
3833 		rval = emlxs_proc_abs_2mb(hba,
3834 		    AwcAifHdr, AwcBuffer, FILE_TYPE_AWC, BWCflag, extType);
3835 
3836 		if (rval) {
3837 			goto SLI_DOWNLOAD_2MB_EXIT;
3838 		}
3839 	}
3840 
3841 	if (DwcBuffer) {
3842 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3843 		    "DWC file: TEST:             new=%s ",
3844 		    fw_image->prog[TEST_PROGRAM].label);
3845 
3846 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3847 		    "DWC file: STUB: old=%s  new=%s ", vpd->opFwName,
3848 		    fw_image->prog[FUNC_FIRMWARE].label);
3849 
3850 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3851 		    "DWC file: SLI1: old=%s  new=%s ", vpd->sli1FwName,
3852 		    fw_image->prog[SLI1_OVERLAY].label);
3853 
3854 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3855 		    "DWC file: SLI2: old=%s  new=%s ", vpd->sli2FwName,
3856 		    fw_image->prog[SLI2_OVERLAY].label);
3857 
3858 		if (vpd->sli3FwRev || fw_image->prog[SLI3_OVERLAY].version) {
3859 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3860 			    "DWC file: SLI3: old=%s  new=%s ",
3861 			    vpd->sli3FwName,
3862 			    fw_image->prog[SLI3_OVERLAY].label);
3863 		}
3864 
3865 		if (vpd->sli4FwRev || fw_image->prog[SLI4_OVERLAY].version) {
3866 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3867 			    "DWC file: SLI4: old=%s  new=%s ",
3868 			    vpd->sli4FwName,
3869 			    fw_image->prog[SLI4_OVERLAY].label);
3870 		}
3871 
3872 		rval = emlxs_proc_abs_2mb(hba,
3873 		    DwcAifHdr, DwcBuffer, FILE_TYPE_DWC, BWCflag, extType);
3874 
3875 		if (rval) {
3876 			goto SLI_DOWNLOAD_2MB_EXIT;
3877 		}
3878 	}
3879 
3880 	if (BwcBuffer) {
3881 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3882 		    "BWC file: BOOT: old=%s  new=%s ", vpd->fcode_version,
3883 		    fw_image->bwc.label);
3884 
3885 		rval = emlxs_proc_abs_2mb(hba,
3886 		    BwcAifHdr, BwcBuffer, FILE_TYPE_BWC, BWCflag, extType);
3887 	}
3888 
3889 SLI_DOWNLOAD_2MB_EXIT:
3890 
3891 	if (offline) {
3892 		(void) emlxs_online(hba);
3893 	}
3894 
3895 	return (rval);
3896 
3897 } /* emlxs_start_abs_download_2mb() */
3898 
3899 
3900 /*
3901  *
3902  * FUNCTION NAME: emlxs_proc_abs_2mb
3903  *
3904  * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
3905  *              the port and download the file with sliIssueMbCommand()
3906  *
3907  *
3908  * PARAMETERS:
3909  *
3910  *
3911  * RETURNS:
3912  *
3913  */
3914 static uint32_t
3915 emlxs_proc_abs_2mb(emlxs_hba_t *hba,
3916     PAIF_HDR AifHdr,
3917     caddr_t EntireBuffer,
3918     uint32_t FileType, uint32_t BWCflag, uint32_t extType)
3919 {
3920 	emlxs_port_t *port = &PPORT;
3921 	caddr_t Buffer = NULL;
3922 	caddr_t DataBuffer = NULL;
3923 	uint32_t *Src;
3924 	uint32_t *Dst;
3925 	MAILBOXQ *mbox;
3926 	MAILBOX *mb;
3927 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
3928 	uint32_t rval = 0;
3929 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
3930 	uint32_t DlToAddr = AifHdr->ImageBase;
3931 	uint32_t DlCount;
3932 	WAKE_UP_PARMS AbsWakeUpParms;
3933 	uint32_t i;
3934 	uint32_t NextAddr;
3935 	uint32_t EraseByteCount;
3936 	uint32_t AreaId;
3937 	uint32_t RspProgress = 0;
3938 	uint32_t numBootImage = 0;
3939 	uint32_t ParamsChg = 0;
3940 	uint32_t BufferSize;
3941 
3942 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
3943 	    KM_NOSLEEP)) == NULL) {
3944 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3945 		    "%x: Unable to allocate data buffer.", FileType);
3946 
3947 		return (EMLXS_IMAGE_FAILED);
3948 	}
3949 
3950 	bzero(DataBuffer, sizeof (DL_SLIM_SEG_BYTE_COUNT));
3951 
3952 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3953 	    KM_NOSLEEP)) == NULL) {
3954 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3955 		    "%x: Unable to allocate mailbox buffer.", FileType);
3956 
3957 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
3958 
3959 		return (EMLXS_IMAGE_FAILED);
3960 	}
3961 
3962 	mb = (MAILBOX *)mbox;
3963 
3964 	BufferSize = DlByteCount + sizeof (AIF_HDR) + sizeof (uint32_t);
3965 	Buffer = EntireBuffer + sizeof (AIF_HDR);
3966 
3967 	switch (FileType) {
3968 	case FILE_TYPE_AWC:
3969 		break;
3970 
3971 	case FILE_TYPE_BWC:
3972 		ParamsChg = emlxs_build_parms_2mb_bwc(hba,
3973 		    AifHdr, extType, &AbsWakeUpParms);
3974 
3975 		if (ParamsChg == FALSE) {
3976 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3977 			    "BWC build parms failed.");
3978 
3979 			rval = EMLXS_IMAGE_FAILED;
3980 
3981 			goto EXIT_ABS_DOWNLOAD;
3982 		}
3983 		break;
3984 
3985 	case FILE_TYPE_DWC:
3986 		ParamsChg = emlxs_build_parms_2mb_dwc(hba,
3987 		    Buffer,
3988 		    BufferSize,
3989 		    AifHdr, &AbsWakeUpParms, BWCflag, extType, &numBootImage);
3990 
3991 		if (ParamsChg == FALSE) {
3992 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3993 			    "DWC build parms failed.");
3994 
3995 			rval = EMLXS_IMAGE_FAILED;
3996 
3997 			goto EXIT_ABS_DOWNLOAD;
3998 		}
3999 		break;
4000 
4001 	default:
4002 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4003 		    "Invalid file type: %x", FileType);
4004 
4005 		rval = EMLXS_IMAGE_BAD;
4006 
4007 		goto EXIT_ABS_DOWNLOAD;
4008 
4009 	}
4010 
4011 	EraseByteCount = AifHdr->Area_Size;
4012 	AreaId = AifHdr->Area_ID;
4013 
4014 	emlxs_format_load_area_cmd(mbox,
4015 	    DlToAddr,
4016 	    EraseByteCount,
4017 	    ERASE_FLASH,
4018 	    0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
4019 
4020 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4021 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4022 		    "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
4023 		    FileType, mb->mbxCommand, mb->mbxStatus);
4024 
4025 		rval = EMLXS_IMAGE_FAILED;
4026 
4027 		goto EXIT_ABS_DOWNLOAD;
4028 	}
4029 
4030 	while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
4031 		NextAddr = mb->un.varLdArea.dl_to_adr;
4032 
4033 		emlxs_format_load_area_cmd(mbox,
4034 		    NextAddr,
4035 		    EraseByteCount,
4036 		    ERASE_FLASH,
4037 		    0,
4038 		    DL_FROM_SLIM_OFFSET,
4039 		    AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
4040 
4041 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4042 		    MBX_SUCCESS) {
4043 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4044 			    "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
4045 			    "status=%x", FileType, mb->mbxCommand,
4046 			    mb->mbxStatus);
4047 
4048 			rval = EMLXS_IMAGE_FAILED;
4049 
4050 			goto EXIT_ABS_DOWNLOAD;
4051 		}
4052 	}
4053 
4054 	while (DlByteCount) {
4055 		if (DlByteCount >= SegSize)
4056 			DlCount = SegSize;
4057 		else
4058 			DlCount = DlByteCount;
4059 
4060 		DlByteCount -= DlCount;
4061 
4062 		Dst = (uint32_t *)DataBuffer;
4063 		Src = (uint32_t *)Buffer;
4064 
4065 		for (i = 0; i < (DlCount / 4); i++) {
4066 			*Dst = *Src;
4067 			Dst++;
4068 			Src++;
4069 		}
4070 
4071 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
4072 		    (volatile uint32_t *)((volatile char *)
4073 		    hba->sli.sli3.slim_addr + sizeof (MAILBOX)),
4074 		    (DlCount / sizeof (uint32_t)));
4075 
4076 		if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
4077 			emlxs_format_load_area_cmd(mbox,
4078 			    DlToAddr,
4079 			    DlCount,
4080 			    PROGRAM_FLASH,
4081 			    (DlByteCount) ? 0 : 1,
4082 			    DL_FROM_SLIM_OFFSET,
4083 			    AreaId,
4084 			    MBX_LOAD_AREA,
4085 			    (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
4086 
4087 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4088 			    MBX_SUCCESS) {
4089 				EMLXS_MSGF(EMLXS_CONTEXT,
4090 				    &emlxs_download_failed_msg,
4091 				    "%x: Could not program 2MB Flash: Mailbox "
4092 				    "cmd=%x status=%x", FileType,
4093 				    mb->mbxCommand, mb->mbxStatus);
4094 
4095 				rval = EMLXS_IMAGE_FAILED;
4096 
4097 				goto EXIT_ABS_DOWNLOAD;
4098 			}
4099 		}
4100 
4101 		RspProgress = mb->un.varLdArea.progress;
4102 
4103 		Buffer += DlCount;
4104 		DlToAddr += DlCount;
4105 	}
4106 
4107 #ifdef FMA_SUPPORT
4108 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
4109 	    != DDI_FM_OK) {
4110 		EMLXS_MSGF(EMLXS_CONTEXT,
4111 		    &emlxs_invalid_access_handle_msg, NULL);
4112 
4113 		rval = EMLXS_IMAGE_FAILED;
4114 
4115 		goto EXIT_ABS_DOWNLOAD;
4116 	}
4117 #endif  /* FMA_SUPPORT */
4118 
4119 	if (RspProgress != RSP_DOWNLOAD_DONE) {
4120 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4121 		    "%x: Failed download response received. %x", FileType,
4122 		    RspProgress);
4123 
4124 		rval = EMLXS_IMAGE_FAILED;
4125 
4126 		goto EXIT_ABS_DOWNLOAD;
4127 	}
4128 
4129 	if (ParamsChg) {
4130 		if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
4131 		    &AbsWakeUpParms)) {
4132 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4133 			    "%x: Unable to update parms.", FileType);
4134 
4135 			rval = EMLXS_IMAGE_FAILED;
4136 		}
4137 	}
4138 
4139 EXIT_ABS_DOWNLOAD:
4140 
4141 	if (DataBuffer) {
4142 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4143 	}
4144 
4145 	if (mbox) {
4146 		kmem_free(mbox, sizeof (MAILBOXQ));
4147 	}
4148 
4149 	return (rval);
4150 
4151 } /* emlxs_proc_abs_2mb() */
4152 
4153 
4154 static void
4155 emlxs_format_load_area_cmd(MAILBOXQ * mbq,
4156     uint32_t Base,
4157     uint32_t DlByteCount,
4158     uint32_t Function,
4159     uint32_t Complete,
4160     uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
4161 {
4162 	MAILBOX *mb = (MAILBOX *)mbq;
4163 
4164 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
4165 
4166 	mb->mbxCommand = MbxCmd;
4167 	mb->mbxOwner = OWN_HOST;
4168 	mb->un.varLdArea.update_flash = 1;
4169 	mb->un.varLdArea.erase_or_prog = Function;
4170 	mb->un.varLdArea.dl_to_adr = Base;
4171 	mb->un.varLdArea.dl_len = DlByteCount;
4172 	mb->un.varLdArea.load_cmplt = Complete;
4173 	mb->un.varLdArea.method = DL_FROM_SLIM;
4174 	mb->un.varLdArea.area_id = AreaId;
4175 	mb->un.varLdArea.step = StepCmd;
4176 	mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
4177 	mbq->mbox_cmpl = NULL;
4178 
4179 } /* emlxs_format_load_area_cmd() */
4180 
4181 
4182 /* ARGSUSED */
4183 static uint32_t
4184 emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
4185     PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
4186 {
4187 	emlxs_port_t *port = &PPORT;
4188 	uint32_t pId[2];
4189 	uint32_t returnStat;
4190 
4191 	/* Read wakeup paramters */
4192 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
4193 	    CFG_DATA_NO_REGION) {
4194 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4195 		    "Unable to get BWC parameters.");
4196 		return (FALSE);
4197 	}
4198 
4199 	pId[0] = AifHdr->AVersion;
4200 	pId[1] = 0;
4201 
4202 	if (extType == BWCext) {
4203 		AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4204 		AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4205 		AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4206 		AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4207 	}
4208 
4209 	else if (extType == ALLext) {
4210 		if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
4211 			/* case of EROM inactive */
4212 			AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4213 			AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4214 		} else {
4215 			/* case of EROM active */
4216 			if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
4217 				/* same ID */
4218 				AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4219 				AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4220 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4221 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4222 			} else {
4223 				/* different ID */
4224 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4225 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4226 
4227 				returnStat =
4228 				    emlxs_update_exp_rom(hba, AbsWakeUpParms);
4229 
4230 				if (returnStat) {
4231 					AbsWakeUpParms->u0.boot_bios_wd[0] =
4232 					    pId[0];
4233 					AbsWakeUpParms->u0.boot_bios_wd[1] =
4234 					    pId[1];
4235 				}
4236 			}
4237 		}
4238 	}
4239 
4240 	return (TRUE);
4241 
4242 } /* emlxs_build_parms_2mb_bwc() */
4243 
4244 
4245 /* ARGSUSED */
4246 static uint32_t
4247 emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba,
4248     caddr_t Buffer,
4249     uint32_t BufferSize,
4250     PAIF_HDR AifHeader,
4251     PWAKE_UP_PARMS AbsWakeUpParms,
4252     uint32_t BWCflag, uint32_t extType, uint32_t *numBootImage)
4253 {
4254 	emlxs_port_t *port = &PPORT;
4255 	uint32_t NextImage;
4256 	uint32_t i;
4257 	IMAGE_HDR ImageHdr;
4258 	uint32_t *ptr1;
4259 	uint32_t *ptr2;
4260 	PROG_ID BootId[MAX_BOOTID];
4261 	uint32_t ChangeParams = FALSE;
4262 	WAKE_UP_PARMS WakeUpParms;
4263 	caddr_t Sptr;
4264 	caddr_t Dptr;
4265 
4266 	bzero(&BootId, (sizeof (PROG_ID)) * MAX_BOOTID);
4267 
4268 	/* Read wakeup paramters */
4269 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
4270 	    CFG_DATA_NO_REGION) {
4271 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4272 		    "Unable to get DWC parameters.");
4273 		return (FALSE);
4274 	}
4275 
4276 	bcopy((caddr_t)AbsWakeUpParms, (caddr_t)&WakeUpParms,
4277 	    sizeof (WAKE_UP_PARMS));
4278 
4279 	if (((BWCflag == ALL_WITHOUT_BWC) || (extType == DWCext)) &&
4280 	    (WakeUpParms.u0.boot_bios_wd[0])) {
4281 		*numBootImage = 0;
4282 	}
4283 
4284 	/* incoming buffer is without aif header */
4285 	NextImage = 0x84 - sizeof (AIF_HDR);
4286 	BufferSize -= (sizeof (AIF_HDR) + sizeof (uint32_t));
4287 
4288 	while (BufferSize > NextImage) {
4289 		Sptr = &Buffer[NextImage];
4290 		Dptr = (caddr_t)&ImageHdr;
4291 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
4292 			Dptr[i] = Sptr[i];
4293 		}
4294 
4295 		if (ImageHdr.BlockSize == 0xffffffff) {
4296 			break;
4297 		}
4298 
4299 		switch (ImageHdr.Id.Type) {
4300 		case TEST_PROGRAM:
4301 			break;
4302 
4303 		case FUNC_FIRMWARE:
4304 			AbsWakeUpParms->prog_id = ImageHdr.Id;
4305 			ChangeParams = TRUE;
4306 			break;
4307 
4308 		case BOOT_BIOS:
4309 			if (!WakeUpParms.u0.boot_bios_wd[0]) {
4310 				if (extType == DWCext) {
4311 					break;
4312 				} else if (BWCflag == ALL_WITHOUT_BWC) {
4313 					/* for possible future changes */
4314 					break;
4315 				}
4316 			}
4317 			ChangeParams = TRUE;
4318 
4319 			if (*numBootImage < MAX_BOOTID) {
4320 				BootId[*numBootImage] = ImageHdr.Id;
4321 				(*numBootImage)++;
4322 			}
4323 			break;
4324 
4325 		case SLI1_OVERLAY:
4326 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
4327 			ChangeParams = TRUE;
4328 			break;
4329 
4330 		case SLI2_OVERLAY:
4331 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
4332 			ChangeParams = TRUE;
4333 			break;
4334 
4335 		case SLI3_OVERLAY:
4336 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
4337 			ChangeParams = TRUE;
4338 			break;
4339 
4340 		case SLI4_OVERLAY:
4341 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
4342 			ChangeParams = TRUE;
4343 			break;
4344 		}
4345 
4346 		NextImage += ImageHdr.BlockSize;
4347 	}
4348 
4349 	if ((ChangeParams) && ((BWCflag == ALL_WITHOUT_BWC) ||
4350 	    (extType == DWCext))) {
4351 
4352 		if (*numBootImage > 1) {
4353 			for (i = 0; i < *numBootImage; i++) {
4354 				ptr1 =
4355 				    (uint32_t *)&WakeUpParms.u0.
4356 				    boot_bios_id;
4357 				ptr2 = (uint32_t *)&BootId[i];
4358 
4359 				if (ptr1[0] == ptr2[0]) {
4360 					AbsWakeUpParms->u1.EROM_prog_id =
4361 					    BootId[i];
4362 					(void) emlxs_update_exp_rom(hba,
4363 					    AbsWakeUpParms);
4364 					break;
4365 				}
4366 			}
4367 		} else {
4368 			if (*numBootImage == 1) {
4369 				ptr2 = (uint32_t *)&BootId[0];
4370 
4371 				if (WakeUpParms.u0.boot_bios_wd[0] == ptr2[0]) {
4372 					AbsWakeUpParms->u1.EROM_prog_id =
4373 					    BootId[0];
4374 					(void) emlxs_update_exp_rom(hba,
4375 					    AbsWakeUpParms);
4376 				}
4377 			}
4378 		}
4379 	}
4380 
4381 	return (ChangeParams);
4382 
4383 
4384 } /* emlxs_build_parms_2mb_dwc() */
4385 
4386 
4387 extern uint32_t
4388 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
4389     uint32_t *MaxIbusSize)
4390 {
4391 	emlxs_port_t *port = &PPORT;
4392 	MAILBOXQ *mbox;
4393 	MAILBOX *mb;
4394 	uint32_t *Uptr;
4395 	uint32_t rval = 0;
4396 
4397 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4398 	    KM_NOSLEEP)) == NULL) {
4399 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4400 		    "Unable to allocate mailbox buffer.");
4401 
4402 		return (1);
4403 	}
4404 
4405 	mb = (MAILBOX *)mbox;
4406 
4407 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
4408 
4409 	if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) !=
4410 	    MBX_SUCCESS) {
4411 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4412 		    "Unable to get SRAM size: Mailbox cmd=%x status=%x",
4413 		    mb->mbxCommand, mb->mbxStatus);
4414 
4415 		rval = 1;
4416 
4417 		goto Exit_Function;
4418 	}
4419 
4420 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4421 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
4422 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
4423 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
4424 	} else {
4425 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
4426 	}
4427 
4428 	*MaxRbusSize = Uptr[0];
4429 	*MaxIbusSize = Uptr[1];
4430 
4431 Exit_Function:
4432 
4433 	if (mbox) {
4434 		kmem_free(mbox, sizeof (MAILBOXQ));
4435 	}
4436 
4437 #ifdef FMA_SUPPORT
4438 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4439 		if (emlxs_fm_check_dma_handle(hba,
4440 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
4441 			EMLXS_MSGF(EMLXS_CONTEXT,
4442 			    &emlxs_invalid_dma_handle_msg,
4443 			    "emlxs_get_max_sram: hdl=%p",
4444 			    hba->sli.sli4.dump_region.dma_handle);
4445 			rval = 1;
4446 		}
4447 	}
4448 #endif  /* FMA_SUPPORT */
4449 
4450 	return (rval);
4451 
4452 } /* emlxs_get_max_sram() */
4453 
4454 
4455 static uint32_t
4456 emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
4457 {
4458 	uint8_t *ptr;
4459 	uint8_t ver;
4460 
4461 	ver = version & 0xff;
4462 	ptr = hba->model_info.pt_FF;
4463 
4464 	while (*ptr) {
4465 		if (*ptr++ == ver) {
4466 			return (1);
4467 		}
4468 	}
4469 
4470 	return (0);
4471 
4472 } /* emlxs_kern_check() */
4473 
4474 static uint32_t
4475 emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
4476 {
4477 	uint8_t *ptr;
4478 	uint8_t ver;
4479 
4480 	ver = version & 0xff;
4481 	ptr = hba->model_info.pt_2;
4482 
4483 	while (*ptr) {
4484 		if (*ptr++ == ver) {
4485 			return (1);
4486 		}
4487 	}
4488 
4489 	return (0);
4490 
4491 } /* emlxs_stub_check() */
4492 
4493 static uint32_t
4494 emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
4495 {
4496 	uint8_t *ptr;
4497 	uint8_t ver;
4498 
4499 	ver = version & 0xff;
4500 	ptr = hba->model_info.pt_3;
4501 
4502 	while (*ptr) {
4503 		if (*ptr++ == ver) {
4504 			return (1);
4505 		}
4506 	}
4507 
4508 	return (0);
4509 
4510 } /* emlxs_bios_check() */
4511 
4512 static uint32_t
4513 emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
4514 {
4515 	uint8_t *ptr;
4516 	uint8_t ver;
4517 
4518 	ver = version & 0xff;
4519 	ptr = hba->model_info.pt_6;
4520 
4521 	while (*ptr) {
4522 		if (*ptr++ == ver) {
4523 			return (1);
4524 		}
4525 	}
4526 
4527 	return (0);
4528 
4529 } /* emlxs_sli1_check() */
4530 
4531 static uint32_t
4532 emlxs_sli2_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_7;
4539 
4540 	while (*ptr) {
4541 		if (*ptr++ == ver) {
4542 			return (1);
4543 		}
4544 	}
4545 
4546 	return (0);
4547 
4548 } /* emlxs_sli2_check() */
4549 
4550 static uint32_t
4551 emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
4552 {
4553 	uint8_t *ptr;
4554 	uint8_t ver;
4555 
4556 	ver = version & 0xff;
4557 	ptr = hba->model_info.pt_B;
4558 
4559 	while (*ptr) {
4560 		if (*ptr++ == ver) {
4561 			return (1);
4562 		}
4563 	}
4564 
4565 	return (0);
4566 
4567 } /* emlxs_sli3_check() */
4568 
4569 
4570 static uint32_t
4571 emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
4572 {
4573 	uint8_t *ptr;
4574 	uint8_t ver;
4575 
4576 	ver = version & 0xff;
4577 	ptr = hba->model_info.pt_E;
4578 
4579 	while (*ptr) {
4580 		if (*ptr++ == ver) {
4581 			return (1);
4582 		}
4583 	}
4584 
4585 	return (0);
4586 
4587 } /* emlxs_sli4_check() */
4588 
4589 
4590 static uint32_t
4591 emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
4592 {
4593 	uint8_t *ptr;
4594 	uint8_t ver;
4595 
4596 	ver = version & 0xff;
4597 	ptr = hba->model_info.pt_A;
4598 
4599 	while (*ptr) {
4600 		if (*ptr++ == ver) {
4601 			return (1);
4602 		}
4603 	}
4604 
4605 	return (0);
4606 
4607 } /* emlxs_sbus_fcode_check() */
4608 
4609 static uint32_t
4610 emlxs_type_check(uint32_t type)
4611 {
4612 	if (type == 0xff) {
4613 		return (KERNEL_CODE);
4614 	}
4615 
4616 	if (type >= MAX_PROG_TYPES) {
4617 		return (RESERVED_D);
4618 	}
4619 
4620 	return (type);
4621 
4622 } /* emlxs_type_check() */
4623 
4624 
4625 
4626 extern int32_t
4627 emlxs_boot_code_disable(emlxs_hba_t *hba)
4628 {
4629 	emlxs_port_t *port = &PPORT;
4630 	PROG_ID Id;
4631 	emlxs_vpd_t *vpd;
4632 
4633 	vpd = &VPD;
4634 
4635 	if (hba->model_info.chip == EMLXS_BE_CHIP) {
4636 		return (EMLXS_OP_NOT_SUP);
4637 	}
4638 
4639 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
4640 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4641 		    "emlxs_boot_code_disable: Unable to read wake up parms.");
4642 
4643 		return (FC_FAILURE);
4644 	}
4645 
4646 	/* Check if boot code is already disabled */
4647 	if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
4648 		return (FC_SUCCESS);
4649 	}
4650 
4651 	/* Make sure EROM entry has copy of boot bios entry */
4652 	if (!(hba->model_info.chip &
4653 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
4654 	    (hba->wakeup_parms.u0.boot_bios_wd[0] !=
4655 	    hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
4656 	    (hba->wakeup_parms.u0.boot_bios_wd[1] !=
4657 	    hba->wakeup_parms.u1.EROM_prog_wd[1])) {
4658 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
4659 		    &hba->wakeup_parms.u0.boot_bios_id, 1);
4660 	}
4661 
4662 	/* Update the bios id with a zero id */
4663 	/* Don't load the EROM this time */
4664 	bzero(&Id, sizeof (PROG_ID));
4665 	(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0);
4666 
4667 	/* Now read the parms again to verify */
4668 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
4669 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
4670 	    vpd->boot_version);
4671 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
4672 
4673 	/* Return the result */
4674 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
4675 	    FC_SUCCESS : FC_FAILURE);
4676 
4677 } /* emlxs_boot_code_disable() */
4678 
4679 
4680 extern int32_t
4681 emlxs_boot_code_enable(emlxs_hba_t *hba)
4682 {
4683 	emlxs_port_t *port = &PPORT;
4684 	emlxs_vpd_t *vpd;
4685 	PROG_ID load_list[MAX_LOAD_ENTRY];
4686 	uint32_t i;
4687 
4688 	vpd = &VPD;
4689 
4690 	if (hba->model_info.chip == EMLXS_BE_CHIP) {
4691 		return (FC_SUCCESS);
4692 	}
4693 
4694 	/* Read the wakeup parms */
4695 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
4696 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4697 		    "emlxs_boot_code_enable: Unable to read wake up parms.");
4698 
4699 		return (FC_FAILURE);
4700 	}
4701 
4702 	/* Check if boot code is already enabled */
4703 	if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
4704 		return (FC_SUCCESS);
4705 	}
4706 
4707 	if (!(hba->model_info.chip &
4708 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
4709 		if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) {
4710 			return (EMLXS_NO_BOOT_CODE);
4711 		}
4712 
4713 		/* Update the parms with the boot image id */
4714 		/* Don't load the EROM this time */
4715 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
4716 		    &hba->wakeup_parms.u1.EROM_prog_id, 0);
4717 	} else {	/* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
4718 
4719 		if (emlxs_get_load_list(hba, load_list)) {
4720 			return (FC_FAILURE);
4721 		}
4722 
4723 		/* Scan load list for a boot image */
4724 		for (i = 0; i < MAX_LOAD_ENTRY; i++) {
4725 			if (load_list[i].Type == BOOT_BIOS) {
4726 				/* Update the parms with the boot image id */
4727 				/* Don't load the EROM this time */
4728 				(void) emlxs_update_boot_wakeup_parms(hba,
4729 				    &hba->wakeup_parms, &load_list[i], 0);
4730 
4731 				break;
4732 			}
4733 		}
4734 
4735 		if (i == MAX_LOAD_ENTRY) {
4736 			return (EMLXS_NO_BOOT_CODE);
4737 		}
4738 	}
4739 
4740 	/* Now read the parms again to verify */
4741 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
4742 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
4743 	    vpd->boot_version);
4744 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
4745 
4746 	/* return the result */
4747 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
4748 	    FC_SUCCESS : FC_FAILURE);
4749 
4750 } /* emlxs_boot_code_enable() */
4751 
4752 
4753 
4754 extern int32_t
4755 emlxs_boot_code_state(emlxs_hba_t *hba)
4756 {
4757 	emlxs_port_t *port = &PPORT;
4758 
4759 	if (hba->model_info.chip == EMLXS_BE_CHIP) {
4760 		return (FC_SUCCESS);
4761 	}
4762 
4763 	/* Read the wakeup parms */
4764 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
4765 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4766 		    "emlxs_boot_code_state: Unable to read wake up parms.");
4767 
4768 		return (FC_FAILURE);
4769 	}
4770 
4771 	/* return the result */
4772 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
4773 	    FC_SUCCESS : FC_FAILURE);
4774 
4775 } /* emlxs_boot_code_state() */
4776