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 #include <emlxs.h>
28 
29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30 EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C);
31 
32 #define	MAX_BOOTID	10
33 
34 #define	DATA32_SWAP(x)	((((x) & 0xFF)<<24) | (((x) & 0xFF00)<<8) | \
35 				(((x) & 0xFF0000)>>8) | \
36 				(((x) & 0xFF000000)>>24))
37 
38 static uint32_t	emlxs_erase_fcode_flash(emlxs_hba_t *hba);
39 static uint32_t	emlxs_write_fcode_flash(emlxs_hba_t *hba,
40 			PIMAGE_HDR ImageHdr, caddr_t Buffer);
41 
42 static int32_t	emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
43 			uint32_t BufferSize, PAIF_HDR AifHeader,
44 			int32_t DwcFile);
45 
46 static uint32_t	emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
47 			uint32_t Size, emlxs_fw_image_t *fw_image);
48 
49 static void	emlxs_format_dump(MAILBOX *mb, uint32_t Type, uint32_t RegionId,
50 			uint32_t WordCount, uint32_t BaseAddr);
51 
52 static uint32_t	emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
53 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
54 			uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize,
55 			PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile);
56 
57 static uint32_t	emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
58 			uint32_t len, uint32_t offline,
59 			emlxs_fw_image_t *fw_image);
60 
61 static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba, PAIF_HDR AifHdr,
62 			caddr_t EntireBuffer, uint32_t FileType,
63 			uint32_t BWCflag, uint32_t extType);
64 
65 static void	emlxs_format_load_area_cmd(MAILBOX *mb, uint32_t Base,
66 			uint32_t DlByteCount, uint32_t Function,
67 			uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
68 			uint8_t MbxCmd, uint32_t StepCmd);
69 
70 static uint32_t	emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
71 			uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
72 
73 static uint32_t	emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba, caddr_t Buffer,
74 			uint32_t BufferSize, PAIF_HDR AifHeader,
75 			PWAKE_UP_PARMS AbsWakeUpParms, uint32_t BWCflag,
76 			uint32_t extType, uint32_t *numBootImage);
77 
78 static uint32_t	emlxs_update_exp_rom(emlxs_hba_t *hba,
79 			PWAKE_UP_PARMS WakeUpParms);
80 
81 extern uint32_t	emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
82 			uint32_t *MaxIbusSize);
83 
84 static void	emlxs_format_prog_flash(MAILBOX *mb, uint32_t Base,
85 			uint32_t DlByteCount, uint32_t Function,
86 			uint32_t Complete, uint32_t BdeAddress,
87 			uint32_t BdeSize, PROG_ID *ProgId);
88 
89 static void	emlxs_format_update_parms(MAILBOX *mb,
90 			PWAKE_UP_PARMS WakeUpParms);
91 
92 static void	emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOX *mb,
93 			uint32_t region_id, uint32_t size);
94 
95 static uint32_t	emlxs_update_wakeup_parms(emlxs_hba_t *hba,
96 			PWAKE_UP_PARMS AbsWakeUpParms,
97 			PWAKE_UP_PARMS WakeUpParms);
98 
99 static uint32_t	emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba,
100 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id,
101 			uint32_t proc_erom);
102 
103 static uint32_t	emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba,
104 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
105 
106 static uint32_t	emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba,
107 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
108 
109 static uint32_t	emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba,
110 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
111 
112 static uint32_t	emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba,
113 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
114 
115 static uint32_t	emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba,
116 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
117 
118 
119 static uint32_t	emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
120 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
121 			uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize);
122 
123 static uint32_t	emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
124 
125 static uint32_t	emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
126 static void	emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr);
127 static void	emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
128 static uint32_t	emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize);
129 
130 static uint32_t	emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer,
131 			uint32_t BufferSize, PAIF_HDR AifHeader);
132 
133 static uint32_t	emlxs_type_check(uint32_t type);
134 static uint32_t	emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
135 static uint32_t	emlxs_stub_check(emlxs_hba_t *hba, uint32_t version);
136 static uint32_t	emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version);
137 static uint32_t	emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version);
138 static uint32_t	emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version);
139 static uint32_t	emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version);
140 static uint32_t	emlxs_bios_check(emlxs_hba_t *hba, uint32_t version);
141 static uint32_t	emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version);
142 static uint32_t	emlxs_validate_version(emlxs_hba_t *hba,
143 			emlxs_fw_file_t *file, uint32_t id, uint32_t type,
144 			char *file_type);
145 
146 /* ************************************************************************* */
147 
148 
149 extern int32_t
150 emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
151     uint32_t offline)
152 {
153 	emlxs_port_t *port = &PPORT;
154 	uint32_t *Uptr;
155 	IMAGE_HDR ImageHdr;
156 	AIF_HDR AifHdr;
157 	uint32_t ImageType;
158 	WAKE_UP_PARMS WakeUpParms;
159 	WAKE_UP_PARMS AbsWakeUpParms;
160 	uint32_t MaxRbusSramSize;
161 	uint32_t MaxIbusSramSize;
162 	int32_t AbsChangeParams = 0;
163 	int32_t DwcFile = FALSE;
164 	uint32_t rval = 0;
165 	emlxs_fw_image_t fw_image;
166 	uint32_t i;
167 
168 #ifdef EMLXS_I386
169 	caddr_t local_buffer;
170 	uint32_t *bptr1;
171 	uint32_t *bptr2;
172 #endif /* EMLXS_I386 */
173 
174 	if (buffer == NULL || len == 0) {
175 		return (EMLXS_IMAGE_BAD);
176 	}
177 #ifdef EMLXS_I386
178 	/* We need to swap the image buffer before we start */
179 
180 	/*
181 	 * Use KM_SLEEP to allocate a temporary buffer
182 	 */
183 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
184 
185 	if (local_buffer == NULL) {
186 		return (FC_NOMEM);
187 	}
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 = SWAP_DATA32(*bptr2);
194 		bptr1++;
195 		bptr2++;
196 	}
197 
198 	/* Replace the original buffer */
199 	buffer = local_buffer;
200 #endif /* EMLXS_I386 */
201 
202 
203 	bzero(&fw_image, sizeof (emlxs_fw_image_t));
204 	for (i = 0; i < MAX_PROG_TYPES; i++) {
205 		(void) strcpy(fw_image.prog[i].label, "none");
206 	}
207 
208 	/* Validate image */
209 	if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) {
210 		goto done;
211 	}
212 
213 	/* Get image type */
214 	Uptr = (uint32_t *)buffer;
215 	ImageType = *Uptr;
216 
217 	/*
218 	 * Pegasus and beyond FW download is done differently
219 	 * for absolute download.
220 	 */
221 
222 	/* Check for absolute image */
223 	if ((ImageType == NOP_IMAGE_TYPE) &&
224 	    !(hba->model_info.chip &
225 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
226 		/*
227 		 * Because 2Mb flash download file format is different from
228 		 * 512k, it needs to be handled differently
229 		 */
230 		if (rval = emlxs_start_abs_download_2mb(hba, buffer, len,
231 		    offline, &fw_image)) {
232 			goto done;
233 		}
234 
235 		/* Offline already handled */
236 		offline = 0;
237 
238 		goto SLI_DOWNLOAD_EXIT;
239 	}
240 
241 	/* Pre-pegasus adapters only */
242 
243 	/* Check for absolute image */
244 	else if (ImageType == NOP_IMAGE_TYPE) {
245 		bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
246 		bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
247 
248 		if (AifHdr.ImageBase && (AifHdr.ImageBase == 0x20000)) {
249 			DwcFile = TRUE;
250 		}
251 
252 		AbsChangeParams = emlxs_build_parms(buffer,
253 		    &AbsWakeUpParms, len, &AifHdr, DwcFile);
254 	} else {	/* (ImageType != NOP_IMAGE_TYPE) Relative image */
255 
256 		bzero((void *)&AifHdr, sizeof (AIF_HDR));
257 		bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
258 	}
259 
260 	/*
261 	 * Everything checks out, now to just do it
262 	 */
263 
264 	if (offline) {
265 		if (emlxs_offline(hba) != FC_SUCCESS) {
266 			offline = 0;
267 
268 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
269 			    "Unable to take adapter offline.");
270 
271 			rval = EMLXS_OFFLINE_FAILED;
272 
273 			goto SLI_DOWNLOAD_EXIT;
274 		}
275 
276 		if (emlxs_sli_hba_reset(hba, 1, 1) != FC_SUCCESS) {
277 			offline = 0;
278 
279 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
280 			    "Unable to restart adapter.");
281 
282 			rval = EMLXS_OFFLINE_FAILED;
283 
284 			goto SLI_DOWNLOAD_EXIT;
285 		}
286 	}
287 
288 	if (ImageHdr.Id.Type == SBUS_FCODE) {
289 		/* Erase Flash */
290 		if (emlxs_erase_fcode_flash(hba)) {
291 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
292 			    "Unable to erase flash.");
293 
294 			rval = EMLXS_IMAGE_FAILED;
295 
296 			goto SLI_DOWNLOAD_EXIT;
297 		}
298 
299 		/* Write FCODE */
300 		if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) {
301 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
302 			    "Unable to write flash.");
303 
304 			rval = EMLXS_IMAGE_FAILED;
305 
306 			goto SLI_DOWNLOAD_EXIT;
307 		}
308 
309 	} else {	/* !SBUS_FCODE */
310 
311 
312 		if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
313 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
314 			    "Unable to get parameters.");
315 
316 			rval = EMLXS_IMAGE_FAILED;
317 
318 			goto SLI_DOWNLOAD_EXIT;
319 		}
320 
321 		if (emlxs_get_max_sram(hba, &MaxRbusSramSize,
322 		    &MaxIbusSramSize)) {
323 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
324 			    "Unable to get RAM size.");
325 
326 			rval = EMLXS_IMAGE_FAILED;
327 
328 			goto SLI_DOWNLOAD_EXIT;
329 		}
330 
331 		if (ImageType == NOP_IMAGE_TYPE) {
332 			if (emlxs_start_abs_download(hba, &AifHdr, buffer,
333 			    &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize,
334 			    (AbsChangeParams) ? &AbsWakeUpParms : NULL,
335 			    DwcFile)) {
336 				EMLXS_MSGF(EMLXS_CONTEXT,
337 				    &emlxs_download_failed_msg,
338 				    "Failed to program flash.");
339 
340 				rval = EMLXS_IMAGE_FAILED;
341 
342 				goto SLI_DOWNLOAD_EXIT;
343 			}
344 
345 		} else {
346 
347 			if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
348 			    &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize)) {
349 				EMLXS_MSGF(EMLXS_CONTEXT,
350 				    &emlxs_download_failed_msg,
351 				    "Failed to program flash.");
352 
353 				rval = EMLXS_IMAGE_FAILED;
354 
355 				goto SLI_DOWNLOAD_EXIT;
356 			}
357 		}
358 
359 	}	/* !SBUS_FCODE */
360 
361 
362 SLI_DOWNLOAD_EXIT:
363 
364 	if (offline) {
365 		(void) emlxs_online(hba);
366 	}
367 
368 	if (rval == 0) {
369 
370 
371 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
372 		    "Status good.");
373 	}
374 
375 done:
376 
377 #ifdef EMLXS_I386
378 	/* Free the local buffer */
379 	kmem_free(local_buffer, len);
380 #endif /* EMLXS_I386 */
381 
382 	return (rval);
383 
384 }  /* emlxs_fw_download */
385 
386 
387 
388 extern int32_t
389 emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer,
390     uint32_t len)
391 {
392 	emlxs_port_t *port = &PPORT;
393 	MAILBOXQ *mbox = NULL;
394 	MAILBOX *mb;
395 	uint32_t rval = 0;
396 	uint32_t region_id;
397 	uint32_t id;
398 
399 #ifndef EMLXS_I386
400 	caddr_t local_buffer;
401 	uint32_t *bptr1;
402 	uint32_t *bptr2;
403 	uint32_t i;
404 #endif /* !EMLXS_I386 */
405 
406 	if (buffer == NULL || len == 0) {
407 		return (EMLXS_IMAGE_BAD);
408 	}
409 #ifndef EMLXS_I386
410 	/* We need to swap the image buffer before we start */
411 
412 	/*
413 	 * Use KM_SLEEP to allocate a temporary buffer
414 	 */
415 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
416 
417 	if (local_buffer == NULL) {
418 		return (FC_NOMEM);
419 	}
420 
421 	/* Perform a 32 bit swap of the image */
422 	bptr1 = (uint32_t *)local_buffer;
423 	bptr2 = (uint32_t *)buffer;
424 
425 	for (i = 0; i < (len / 4); i++) {
426 		*bptr1 = DATA32_SWAP(*bptr2);
427 		bptr1++;
428 		bptr2++;
429 	}
430 
431 	/* Replace the original buffer */
432 	buffer = local_buffer;
433 
434 #endif /* !EMLXS_I386 */
435 
436 	if (len > 128) {
437 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
438 		    "Invalid image length: 0x%x > 128", len);
439 
440 		return (EMLXS_IMAGE_BAD);
441 	}
442 
443 	/* Check the region number */
444 	if ((region > 2) && (region != 0xff)) {
445 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
446 		    "Invalid region id: 0x%x", region);
447 
448 		return (EMLXS_IMAGE_BAD);
449 
450 	}
451 
452 	/* Check the image vendor id */
453 	id = *(int32_t *)buffer;
454 	if ((id & 0xffff) != 0x10df) {
455 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
456 		    "Invalid image id: 0x%x", id);
457 
458 		return (EMLXS_IMAGE_BAD);
459 	}
460 
461 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
462 	    KM_NOSLEEP)) == NULL) {
463 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
464 		    "Unable to allocate mailbox buffer.");
465 
466 		rval = 1;
467 
468 		goto done;
469 	}
470 
471 	mb = (MAILBOX *)mbox;
472 
473 	/*
474 	 * Everything checks out, now to just do it
475 	 */
476 	if (emlxs_offline(hba) != FC_SUCCESS) {
477 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
478 		    "Unable to take HBA offline.");
479 
480 		rval = EMLXS_OFFLINE_FAILED;
481 
482 		goto done;
483 	}
484 
485 	if (emlxs_sli_hba_reset(hba, 1, 1) != FC_SUCCESS) {
486 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
487 		    "Unable to restart adapter.");
488 
489 		rval = EMLXS_OFFLINE_FAILED;
490 
491 		goto done;
492 	}
493 
494 	/* Check if default region is requested */
495 	if (region == 0xff) {
496 		/*
497 		 * Sun-branded Helios and Zypher have different
498 		 * default PCI region
499 		 */
500 		if ((hba->model_info.flags & EMLXS_SUN_BRANDED) &&
501 		    (hba->model_info.chip &
502 		    (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
503 			region = 2;
504 		} else {
505 			region = 0;
506 		}
507 	}
508 
509 	/* Set region id based on PCI region requested */
510 	region_id = DEF_PCI_CFG_REGION_ID + region;
511 
512 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
513 	    "PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
514 	    region_id, id, len);
515 
516 	/* Copy the data buffer to SLIM */
517 	WRITE_SLIM_COPY(hba, (uint32_t *)buffer,
518 	    (volatile uint32_t *)((volatile char *)hba->slim_addr +
519 	    sizeof (MAILBOX)), (len / sizeof (uint32_t)));
520 
521 #ifdef FMA_SUPPORT
522 	if (emlxs_fm_check_acc_handle(hba, hba->slim_acc_handle)
523 	    != DDI_FM_OK) {
524 		EMLXS_MSGF(EMLXS_CONTEXT,
525 		    &emlxs_invalid_access_handle_msg, NULL);
526 		rval = 1;
527 	}
528 #endif  /* FMA_SUPPORT */
529 
530 	emlxs_format_update_pci_cfg(hba, mb, region_id, len);
531 
532 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
533 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
534 		    "Unable to update PCI configuration: Mailbox cmd=%x "
535 		    "status=%x info=%d", mb->mbxCommand, mb->mbxStatus,
536 		    mb->un.varUpdateCfg.rsp_info);
537 
538 		rval = 1;
539 	}
540 
541 	(void) emlxs_online(hba);
542 
543 	if (rval == 0) {
544 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
545 		    "Status good.");
546 	}
547 
548 done:
549 
550 	if (mbox) {
551 		kmem_free(mbox, sizeof (MAILBOXQ));
552 	}
553 #ifndef EMLXS_I386
554 	/* Free the local buffer */
555 	kmem_free(local_buffer, len);
556 #endif /* !EMLXS_I386 */
557 
558 	return (rval);
559 
560 }  /* emlxs_cfl_download */
561 
562 
563 
564 static uint32_t
565 emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr)
566 {
567 	uint32_t Temp;
568 	uint32_t CkSum;
569 
570 	EndAddr++;
571 	CkSum = SLI_CKSUM_SEED;
572 
573 	CkSum = (CkSum >> 1) | (CkSum << 31);
574 	while (StartAddr != EndAddr) {
575 		CkSum = (CkSum << 1) | (CkSum >> 31);
576 		Temp = *StartAddr;
577 
578 		CkSum ^= Temp;
579 		StartAddr++;
580 	}
581 
582 	return (CkSum << 1) | (CkSum >> 31);
583 
584 }  /* emlxs_valid_cksum() */
585 
586 
587 static void
588 emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr)
589 {
590 	emlxs_port_t *port = &PPORT;
591 
592 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: ");
593 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
594 	    "AIF Header: compress_br = 0x%x", AifHdr->CompressBr);
595 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
596 	    "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr);
597 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
598 	    "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr);
599 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
600 	    "AIF Header: entry_br = 0x%x", AifHdr->EntryBr);
601 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
602 	    "AIF Header: area_id = 0x%x", AifHdr->Area_ID);
603 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
604 	    "AIF Header: rosize = 0x%x", AifHdr->RoSize);
605 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
606 	    "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize);
607 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
608 	    "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize);
609 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
610 	    "AIF Header: dbgtype = 0x%x", AifHdr->DbgType);
611 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
612 	    "AIF Header: imagebase = 0x%x", AifHdr->ImageBase);
613 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
614 	    "AIF Header: area_size = 0x%x", AifHdr->Area_Size);
615 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
616 	    "AIF Header: address_mode = 0x%x", AifHdr->AddressMode);
617 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
618 	    "AIF Header: database = 0x%x", AifHdr->DataBase);
619 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
620 	    "AIF Header: aversion = 0x%x", AifHdr->AVersion);
621 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
622 	    "AIF Header: spare2 = 0x%x", AifHdr->Spare2);
623 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
624 	    "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi);
625 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
626 	    "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]);
627 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
628 	    "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]);
629 
630 }  /* emlxs_disp_aif_header() */
631 
632 
633 
634 static void
635 emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image)
636 {
637 	emlxs_port_t *port = &PPORT;
638 
639 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: ");
640 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
641 	    "Img Header: BlockSize = 0x%x", image->BlockSize);
642 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
643 	    "Img Header: PROG_ID Type = 0x%x", image->Id.Type);
644 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
645 	    "Img Header: PROG_ID Id = 0x%x", image->Id.Id);
646 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
647 	    "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver);
648 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
649 	    "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev);
650 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
651 	    "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp);
652 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
653 	    "Img Header: Flags = 0x%x", image->Flags);
654 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
655 	    "Img Header: EntryAdr = 0x%x", image->EntryAdr);
656 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
657 	    "Img Header: InitAdr = 0x%x", image->InitAdr);
658 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
659 	    "Img Header: ExitAdr = 0x%x", image->ExitAdr);
660 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
661 	    "Img Header: ImageBase = 0x%x", image->ImageBase);
662 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
663 	    "Img Header: ImageSize = 0x%x", image->ImageSize);
664 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
665 	    "Img Header: ZinitSize = 0x%x", image->ZinitSize);
666 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
667 	    "Img Header: RelocSize = 0x%x", image->RelocSize);
668 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
669 	    "Img Header: HdrCks = 0x%x", image->HdrCks);
670 
671 }  /* emlxs_dump_image_header() */
672 
673 
674 static void
675 emlxs_format_dump(MAILBOX *mb, uint32_t Type, uint32_t RegionId,
676     uint32_t WordCount, uint32_t BaseAddr)
677 {
678 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
679 
680 	mb->mbxCommand = MBX_DUMP_MEMORY;
681 	mb->un.varDmp.type = Type;
682 	mb->un.varDmp.region_id = RegionId;
683 	mb->un.varDmp.word_cnt = WordCount;
684 	mb->un.varDmp.base_adr = BaseAddr;
685 	mb->mbxOwner = OWN_HOST;
686 
687 	return;
688 
689 }  /* emlxs_format_dump() */
690 
691 
692 /* ARGSUSED */
693 static uint32_t
694 emlxs_start_abs_download(emlxs_hba_t *hba,
695     PAIF_HDR AifHdr,
696     caddr_t Buffer,
697     PWAKE_UP_PARMS WakeUpParms,
698     uint32_t MaxRbusSramSize,
699     uint32_t MaxIbusSramSize, PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile)
700 {
701 	emlxs_port_t *port = &PPORT;
702 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
703 	IMAGE_HDR ImageHdr;
704 	uint32_t *Src;
705 	uint32_t *Dst;
706 	caddr_t DataBuffer = NULL;
707 	MAILBOXQ *mbox;
708 	MAILBOX *mb;
709 	uint32_t rval = 1;
710 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
711 	uint32_t DlToAddr = AifHdr->ImageBase;
712 	uint32_t DlCount;
713 	uint32_t i;
714 
715 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
716 	    "Performing absolute download...");
717 
718 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
719 	    KM_NOSLEEP)) == NULL) {
720 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
721 		    "Unable to allocate data buffer.");
722 
723 		return (rval);
724 	}
725 
726 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
727 	    KM_NOSLEEP)) == NULL) {
728 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
729 		    "Unable to allocate mailbox buffer.");
730 
731 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
732 
733 		return (rval);
734 	}
735 
736 	mb = (MAILBOX *)mbox;
737 
738 	Buffer += sizeof (AIF_HDR);
739 
740 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash...");
741 
742 	if (DwcFile) {
743 		emlxs_format_prog_flash(mb, 0x20000, 0x50000, ERASE_FLASH, 0,
744 		    0, 0, NULL);
745 	} else {
746 		emlxs_format_prog_flash(mb, DlToAddr, DlByteCount,
747 		    ERASE_FLASH, 0, 0, 0, NULL);
748 	}
749 
750 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
751 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
752 		    "Unable to erase Flash: Mailbox cmd=%x status=%x",
753 		    mb->mbxCommand, mb->mbxStatus);
754 
755 		rval = 1;
756 
757 		goto EXIT_ABS_DOWNLOAD;
758 	}
759 
760 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
761 	    "Programming flash...");
762 
763 	while (DlByteCount) {
764 
765 		if (DlByteCount > SegSize) {
766 			DlCount = SegSize;
767 		} else {
768 			DlCount = DlByteCount;
769 		}
770 		DlByteCount -= DlCount;
771 
772 		Dst = (uint32_t *)DataBuffer;
773 		Src = (uint32_t *)Buffer;
774 
775 		for (i = 0; i < (DlCount / 4); i++) {
776 			*Dst = *Src;
777 			Dst++;
778 			Src++;
779 		}
780 
781 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
782 		    (volatile uint32_t *)((volatile char *)hba->slim_addr +
783 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
784 
785 		emlxs_format_prog_flash(mb, DlToAddr, DlCount,
786 		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL);
787 
788 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
789 		    MBX_SUCCESS) {
790 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
791 			    "Unable to program Flash: Mailbox cmd=%x status=%x",
792 			    mb->mbxCommand, mb->mbxStatus);
793 
794 			rval = 1;
795 
796 			goto EXIT_ABS_DOWNLOAD;
797 		}
798 
799 		Buffer += DlCount;
800 		DlToAddr += DlCount;
801 	}
802 
803 #ifdef FMA_SUPPORT
804 	if (emlxs_fm_check_acc_handle(hba, hba->slim_acc_handle)
805 	    != DDI_FM_OK) {
806 		EMLXS_MSGF(EMLXS_CONTEXT,
807 		    &emlxs_invalid_access_handle_msg, NULL);
808 
809 		rval = 1;
810 
811 		goto EXIT_ABS_DOWNLOAD;
812 	}
813 #endif  /* FMA_SUPPORT */
814 
815 	bzero((caddr_t)&ImageHdr, sizeof (IMAGE_HDR));
816 	ImageHdr.Id.Type = FUNC_FIRMWARE;
817 
818 	switch (MaxRbusSramSize) {
819 	case REDUCED_RBUS_SRAM_CFG:
820 		ImageHdr.Id.Id = REDUCED_SRAM_CFG_PROG_ID;
821 		break;
822 	case FULL_RBUS_SRAM_CFG:
823 		ImageHdr.Id.Id = FULL_SRAM_CFG_PROG_ID;
824 		break;
825 	default:
826 		ImageHdr.Id.Id = OTHER_SRAM_CFG_PROG_ID;
827 		break;
828 	}
829 
830 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
831 
832 	if (AbsWakeUpParms) {
833 		rval =
834 		    emlxs_update_wakeup_parms(hba, AbsWakeUpParms,
835 		    WakeUpParms);
836 	} else {
837 		rval =
838 		    emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
839 		    &ImageHdr.Id, 1);
840 	}
841 
842 EXIT_ABS_DOWNLOAD:
843 	if (DataBuffer) {
844 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
845 	}
846 
847 	if (mbox) {
848 		kmem_free(mbox, sizeof (MAILBOXQ));
849 	}
850 
851 	return (rval);
852 
853 }  /* emlxs_start_abs_download() */
854 
855 
856 /* ARGSUSED */
857 static void
858 emlxs_format_prog_flash(MAILBOX *mb,
859     uint32_t Base,
860     uint32_t DlByteCount,
861     uint32_t Function,
862     uint32_t Complete,
863     uint32_t BdeAddress, uint32_t BdeSize, PROG_ID *ProgId)
864 {
865 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
866 
867 	if (ProgId)
868 		mb->mbxCommand = MBX_DOWN_LOAD;
869 	else
870 		mb->mbxCommand = MBX_LOAD_SM;
871 
872 	mb->un.varLdSM.load_cmplt = Complete;
873 	mb->un.varLdSM.method = DL_FROM_SLIM;
874 	mb->un.varLdSM.update_flash = 1;
875 	mb->un.varLdSM.erase_or_prog = Function;
876 	mb->un.varLdSM.dl_to_adr = Base;
877 	mb->un.varLdSM.dl_len = DlByteCount;
878 
879 	if (BdeSize) {
880 		mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
881 	} else if (ProgId) {
882 		mb->un.varLdSM.un.prog_id = *ProgId;
883 	} else {
884 		mb->un.varLdSM.un.dl_from_slim_offset = 0;
885 	}
886 
887 	mb->mbxOwner = OWN_HOST;
888 
889 }  /* emlxs_format_prog_flash() */
890 
891 
892 static void
893 emlxs_format_update_parms(MAILBOX *mb, PWAKE_UP_PARMS WakeUpParms)
894 {
895 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
896 
897 	mb->mbxCommand = MBX_UPDATE_CFG;
898 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
899 	mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID;
900 	mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS);
901 	mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS);
902 
903 	bcopy((caddr_t)WakeUpParms,
904 	    (caddr_t)&(mb->un.varUpdateCfg.cfg_data),
905 	    sizeof (WAKE_UP_PARMS));
906 
907 }  /* emlxs_format_update_parms () */
908 
909 
910 /* ARGSUSED */
911 static void
912 emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOX *mb,
913     uint32_t region_id, uint32_t size)
914 {
915 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
916 
917 	mb->mbxCommand = MBX_UPDATE_CFG;
918 	mb->un.varUpdateCfg.Vbit = 1;
919 	mb->un.varUpdateCfg.Obit = 1;
920 	mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET;
921 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
922 	mb->un.varUpdateCfg.region_id = region_id;
923 	mb->un.varUpdateCfg.entry_len = size;
924 	mb->un.varUpdateCfg.byte_len = size;
925 
926 
927 }  /* emlxs_format_update_pci_cfg() */
928 
929 
930 
931 static uint32_t
932 emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
933     PROG_ID * prog_id, uint32_t proc_erom)
934 {
935 	emlxs_port_t *port = &PPORT;
936 	MAILBOX *mb;
937 	MAILBOXQ *mbox;
938 	uint32_t rval = 0;
939 
940 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
941 	    KM_NOSLEEP)) == NULL) {
942 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
943 		    "Unable to allocate mailbox buffer.");
944 
945 		return (1);
946 	}
947 
948 	mb = (MAILBOX *)mbox;
949 
950 	if (proc_erom && !(hba->model_info.chip &
951 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
952 		WakeUpParms->u1.EROM_prog_id = *prog_id;
953 		(void) emlxs_update_exp_rom(hba, WakeUpParms);
954 	}
955 
956 	WakeUpParms->u0.boot_bios_id = *prog_id;
957 
958 	emlxs_format_update_parms(mb, WakeUpParms);
959 
960 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
961 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
962 		    "Unable to update boot wakeup parms: Mailbox cmd=%x "
963 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
964 
965 		rval = 1;
966 	}
967 
968 	if (mbox) {
969 		kmem_free(mbox, sizeof (MAILBOXQ));
970 	}
971 
972 	return (rval);
973 
974 }  /* emlxs_update_boot_wakeup_parms() */
975 
976 
977 
978 static uint32_t
979 emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
980     PROG_ID *prog_id)
981 {
982 	emlxs_port_t *port = &PPORT;
983 	uint32_t rval = 0;
984 	MAILBOXQ *mbox;
985 	MAILBOX *mb;
986 
987 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
988 	    KM_NOSLEEP)) == NULL) {
989 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
990 		    "Unable to allocate mailbox buffer.");
991 
992 		return (1);
993 	}
994 
995 	mb = (MAILBOX *)mbox;
996 
997 	WakeUpParms->prog_id = *prog_id;
998 
999 	emlxs_format_update_parms(mb, WakeUpParms);
1000 
1001 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1002 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1003 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
1004 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
1005 
1006 		rval = 1;
1007 	}
1008 
1009 	if (mbox) {
1010 		kmem_free(mbox, sizeof (MAILBOXQ));
1011 	}
1012 
1013 	return (rval);
1014 
1015 }  /* emlxs_update_ff_wakeup_parms() */
1016 
1017 
1018 static uint32_t
1019 emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1020     PROG_ID * prog_id)
1021 {
1022 	emlxs_port_t *port = &PPORT;
1023 	uint32_t rval = 0;
1024 	MAILBOXQ *mbox;
1025 	MAILBOX *mb;
1026 
1027 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1028 	    KM_NOSLEEP)) == NULL) {
1029 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1030 		    "Unable to allocate mailbox buffer.");
1031 
1032 		return (1);
1033 	}
1034 
1035 	mb = (MAILBOX *)mbox;
1036 
1037 	WakeUpParms->sli1_prog_id = *prog_id;
1038 
1039 	emlxs_format_update_parms(mb, WakeUpParms);
1040 
1041 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1042 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1043 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
1044 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
1045 
1046 		rval = 1;
1047 	}
1048 
1049 	if (mbox) {
1050 		kmem_free(mbox, sizeof (MAILBOXQ));
1051 	}
1052 
1053 	return (rval);
1054 
1055 }  /* emlxs_update_sli1_wakeup_parms() */
1056 
1057 
1058 static uint32_t
1059 emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1060     PROG_ID * prog_id)
1061 {
1062 	emlxs_port_t *port = &PPORT;
1063 	uint32_t rval = 0;
1064 	MAILBOXQ *mbox;
1065 	MAILBOX *mb;
1066 
1067 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1068 	    KM_NOSLEEP)) == NULL) {
1069 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1070 		    "Unable to allocate mailbox buffer.");
1071 
1072 		return (1);
1073 	}
1074 
1075 	mb = (MAILBOX *)mbox;
1076 
1077 	WakeUpParms->sli2_prog_id = *prog_id;
1078 
1079 	emlxs_format_update_parms(mb, WakeUpParms);
1080 
1081 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1082 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1083 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
1084 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
1085 
1086 		rval = 1;
1087 	}
1088 
1089 	if (mbox) {
1090 		kmem_free(mbox, sizeof (MAILBOXQ));
1091 	}
1092 
1093 	return (rval);
1094 
1095 }  /* emlxs_update_sli2_wakeup_parms() */
1096 
1097 
1098 static uint32_t
1099 emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1100     PROG_ID *prog_id)
1101 {
1102 	emlxs_port_t *port = &PPORT;
1103 	uint32_t rval = 0;
1104 	MAILBOXQ *mbox;
1105 	MAILBOX *mb;
1106 
1107 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1108 	    KM_NOSLEEP)) == NULL) {
1109 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1110 		    "Unable to allocate mailbox buffer.");
1111 
1112 		return (1);
1113 	}
1114 
1115 	mb = (MAILBOX *)mbox;
1116 
1117 	WakeUpParms->sli3_prog_id = *prog_id;
1118 
1119 	emlxs_format_update_parms(mb, WakeUpParms);
1120 
1121 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1122 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1123 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
1124 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
1125 
1126 		rval = 1;
1127 	}
1128 
1129 	if (mbox) {
1130 		kmem_free(mbox, sizeof (MAILBOXQ));
1131 	}
1132 
1133 	return (rval);
1134 
1135 }  /* emlxs_update_sli3_wakeup_parms() */
1136 
1137 
1138 static uint32_t
1139 emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1140     PROG_ID *prog_id)
1141 {
1142 	emlxs_port_t *port = &PPORT;
1143 	uint32_t rval = 0;
1144 	MAILBOXQ *mbox;
1145 	MAILBOX *mb;
1146 
1147 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1148 	    KM_NOSLEEP)) == NULL) {
1149 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1150 		    "Unable to allocate mailbox buffer.");
1151 
1152 		return (1);
1153 	}
1154 
1155 	mb = (MAILBOX *)mbox;
1156 
1157 	WakeUpParms->sli4_prog_id = *prog_id;
1158 
1159 	emlxs_format_update_parms(mb, WakeUpParms);
1160 
1161 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1162 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1163 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
1164 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
1165 
1166 		rval = 1;
1167 	}
1168 
1169 	if (mbox) {
1170 		kmem_free(mbox, sizeof (MAILBOXQ));
1171 	}
1172 
1173 	return (rval);
1174 
1175 }  /* emlxs_update_sli4_wakeup_parms() */
1176 
1177 
1178 /* ARGSUSED */
1179 static uint32_t
1180 emlxs_start_rel_download(emlxs_hba_t *hba,
1181     PIMAGE_HDR ImageHdr,
1182     caddr_t Buffer,
1183     PWAKE_UP_PARMS WakeUpParms,
1184     uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize)
1185 {
1186 	emlxs_port_t *port = &PPORT;
1187 	MAILBOXQ *mbox;
1188 	MAILBOX *mb;
1189 	uint32_t *Src;
1190 	uint32_t *Dst;
1191 	caddr_t DataBuffer = NULL;
1192 	uint32_t rval = 1;
1193 	uint32_t DlByteCount = ImageHdr->BlockSize;
1194 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
1195 	uint32_t DlCount;
1196 	uint32_t i;
1197 
1198 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1199 	    "Performing relative download...");
1200 
1201 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
1202 	    KM_NOSLEEP)) == NULL) {
1203 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1204 		    "Unable to allocate data buffer.");
1205 
1206 		return (rval);
1207 	}
1208 
1209 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1210 	    KM_NOSLEEP)) == NULL) {
1211 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1212 		    "Unable to allocate mailbox buffer.");
1213 
1214 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
1215 
1216 		return (rval);
1217 	}
1218 
1219 	if (ImageHdr->Id.Type == FUNC_FIRMWARE) {
1220 		switch (MaxRbusSramSize) {
1221 		case REDUCED_RBUS_SRAM_CFG:
1222 			if (ImageHdr->Id.Id != REDUCED_SRAM_CFG_PROG_ID) {
1223 				EMLXS_MSGF(EMLXS_CONTEXT,
1224 				    &emlxs_image_bad_msg,
1225 				    "Invalid header id.");
1226 
1227 				return (1);
1228 			}
1229 			break;
1230 		case FULL_RBUS_SRAM_CFG:
1231 			if (ImageHdr->Id.Id != FULL_SRAM_CFG_PROG_ID) {
1232 				EMLXS_MSGF(EMLXS_CONTEXT,
1233 				    &emlxs_image_bad_msg,
1234 				    "Invalid header id.");
1235 
1236 				return (1);
1237 			}
1238 			break;
1239 		default:
1240 			if (ImageHdr->Id.Id != OTHER_SRAM_CFG_PROG_ID) {
1241 				EMLXS_MSGF(EMLXS_CONTEXT,
1242 				    &emlxs_image_bad_msg,
1243 				    "Invalid header id.");
1244 
1245 				return (1);
1246 			}
1247 			break;
1248 		}
1249 	}
1250 
1251 	mb = (MAILBOX *)mbox;
1252 
1253 	emlxs_format_prog_flash(mb, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
1254 	    &ImageHdr->Id);
1255 
1256 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash...");
1257 
1258 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1259 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1260 		    "Unable to erase flash. Mailbox cmd=%x status=%x",
1261 		    mb->mbxCommand, mb->mbxStatus);
1262 
1263 		rval = 1;
1264 
1265 		goto EXIT_REL_DOWNLOAD;
1266 	}
1267 
1268 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1269 	    "Programming flash...");
1270 
1271 	while (DlByteCount) {
1272 		if (DlByteCount > SegSize) {
1273 			DlCount = SegSize;
1274 		} else {
1275 			DlCount = DlByteCount;
1276 		}
1277 		DlByteCount -= DlCount;
1278 
1279 		Dst = (uint32_t *)DataBuffer;
1280 		Src = (uint32_t *)Buffer;
1281 
1282 		for (i = 0; i < (DlCount / 4); i++) {
1283 			*Dst = *Src;
1284 			Dst++;
1285 			Src++;
1286 		}
1287 
1288 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
1289 		    (volatile uint32_t *)((volatile char *)hba->slim_addr +
1290 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
1291 
1292 		emlxs_format_prog_flash(mb,
1293 		    0,
1294 		    DlCount,
1295 		    PROGRAM_FLASH,
1296 		    (DlByteCount) ? 0 : 1, 0, DlCount, &ImageHdr->Id);
1297 
1298 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
1299 		    MBX_SUCCESS) {
1300 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1301 			    "Unable to program flash. Mailbox cmd=%x status=%x",
1302 			    mb->mbxCommand, mb->mbxStatus);
1303 
1304 			rval = 1;
1305 
1306 			goto EXIT_REL_DOWNLOAD;
1307 		}
1308 
1309 		Buffer += DlCount;
1310 	}
1311 
1312 #ifdef FMA_SUPPORT
1313 	if (emlxs_fm_check_acc_handle(hba, hba->slim_acc_handle)
1314 	    != DDI_FM_OK) {
1315 		EMLXS_MSGF(EMLXS_CONTEXT,
1316 		    &emlxs_invalid_access_handle_msg, NULL);
1317 
1318 		rval = 1;
1319 
1320 		goto EXIT_REL_DOWNLOAD;
1321 	}
1322 #endif  /* FMA_SUPPORT */
1323 
1324 	switch (ImageHdr->Id.Type) {
1325 	case TEST_PROGRAM:
1326 		rval = 0;
1327 		break;
1328 
1329 	case FUNC_FIRMWARE:
1330 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1331 		    "FF: Updating parms...");
1332 		rval =
1333 		    emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
1334 		    &ImageHdr->Id);
1335 		break;
1336 
1337 	case BOOT_BIOS:
1338 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1339 		    "BOOT: Updating parms...");
1340 		rval =
1341 		    emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
1342 		    &ImageHdr->Id, 1);
1343 		break;
1344 
1345 	case SLI1_OVERLAY:
1346 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1347 		    "SLI1: Updating parms...");
1348 		rval =
1349 		    emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
1350 		    &ImageHdr->Id);
1351 		break;
1352 
1353 	case SLI2_OVERLAY:
1354 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1355 		    "SLI2: Updating parms...");
1356 		rval =
1357 		    emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
1358 		    &ImageHdr->Id);
1359 		break;
1360 
1361 	case SLI3_OVERLAY:
1362 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1363 		    "SLI3: Updating parms...");
1364 		rval =
1365 		    emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
1366 		    &ImageHdr->Id);
1367 		break;
1368 
1369 	case SLI4_OVERLAY:
1370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1371 		    "SLI4: Updating parms...");
1372 		rval =
1373 		    emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
1374 		    &ImageHdr->Id);
1375 		break;
1376 
1377 	default:
1378 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1379 		    "Image type not supported. Type=%x", ImageHdr->Id.Type);
1380 
1381 		break;
1382 	}
1383 
1384 EXIT_REL_DOWNLOAD:
1385 	if (DataBuffer) {
1386 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
1387 	}
1388 
1389 	if (mbox) {
1390 		kmem_free(mbox, sizeof (MAILBOXQ));
1391 	}
1392 
1393 	return (rval);
1394 
1395 }  /* emlxs_start_rel_download() */
1396 
1397 
1398 #define	FLASH_POLLING_BIT	0x80
1399 #define	FLASH_ERROR_BIT		0x20
1400 
1401 typedef struct _flash_t
1402 {
1403 	uint32_t	offset;
1404 	uint8_t		val;
1405 } flash_t;
1406 
1407 
1408 
1409 static uint32_t
1410 emlxs_write_fcode_flash(emlxs_hba_t *hba,
1411     PIMAGE_HDR ImageHdr, caddr_t Buffer)
1412 {
1413 	emlxs_port_t *port = &PPORT;
1414 	uint8_t bb;
1415 	uint8_t cc;
1416 	uint8_t *src;
1417 	uint32_t DlByteCount = ImageHdr->BlockSize;
1418 	uint32_t i;
1419 	uint32_t j;
1420 	uint32_t k;
1421 
1422 	flash_t wr[3] = {
1423 		{0x555, 0xaa},
1424 		{0x2aa, 0x55},
1425 		{0x555, 0xa0}
1426 	};
1427 
1428 	/* Load Fcode */
1429 	src = (uint8_t *)Buffer + sizeof (IMAGE_HDR);
1430 	for (i = 0; i < DlByteCount; i++) {
1431 		for (k = 0; k < 3; k++) {
1432 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
1433 		}
1434 
1435 		/* Reverse Endian word alignment */
1436 		j = (i & 3) ^ 3;
1437 
1438 		bb = src[j];
1439 
1440 		if (j == 0) {
1441 			src += 4;
1442 		}
1443 
1444 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
1445 
1446 		/* check for complete */
1447 		for (;;) {
1448 			DELAYUS(20);
1449 
1450 			cc = SBUS_READ_FLASH_COPY(hba, i);
1451 
1452 			/* If data matches then continue */
1453 			if (cc == bb) {
1454 				break;
1455 			}
1456 
1457 			/* Polling bit will be inverse final value */
1458 			/* while active */
1459 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
1460 				/* Still busy */
1461 
1462 				/* Check for error bit */
1463 				if (cc & FLASH_ERROR_BIT) {
1464 					/* Read data one more time */
1465 					cc = SBUS_READ_FLASH_COPY(hba, i);
1466 
1467 					/* Check if data matches */
1468 					if (cc == bb) {
1469 						break;
1470 					}
1471 
1472 					EMLXS_MSGF(EMLXS_CONTEXT,
1473 					    &emlxs_download_failed_msg,
1474 					    "FCode write error: offset:%x "
1475 					    "wrote:%x read:%x\n", i, bb, cc);
1476 
1477 					return (1);
1478 				}
1479 			}
1480 		}
1481 	}
1482 
1483 	/* Load Header */
1484 	src = (uint8_t *)ImageHdr;
1485 
1486 	for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) {
1487 		for (k = 0; k < 3; k++) {
1488 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
1489 		}
1490 
1491 		/* Reverse Endian word alignment */
1492 		j = (i & 3) ^ 3;
1493 
1494 		bb = src[j];
1495 
1496 		if (j == 0) {
1497 			src += 4;
1498 		}
1499 
1500 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
1501 
1502 		/* check for complete */
1503 		for (;;) {
1504 			DELAYUS(20);
1505 
1506 			cc = SBUS_READ_FLASH_COPY(hba, i);
1507 
1508 			/* If data matches then continue */
1509 			if (cc == bb) {
1510 				break;
1511 			}
1512 
1513 			/* Polling bit will be inverse final value */
1514 			/* while active */
1515 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
1516 				/* Still busy */
1517 
1518 				/* Check for error bit */
1519 				if (cc & FLASH_ERROR_BIT) {
1520 					/* Read data one more time */
1521 					cc = SBUS_READ_FLASH_COPY(hba, i);
1522 
1523 					/* Check if data matches */
1524 					if (cc == bb) {
1525 						break;
1526 					}
1527 
1528 					EMLXS_MSGF(EMLXS_CONTEXT,
1529 					    &emlxs_download_failed_msg,
1530 					    "FCode write error: offset:%x "
1531 					    "wrote:%x read:%x\n", i, bb, cc);
1532 
1533 					return (1);
1534 				}
1535 			}
1536 		}
1537 	}
1538 
1539 #ifdef FMA_SUPPORT
1540 	if (emlxs_fm_check_acc_handle(hba, hba->sbus_flash_acc_handle)
1541 	    != DDI_FM_OK) {
1542 		EMLXS_MSGF(EMLXS_CONTEXT,
1543 		    &emlxs_invalid_access_handle_msg, NULL);
1544 		return (1);
1545 	}
1546 #endif  /* FMA_SUPPORT */
1547 
1548 	return (0);
1549 
1550 }  /* emlxs_write_fcode_flash() */
1551 
1552 
1553 
1554 static uint32_t
1555 emlxs_erase_fcode_flash(emlxs_hba_t *hba)
1556 {
1557 	emlxs_port_t *port = &PPORT;
1558 	int32_t i, j;
1559 	uint8_t cc;
1560 	uint32_t offset;
1561 
1562 	flash_t ef[6] = {
1563 		{0x555, 0xaa},
1564 		{0x2aa, 0x55},
1565 		{0x555, 0x80},
1566 		{0x555, 0xaa},
1567 		{0x2aa, 0x55},
1568 		{0x555, 0x10}
1569 	};
1570 
1571 	/* Auto select */
1572 	flash_t as[3] = {
1573 		{0x555, 0xaa},
1574 		{0x2aa, 0x55},
1575 		{0x555, 0x90}
1576 	};
1577 
1578 
1579 	/* Check Manufacturers Code */
1580 	for (i = 0; i < 3; i++) {
1581 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
1582 	}
1583 
1584 	cc = SBUS_READ_FLASH_COPY(hba, 0);
1585 
1586 	/* Check Device Code */
1587 	for (i = 0; i < 3; i++) {
1588 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
1589 	}
1590 
1591 	cc = SBUS_READ_FLASH_COPY(hba, 1);
1592 
1593 
1594 	/* Check block protections (up to 4 16K blocks = 64K) */
1595 	for (j = 0; j < 4; j++) {
1596 		for (i = 0; i < 3; i++) {
1597 			SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
1598 		}
1599 
1600 		offset = (j << 14) | 0x2;
1601 
1602 		cc = SBUS_READ_FLASH_COPY(hba, offset);
1603 
1604 		if (cc == 0x01) {
1605 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1606 			    "Block %d is protected and can't be erased.", j);
1607 		}
1608 	}
1609 
1610 	/* Write erase flash sequence */
1611 	for (i = 0; i < 6; i++) {
1612 		SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val);
1613 	}
1614 
1615 	/* check for complete */
1616 	for (;;) {
1617 		/* Delay 3 seconds */
1618 		DELAYMS(3000);
1619 
1620 		cc = SBUS_READ_FLASH_COPY(hba, 0);
1621 
1622 
1623 		/* If data matches then continue; */
1624 		if (cc == 0xff) {
1625 			break;
1626 		}
1627 
1628 		/* Polling bit will be inverse final value while active */
1629 		if ((cc ^ 0xff) & FLASH_POLLING_BIT) {
1630 			/* Still busy */
1631 
1632 			/* Check for error bit */
1633 			if (cc & FLASH_ERROR_BIT) {
1634 				/* Read data one more time */
1635 				cc = SBUS_READ_FLASH_COPY(hba, 0);
1636 
1637 				/* Check if data matches */
1638 				if (cc == 0xff) {
1639 					break;
1640 				}
1641 
1642 				EMLXS_MSGF(EMLXS_CONTEXT,
1643 				    &emlxs_download_failed_msg,
1644 				    "FCode write error: offset:%x wrote:%x "
1645 				    "read:%x\n", i, 0xff, cc);
1646 
1647 				return (1);
1648 			}
1649 		}
1650 	}
1651 
1652 #ifdef FMA_SUPPORT
1653 	if (emlxs_fm_check_acc_handle(hba, hba->sbus_flash_acc_handle)
1654 	    != DDI_FM_OK) {
1655 		EMLXS_MSGF(EMLXS_CONTEXT,
1656 		    &emlxs_invalid_access_handle_msg, NULL);
1657 		return (1);
1658 	}
1659 #endif  /* FMA_SUPPORT */
1660 
1661 	return (0);
1662 
1663 }  /* emlxs_erase_fcode_flash() */
1664 
1665 
1666 extern uint32_t
1667 emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
1668 {
1669 	emlxs_port_t *port = &PPORT;
1670 	LOAD_ENTRY *LoadEntry;
1671 	LOAD_LIST *LoadList = NULL;
1672 	uint32_t i;
1673 	uint32_t rval = 0;
1674 
1675 	bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
1676 
1677 	if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST),
1678 	    KM_NOSLEEP)) == NULL) {
1679 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1680 		    "Unable to allocate LOADLIST buffer.");
1681 
1682 		rval = 1;
1683 		goto done;
1684 	}
1685 
1686 	if (emlxs_read_load_list(hba, LoadList)) {
1687 		rval = 1;
1688 		goto done;
1689 	}
1690 
1691 	for (i = 0; i < LoadList->entry_cnt; i++) {
1692 		LoadEntry = &LoadList->load_entry[i];
1693 		if ((LoadEntry->un.wd[0] != 0) &&
1694 		    (LoadEntry->un.wd[0] != 0xffffffff)) {
1695 			load_list[i] = LoadEntry->un.id;
1696 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1697 			    "Load List[%d]: %08x %08x", i,
1698 			    LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
1699 		}
1700 	}
1701 
1702 done:
1703 
1704 	if (LoadList) {
1705 		kmem_free(LoadList, sizeof (LOAD_LIST));
1706 	}
1707 
1708 	return (rval);
1709 
1710 }  /* emlxs_get_load_list() */
1711 
1712 
1713 extern uint32_t
1714 emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1715     uint32_t verbose)
1716 {
1717 	emlxs_port_t *port = &PPORT;
1718 	MAILBOXQ *mbox;
1719 	MAILBOX *mb;
1720 	uint32_t rval = 0;
1721 	uint32_t *wd;
1722 
1723 	bzero(WakeUpParms, sizeof (WAKE_UP_PARMS));
1724 
1725 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1726 	    KM_NOSLEEP)) == NULL) {
1727 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1728 		    "Unable to allocate mailbox buffer.");
1729 
1730 		return (1);
1731 	}
1732 
1733 	mb = (MAILBOX *)mbox;
1734 
1735 	emlxs_format_dump(mb,
1736 	    DMP_NV_PARAMS,
1737 	    WAKE_UP_PARMS_REGION_ID,
1738 	    sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
1739 
1740 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1741 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1742 		    "Unable to get parameters: Mailbox cmd=%x status=%x",
1743 		    mb->mbxCommand, mb->mbxStatus);
1744 
1745 		if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) {
1746 			rval = (uint32_t)CFG_DATA_NO_REGION;
1747 		} else {
1748 			rval = 1;
1749 		}
1750 	} else {
1751 		bcopy((caddr_t)&mb->un.varDmp.resp_offset,
1752 		    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
1753 
1754 		if (verbose) {
1755 			wd = (uint32_t *)&WakeUpParms->prog_id;
1756 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1757 			    "Wakeup:      prog_id=%08x %08x", wd[0], wd[1]);
1758 
1759 			wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id;
1760 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1761 			    "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]);
1762 
1763 			wd = (uint32_t *)&WakeUpParms->sli1_prog_id;
1764 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1765 			    "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]);
1766 
1767 			wd = (uint32_t *)&WakeUpParms->sli2_prog_id;
1768 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1769 			    "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]);
1770 
1771 			wd = (uint32_t *)&WakeUpParms->sli3_prog_id;
1772 			if (wd[0] || wd[1]) {
1773 				EMLXS_MSGF(EMLXS_CONTEXT,
1774 				    &emlxs_init_debug_msg,
1775 				    "Wakeup: sli3_prog_id=%08x %08x", wd[0],
1776 				    wd[1]);
1777 			}
1778 
1779 			wd = (uint32_t *)&WakeUpParms->sli4_prog_id;
1780 			if (wd[0] || wd[1]) {
1781 				EMLXS_MSGF(EMLXS_CONTEXT,
1782 				    &emlxs_init_debug_msg,
1783 				    "Wakeup: sli4_prog_id=%08x %08x", wd[0],
1784 				    wd[1]);
1785 			}
1786 
1787 			wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id;
1788 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1789 			    "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]);
1790 
1791 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1792 			    "Wakeup: pci_cfg_rsvd=%x",
1793 			    WakeUpParms->pci_cfg_rsvd);
1794 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1795 			    "Wakeup:  use_hdw_def=%x",
1796 			    WakeUpParms->use_hdw_def);
1797 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1798 			    "Wakeup:  pci_cfg_sel=%x",
1799 			    WakeUpParms->pci_cfg_sel);
1800 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1801 			    "Wakeup:   cfg_lookup=%x",
1802 			    WakeUpParms->pci_cfg_lookup_sel);
1803 		}
1804 	}
1805 
1806 done:
1807 
1808 	if (mbox) {
1809 		kmem_free(mbox, sizeof (MAILBOXQ));
1810 	}
1811 
1812 	return (rval);
1813 
1814 }  /* emlxs_read_wakeup_parms() */
1815 
1816 
1817 static uint32_t
1818 emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
1819 {
1820 	emlxs_port_t *port = &PPORT;
1821 	LOAD_ENTRY *LoadEntry;
1822 	uint32_t *Uptr;
1823 	uint32_t CurEntryAddr;
1824 	MAILBOXQ *mbox = NULL;
1825 	MAILBOX *mb;
1826 
1827 	bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
1828 
1829 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1830 	    KM_NOSLEEP)) == NULL) {
1831 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1832 		    "Unable to allocate mailbox buffer.");
1833 
1834 		return (1);
1835 	}
1836 
1837 	mb = (MAILBOX *)mbox;
1838 
1839 	emlxs_format_dump(mb, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
1840 
1841 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
1842 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1843 		    "Unable to get load list: Mailbox cmd=%x status=%x",
1844 		    mb->mbxCommand, mb->mbxStatus);
1845 
1846 		goto done;
1847 	}
1848 
1849 	Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
1850 
1851 	LoadList->head = Uptr[0];
1852 	LoadList->tail = Uptr[1];
1853 
1854 	CurEntryAddr = LoadList->head;
1855 
1856 	while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
1857 	    (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
1858 		LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
1859 		LoadList->entry_cnt++;
1860 
1861 		emlxs_format_dump(mb,
1862 		    DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
1863 
1864 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
1865 		    MBX_SUCCESS) {
1866 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1867 			    "Unable to get load list (%d): Mailbox cmd=%x "
1868 			    "status=%x", LoadList->entry_cnt, mb->mbxCommand,
1869 			    mb->mbxStatus);
1870 
1871 			goto done;
1872 		}
1873 
1874 		Uptr = (uint32_t *)&(mb->un.varDmp.resp_offset);
1875 
1876 		LoadEntry->next = Uptr[0];
1877 		LoadEntry->prev = Uptr[1];
1878 		LoadEntry->start_adr = Uptr[2];
1879 		LoadEntry->len = Uptr[3];
1880 		LoadEntry->un.wd[0] = Uptr[4];
1881 		LoadEntry->un.wd[1] = Uptr[5];
1882 
1883 		/* update next current load entry address */
1884 		CurEntryAddr = LoadEntry->next;
1885 
1886 	}	/* end of while (not end of list) */
1887 
1888 done:
1889 
1890 	if (mbox) {
1891 		kmem_free(mbox, sizeof (MAILBOXQ));
1892 	}
1893 
1894 	return (0);
1895 
1896 }  /* emlxs_read_load_list() */
1897 
1898 
1899 
1900 
1901 static uint32_t
1902 emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize)
1903 {
1904 	uint32_t Version;
1905 
1906 	if (BufferSize < (SLI_VERSION_LOC + 4))
1907 		return (0xffffffff);
1908 
1909 	Buffer += SLI_VERSION_LOC;
1910 	Version = *((uint32_t *)Buffer);
1911 
1912 	return (Version);
1913 
1914 }  /* emlxs_get_abs_image_type() */
1915 
1916 
1917 static uint32_t
1918 emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer,
1919     uint32_t BufferSize, PAIF_HDR AifHeader)
1920 {
1921 	emlxs_port_t *port = &PPORT;
1922 	IMAGE_HDR ImageHdr;
1923 	uint32_t NextImage;
1924 	uint32_t i;
1925 	uint8_t *Sptr;
1926 	uint8_t *Dptr;
1927 	uint32_t HwId = 0xffffffff;
1928 
1929 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
1930 
1931 	while (BufferSize > NextImage) {
1932 		Sptr = (uint8_t *)&Buffer[NextImage];
1933 		Dptr = (uint8_t *)&ImageHdr;
1934 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
1935 			Dptr[i] = Sptr[i];
1936 		}
1937 
1938 		if (ImageHdr.BlockSize == 0xffffffff)
1939 			break;
1940 
1941 		switch (ImageHdr.Id.Type) {
1942 		case 6:
1943 		case 7:
1944 			if (HwId == 0xffffffff) {
1945 				HwId = ImageHdr.Id.Id;
1946 			}
1947 
1948 			if (HwId != ImageHdr.Id.Id) {
1949 				EMLXS_MSGF(EMLXS_CONTEXT,
1950 				    &emlxs_image_bad_msg,
1951 				    "Invalid hardware id. %x %x", HwId,
1952 				    ImageHdr.Id.Id);
1953 			}
1954 			break;
1955 		}
1956 
1957 		NextImage += ImageHdr.BlockSize;
1958 	}
1959 
1960 	return (HwId);
1961 
1962 }  /* emlxs_get_dwc_image_type() */
1963 
1964 
1965 static int
1966 emlxs_build_parms(caddr_t Buffer,
1967     PWAKE_UP_PARMS AbsWakeUpParms,
1968     uint32_t BufferSize, PAIF_HDR AifHeader, int32_t DwcFile)
1969 {
1970 	IMAGE_HDR ImageHdr;
1971 	uint32_t NextImage;
1972 	uint32_t i;
1973 	int32_t ChangeParams = FALSE;
1974 	caddr_t Sptr;
1975 	caddr_t Dptr;
1976 
1977 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
1978 
1979 	if (!DwcFile && ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
1980 		return (FALSE);
1981 	}
1982 
1983 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
1984 
1985 	while (BufferSize > NextImage) {
1986 		Sptr = &Buffer[NextImage];
1987 		Dptr = (caddr_t)&ImageHdr;
1988 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
1989 			Dptr[i] = Sptr[i];
1990 		}
1991 
1992 		if (ImageHdr.BlockSize == 0xffffffff)
1993 			break;
1994 
1995 		switch (ImageHdr.Id.Type) {
1996 		case TEST_PROGRAM:
1997 			break;
1998 		case FUNC_FIRMWARE:
1999 			AbsWakeUpParms->prog_id = ImageHdr.Id;
2000 			ChangeParams = TRUE;
2001 			break;
2002 		case BOOT_BIOS:
2003 			AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
2004 			ChangeParams = TRUE;
2005 			break;
2006 		case SLI1_OVERLAY:
2007 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
2008 			ChangeParams = TRUE;
2009 			break;
2010 		case SLI2_OVERLAY:
2011 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
2012 			ChangeParams = TRUE;
2013 			break;
2014 		case SLI3_OVERLAY:
2015 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
2016 			ChangeParams = TRUE;
2017 			break;
2018 		case SLI4_OVERLAY:
2019 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
2020 			ChangeParams = TRUE;
2021 			break;
2022 		default:
2023 			break;
2024 		}
2025 
2026 		NextImage += ImageHdr.BlockSize;
2027 	}
2028 
2029 	return (ChangeParams);
2030 
2031 }  /* emlxs_build_parms() */
2032 
2033 
2034 static uint32_t
2035 emlxs_update_wakeup_parms(emlxs_hba_t *hba,
2036     PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
2037 {
2038 	emlxs_port_t *port = &PPORT;
2039 	MAILBOX *mb;
2040 	MAILBOXQ *mbox;
2041 	uint32_t rval = 0;
2042 
2043 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2044 	    KM_NOSLEEP)) == NULL) {
2045 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2046 		    "Unable to allocate mailbox buffer.");
2047 
2048 		return (1);
2049 	}
2050 
2051 	mb = (MAILBOX *)mbox;
2052 
2053 	WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
2054 	WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
2055 	WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
2056 	WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
2057 	WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
2058 	WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
2059 
2060 	emlxs_format_update_parms(mb, WakeUpParms);
2061 
2062 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
2063 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2064 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
2065 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2066 
2067 		rval = 1;
2068 	}
2069 
2070 	if (mbox) {
2071 		kmem_free(mbox, sizeof (MAILBOXQ));
2072 	}
2073 
2074 	return (rval);
2075 
2076 }  /* emlxs_update_wakeup_parms() */
2077 
2078 
2079 static uint32_t
2080 emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
2081     uint32_t type, char *file_type)
2082 {
2083 	emlxs_port_t *port = &PPORT;
2084 
2085 	/* Create the version label */
2086 	emlxs_decode_version(file->version, file->label);
2087 
2088 	/* Process the DWC type */
2089 	switch (type) {
2090 	case TEST_PROGRAM:
2091 
2092 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2093 		    "%s: TEST: offset=%08x  version=%08x, %s", file_type,
2094 		    file->offset, file->version, file->label);
2095 
2096 		break;
2097 
2098 	case BOOT_BIOS:
2099 
2100 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2101 		    "%s: BOOT: offset=%08x  version=%08x, %s", file_type,
2102 		    file->offset, file->version, file->label);
2103 
2104 		if (!emlxs_bios_check(hba, id)) {
2105 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2106 			    "BOOT Check: Image not compatible with %s. id=%02x",
2107 			    hba->model_info.model, id);
2108 
2109 			return (EMLXS_IMAGE_INCOMPATIBLE);
2110 		}
2111 
2112 		break;
2113 
2114 	case FUNC_FIRMWARE:	/* Stub */
2115 
2116 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2117 		    "%s: STUB: offset=%08x  version=%08x, %s", file_type,
2118 		    file->offset, file->version, file->label);
2119 
2120 		if (!emlxs_stub_check(hba, id)) {
2121 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2122 			    "STUB Check: Image not compatible with %s. id=%02x",
2123 			    hba->model_info.model, id);
2124 
2125 			return (EMLXS_IMAGE_INCOMPATIBLE);
2126 		}
2127 
2128 		break;
2129 
2130 	case SLI1_OVERLAY:
2131 
2132 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2133 		    "%s: SLI1: offset=%08x  version=%08x, %s", file_type,
2134 		    file->offset, file->version, file->label);
2135 
2136 		if (!emlxs_sli1_check(hba, id)) {
2137 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2138 			    "SLI1 Check: Image not compatible with %s. id=%02x",
2139 			    hba->model_info.model, id);
2140 
2141 			return (EMLXS_IMAGE_INCOMPATIBLE);
2142 		}
2143 
2144 		break;
2145 
2146 	case SLI2_OVERLAY:
2147 
2148 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2149 		    "%s: SLI2: offset=%08x  version=%08x, %s", file_type,
2150 		    file->offset, file->version, file->label);
2151 
2152 		if (!emlxs_sli2_check(hba, id)) {
2153 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2154 			    "SLI2 Check: Image not compatible with %s. id=%02x",
2155 			    hba->model_info.model, id);
2156 
2157 			return (EMLXS_IMAGE_INCOMPATIBLE);
2158 		}
2159 
2160 		break;
2161 
2162 	case SLI3_OVERLAY:
2163 
2164 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2165 		    "%s: SLI3: offset=%08x  version=%08x, %s", file_type,
2166 		    file->offset, file->version, file->label);
2167 
2168 		if (!emlxs_sli3_check(hba, id)) {
2169 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2170 			    "SLI3 Check: Image not compatible with %s. id=%02x",
2171 			    hba->model_info.model, id);
2172 
2173 			return (EMLXS_IMAGE_INCOMPATIBLE);
2174 		}
2175 
2176 		break;
2177 
2178 	case SLI4_OVERLAY:
2179 
2180 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2181 		    "%s: SLI4: offset=%08x  version=%08x, %s", file_type,
2182 		    file->offset, file->version, file->label);
2183 
2184 		if (!emlxs_sli4_check(hba, id)) {
2185 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2186 			    "SLI4 Check: Image not compatible with %s. id=%02x",
2187 			    hba->model_info.model, id);
2188 
2189 			return (EMLXS_IMAGE_INCOMPATIBLE);
2190 		}
2191 
2192 		break;
2193 
2194 	case SBUS_FCODE:
2195 
2196 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2197 		    "%s: SBUS FCODE: offset=%08x  version=%08x, %s",
2198 		    file_type, file->offset, file->version, file->label);
2199 
2200 		if (!emlxs_sbus_fcode_check(hba, id)) {
2201 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2202 			    "SBUS FCODE Check: Image not compatible with %s. "
2203 			    "id=%02x", hba->model_info.model, id);
2204 
2205 			return (EMLXS_IMAGE_INCOMPATIBLE);
2206 		}
2207 
2208 		break;
2209 
2210 	case KERNEL_CODE:
2211 
2212 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2213 		    "%s: KERN: offset=%08x  version=%08x, %s", file_type,
2214 		    file->offset, file->version, file->label);
2215 
2216 		if (!emlxs_kern_check(hba, id)) {
2217 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2218 			    "KERN Check: Image not compatible with %s. id=%02x",
2219 			    hba->model_info.model, id);
2220 
2221 			return (EMLXS_IMAGE_INCOMPATIBLE);
2222 		}
2223 
2224 		break;
2225 
2226 	default:
2227 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2228 		    "%s: Image type not supported. type=%x", file_type, type);
2229 
2230 		return (EMLXS_IMAGE_BAD);
2231 	}
2232 
2233 	return (0);
2234 
2235 }  /* emlxs_validate_version() */
2236 
2237 
2238 static uint32_t
2239 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
2240     emlxs_fw_image_t *image)
2241 {
2242 	emlxs_port_t *port = &PPORT;
2243 	uint32_t ImageType;
2244 	AIF_HDR AifHdr;
2245 	IMAGE_HDR ImageHdr;
2246 	uint32_t NextImage;
2247 	uint32_t FileType;
2248 	uint32_t FileLen = 0;
2249 	uint32_t TotalLen = 0;
2250 	uint32_t *CkSumEnd;
2251 	uint32_t id;
2252 	uint32_t type;
2253 	uint32_t ver;
2254 	uint32_t ImageLength;
2255 	uint32_t BufferSize;
2256 	uint32_t rval = 0;
2257 	caddr_t bptr;
2258 	emlxs_vpd_t *vpd;
2259 
2260 	vpd = &VPD;
2261 
2262 	/* Get image type */
2263 	ImageType = *((uint32_t *)Buffer);
2264 
2265 	/* Pegasus and beyond adapters */
2266 	if ((ImageType == NOP_IMAGE_TYPE) &&
2267 	    !(hba->model_info.chip &
2268 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2269 		bptr = Buffer;
2270 		TotalLen = sizeof (uint32_t);
2271 
2272 		while (TotalLen < Size) {
2273 			if (Size < sizeof (AIF_HDR)) {
2274 				EMLXS_MSGF(EMLXS_CONTEXT,
2275 				    &emlxs_image_bad_msg,
2276 				    "Invalid image header length: 0x%x < 0x%x",
2277 				    Size, sizeof (AIF_HDR));
2278 
2279 				return (EMLXS_IMAGE_BAD);
2280 			}
2281 
2282 			bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
2283 			emlxs_disp_aif_header(hba, &AifHdr);
2284 
2285 			ImageLength = AifHdr.RoSize;
2286 
2287 			/* Validate checksum */
2288 			CkSumEnd =
2289 			    (uint32_t *)(bptr + ImageLength +
2290 			    sizeof (AIF_HDR));
2291 			if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
2292 				EMLXS_MSGF(EMLXS_CONTEXT,
2293 				    &emlxs_image_bad_msg,
2294 				    "Invalid checksum found.");
2295 
2296 				return (EMLXS_IMAGE_BAD);
2297 			}
2298 
2299 			FileType = AifHdr.ZinitBr;
2300 			switch (FileType) {
2301 			case FILE_TYPE_AWC:
2302 				image->awc.offset =
2303 				    (uint32_t)((uintptr_t)bptr -
2304 				    (uintptr_t)Buffer);
2305 				image->awc.version = AifHdr.AVersion;
2306 				image->awc.revcomp = 0;
2307 
2308 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
2309 				type = emlxs_type_check(
2310 				    (AifHdr.AVersion & 0xff000000) >> 24);
2311 
2312 				/* Validate the file version */
2313 				if ((rval = emlxs_validate_version(hba,
2314 				    &image->awc, id, type, "AWC file"))) {
2315 					return (rval);
2316 				}
2317 
2318 				break;
2319 
2320 			case FILE_TYPE_BWC:
2321 				image->bwc.offset =
2322 				    (uint32_t)((uintptr_t)bptr -
2323 				    (uintptr_t)Buffer);
2324 				image->bwc.version = AifHdr.AVersion;
2325 				image->bwc.revcomp = 0;
2326 
2327 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
2328 				type = emlxs_type_check(
2329 				    (AifHdr.AVersion & 0xff000000) >> 24);
2330 
2331 				/* Validate the file version */
2332 				if ((rval = emlxs_validate_version(hba,
2333 				    &image->bwc, id, type, "BWC file"))) {
2334 					return (rval);
2335 				}
2336 
2337 				break;
2338 
2339 			case FILE_TYPE_DWC:
2340 				image->dwc.offset =
2341 				    (uint32_t)((uintptr_t)bptr -
2342 				    (uintptr_t)Buffer);
2343 				image->dwc.version = AifHdr.AVersion;
2344 				image->dwc.revcomp = 0;
2345 
2346 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
2347 				type = emlxs_type_check(
2348 				    (AifHdr.AVersion & 0xff000000) >> 24);
2349 
2350 				/* Validate the file version */
2351 				if ((rval = emlxs_validate_version(hba,
2352 				    &image->dwc, id, type, "DWC file"))) {
2353 					return (rval);
2354 				}
2355 
2356 				/* Scan for program types */
2357 				NextImage = sizeof (AIF_HDR) + 4;
2358 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
2359 
2360 				while (BufferSize > NextImage) {
2361 					bcopy(&bptr[NextImage], &ImageHdr,
2362 					    sizeof (IMAGE_HDR));
2363 					emlxs_dump_image_header(hba,
2364 					    &ImageHdr);
2365 
2366 					/* Validate block size */
2367 					if (ImageHdr.BlockSize == 0xffffffff) {
2368 						break;
2369 					}
2370 
2371 					type = emlxs_type_check(
2372 					    ImageHdr.Id.Type);
2373 
2374 					/* Calculate the program offset */
2375 					image->prog[type].offset =
2376 					    (uint32_t)((uintptr_t)
2377 					    &bptr[NextImage] -
2378 					    (uintptr_t)Buffer);
2379 
2380 					/* Acquire the versions */
2381 					image->prog[type].version =
2382 					    (ImageHdr.Id.Type << 24) |
2383 					    (ImageHdr.Id.Id << 16) |
2384 					    (ImageHdr.Id.Ver << 8) |
2385 					    ImageHdr.Id.Rev;
2386 
2387 					image->prog[type].revcomp =
2388 					    ImageHdr.Id.un.revcomp;
2389 
2390 					/* Validate the file version */
2391 					if ((rval = emlxs_validate_version(hba,
2392 					    &image->prog[type], ImageHdr.Id.Id,
2393 					    type, "DWC prog"))) {
2394 						return (rval);
2395 					}
2396 
2397 					NextImage += ImageHdr.BlockSize;
2398 
2399 				}	/* while() */
2400 
2401 				break;
2402 			}
2403 
2404 			FileLen =
2405 			    sizeof (AIF_HDR) + ImageLength +
2406 			    sizeof (uint32_t);
2407 			TotalLen += FileLen;
2408 			bptr += FileLen;
2409 		}
2410 	}
2411 
2412 	/* Pre-pegasus adapters */
2413 
2414 	else if (ImageType == NOP_IMAGE_TYPE) {
2415 		if (Size < sizeof (AIF_HDR)) {
2416 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2417 			    "Invalid image header length: 0x%x < 0x%x", Size,
2418 			    sizeof (AIF_HDR));
2419 
2420 			return (EMLXS_IMAGE_BAD);
2421 		}
2422 
2423 		bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
2424 		emlxs_disp_aif_header(hba, &AifHdr);
2425 
2426 		ImageLength = AifHdr.RoSize + AifHdr.RwSize;
2427 
2428 		if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
2429 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2430 			    "Image length incorrect: 0x%x != 0x%x", Size,
2431 			    sizeof (AIF_HDR) + ImageLength +
2432 			    sizeof (uint32_t));
2433 
2434 			return (EMLXS_IMAGE_BAD);
2435 		}
2436 
2437 		if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
2438 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2439 			    "Invalid imageBase value %x != 0x20000",
2440 			    AifHdr.ImageBase);
2441 
2442 			return (EMLXS_IMAGE_BAD);
2443 		}
2444 
2445 		CkSumEnd =
2446 		    (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
2447 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
2448 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2449 			    "Invalid checksum found.");
2450 
2451 			return (EMLXS_IMAGE_BAD);
2452 		}
2453 
2454 		image->dwc.offset = 0;
2455 		image->dwc.version = AifHdr.AVersion;
2456 		image->dwc.revcomp = 0;
2457 
2458 		id = (AifHdr.AVersion & 0x00ff0000) >> 16;
2459 		type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
2460 
2461 		/* Validate the file version */
2462 		if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
2463 		    "DWC file"))) {
2464 			return (rval);
2465 		}
2466 
2467 		NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
2468 		while (Size > NextImage) {
2469 			bcopy(&Buffer[NextImage], &ImageHdr,
2470 			    sizeof (IMAGE_HDR));
2471 			emlxs_dump_image_header(hba, &ImageHdr);
2472 
2473 			/* Validate block size */
2474 			if (ImageHdr.BlockSize == 0xffffffff) {
2475 				break;
2476 			}
2477 
2478 			type = emlxs_type_check(ImageHdr.Id.Type);
2479 
2480 			/* Calculate the program offset */
2481 			image->prog[type].offset = NextImage;
2482 
2483 			/* Acquire the versions */
2484 			image->prog[type].version =
2485 			    (ImageHdr.Id.Type << 24) |
2486 			    (ImageHdr.Id.Id << 16) |
2487 			    (ImageHdr.Id.Ver << 8) |
2488 			    ImageHdr.Id.Rev;
2489 
2490 			image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
2491 
2492 			/* Validate the file version */
2493 			if ((rval = emlxs_validate_version(hba,
2494 			    &image->prog[type], ImageHdr.Id.Id, type,
2495 			    "DWC prog"))) {
2496 				return (rval);
2497 			}
2498 
2499 			NextImage += ImageHdr.BlockSize;
2500 		}
2501 	} else {
2502 		/* Precheck image size */
2503 		if (Size < sizeof (IMAGE_HDR)) {
2504 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2505 			    "Invalid image header length: 0x%x < 0x%x", Size,
2506 			    sizeof (IMAGE_HDR));
2507 
2508 			return (EMLXS_IMAGE_BAD);
2509 		}
2510 
2511 		bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
2512 		emlxs_dump_image_header(hba, &ImageHdr);
2513 
2514 		/* Validate block size */
2515 		if (ImageHdr.BlockSize == 0xffffffff) {
2516 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2517 			    "Invalid block size.");
2518 
2519 			return (EMLXS_IMAGE_BAD);
2520 		}
2521 
2522 		ImageLength = ImageHdr.BlockSize;
2523 
2524 		/* Validate image length */
2525 		if (Size != ImageLength) {
2526 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2527 			    "Invalid image length: 0x%x != 0x%x", Size,
2528 			    ImageLength);
2529 
2530 			return (EMLXS_IMAGE_BAD);
2531 		}
2532 
2533 		/* Validate Checksum */
2534 		CkSumEnd =
2535 		    (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
2536 		    1;
2537 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
2538 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2539 			    "Invalid checksum found.");
2540 
2541 			return (EMLXS_IMAGE_BAD);
2542 		}
2543 
2544 		type = emlxs_type_check(ImageHdr.Id.Type);
2545 
2546 		/* Calculate the program offset */
2547 		image->prog[type].offset = 0;
2548 
2549 		/* Acquire the versions */
2550 		image->prog[type].version =
2551 		    (ImageHdr.Id.Type << 24) | (ImageHdr.Id.
2552 		    Id << 16) | (ImageHdr.Id.Ver << 8) | ImageHdr.Id.Rev;
2553 
2554 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
2555 
2556 		/* Validate the file version */
2557 		if ((rval = emlxs_validate_version(hba, &image->prog[type],
2558 		    ImageHdr.Id.Id, type, "DWC file"))) {
2559 			return (rval);
2560 		}
2561 	}
2562 
2563 	/*
2564 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
2565 	 * image file is greater than version 3.8
2566 	 */
2567 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
2568 		if (image->prog[SLI2_OVERLAY].version != 0) {
2569 			ver = (image->prog[SLI2_OVERLAY].version &
2570 			    0x0000ff00) >> 8;
2571 
2572 			if ((((ver & 0xf0) == 0x30) &&
2573 			    ((ver & 0x0f) >= 0x08)) ||
2574 			    ((ver & 0xf0) > 0x30)) {
2575 				EMLXS_MSGF(EMLXS_CONTEXT,
2576 				    &emlxs_image_incompat_msg,
2577 				    "ASIC Check: Image requires DragonFly "
2578 				    "V2 ASIC");
2579 
2580 				return (EMLXS_IMAGE_INCOMPATIBLE);
2581 			}
2582 		}
2583 	}
2584 
2585 	return (0);
2586 
2587 }  /* emlxs_validate_image() */
2588 
2589 
2590 static uint32_t
2591 emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
2592 {
2593 	emlxs_port_t *port = &PPORT;
2594 	MAILBOXQ *mbox;
2595 	MAILBOX *mb;
2596 	uint32_t next_address;
2597 	uint32_t rval = 0;
2598 
2599 	if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
2600 		return (1);
2601 	}
2602 
2603 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2604 	    KM_NOSLEEP)) == NULL) {
2605 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2606 		    "Unable to allocate mailbox buffer.");
2607 
2608 		return (1);
2609 	}
2610 
2611 	bzero(mbox, sizeof (MAILBOXQ));
2612 
2613 	mb = (MAILBOX *)mbox;
2614 	mb->mbxCommand = MBX_LOAD_EXP_ROM;
2615 	mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
2616 	mb->un.varLdExpRom.progress = 0;
2617 	mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
2618 
2619 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
2620 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2621 		    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
2622 		    mb->mbxCommand, mb->mbxStatus);
2623 
2624 		rval = 1;
2625 
2626 		goto SLI_DOWNLOAD_EXIT;
2627 	}
2628 
2629 	if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
2630 		(void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
2631 
2632 		rval = 1;
2633 		goto SLI_DOWNLOAD_EXIT;
2634 	}
2635 
2636 	if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
2637 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2638 		    "Invalid exp ROM progress. progress=%x",
2639 		    mb->un.varLdExpRom.progress);
2640 
2641 		rval = 1;
2642 
2643 		goto SLI_DOWNLOAD_EXIT;
2644 	}
2645 
2646 	/*
2647 	 * continue Erase
2648 	 */
2649 	while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
2650 
2651 		next_address = mb->un.varLdExpRom.dl_to_adr;
2652 
2653 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
2654 
2655 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
2656 		mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
2657 		mb->un.varLdExpRom.dl_to_adr = next_address;
2658 		mb->un.varLdExpRom.progress = 0;
2659 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
2660 
2661 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
2662 		    MBX_SUCCESS) {
2663 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2664 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
2665 			    mb->mbxCommand, mb->mbxStatus);
2666 
2667 			rval = 1;
2668 			goto SLI_DOWNLOAD_EXIT;
2669 		}
2670 
2671 	}
2672 
2673 	while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
2674 		next_address = mb->un.varLdExpRom.dl_to_adr;
2675 
2676 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
2677 
2678 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
2679 		mb->un.varLdExpRom.step = EROM_CMD_COPY;
2680 		mb->un.varLdExpRom.dl_to_adr = next_address;
2681 		mb->un.varLdExpRom.progress = 0;
2682 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
2683 
2684 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
2685 		    MBX_SUCCESS) {
2686 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2687 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
2688 			    mb->mbxCommand, mb->mbxStatus);
2689 
2690 			rval = 1;
2691 
2692 			goto SLI_DOWNLOAD_EXIT;
2693 		}
2694 	}
2695 
2696 	rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
2697 
2698 SLI_DOWNLOAD_EXIT:
2699 
2700 	if (mbox) {
2701 		kmem_free(mbox, sizeof (MAILBOXQ));
2702 	}
2703 
2704 	return (rval);
2705 
2706 }  /* emlxs_update_exp_rom() */
2707 
2708 
2709 /*
2710  *
2711  * FUNCTION NAME: emlxs_start_abs_download_2mb
2712  *
2713  * DESCRIPTION: Perform absolute download for 2 MB flash.  A incoming
2714  *              buffer may consist of more than 1 file.  This function
2715  *              will parse the buffer to find all the files.
2716  *
2717  *
2718  * PARAMETERS:
2719  *
2720  *
2721  * RETURNS:
2722  *
2723  */
2724 /* ARGSUSED */
2725 static uint32_t
2726 emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
2727     uint32_t offline, emlxs_fw_image_t *fw_image)
2728 {
2729 	emlxs_port_t *port = &PPORT;
2730 	caddr_t AwcBuffer = NULL;
2731 	caddr_t BwcBuffer = NULL;
2732 	caddr_t DwcBuffer = NULL;
2733 	AIF_HDR *AwcAifHdr;
2734 	AIF_HDR *BwcAifHdr;
2735 	AIF_HDR *DwcAifHdr;
2736 	uint32_t BWCflag;
2737 	emlxs_vpd_t *vpd;
2738 	uint32_t i;
2739 	uint32_t count;
2740 	uint32_t extType = 0;
2741 	uint32_t rval = 0;
2742 
2743 	vpd = &VPD;
2744 
2745 	/* Check for AWC file */
2746 	if (fw_image->awc.version) {
2747 		AwcBuffer = buffer + fw_image->awc.offset;
2748 		AwcAifHdr = (AIF_HDR *)AwcBuffer;
2749 	}
2750 
2751 	/* Check for BWC file */
2752 	if (fw_image->bwc.version) {
2753 		extType = BWCext;
2754 		BwcBuffer = buffer + fw_image->bwc.offset;
2755 		BwcAifHdr = (AIF_HDR *)BwcBuffer;
2756 	}
2757 
2758 	/* Check for DWC file */
2759 	if (fw_image->dwc.version) {
2760 		extType = DWCext;
2761 		DwcBuffer = buffer + fw_image->dwc.offset;
2762 		DwcAifHdr = (AIF_HDR *)DwcBuffer;
2763 	}
2764 
2765 	/* Check for program files */
2766 	count = 0;
2767 	for (i = 0; i < MAX_PROG_TYPES; i++) {
2768 		if (fw_image->prog[i].version) {
2769 			count++;
2770 		}
2771 	}
2772 
2773 	if (count > 1) {
2774 		extType = ALLext;
2775 
2776 		if (fw_image->bwc.version) {
2777 			BWCflag = ALL_WITH_BWC;
2778 		} else {
2779 			BWCflag = ALL_WITHOUT_BWC;
2780 		}
2781 	} else {
2782 		BWCflag = NO_ALL;
2783 	}
2784 
2785 	/* If nothing to download then quit now */
2786 	if (!AwcBuffer && !DwcBuffer && !BwcBuffer) {
2787 		return (0);
2788 	}
2789 
2790 	/*
2791 	 * Everything checks out, now to just do it
2792 	 */
2793 	if (offline) {
2794 		if (emlxs_offline(hba) != FC_SUCCESS) {
2795 			return (EMLXS_OFFLINE_FAILED);
2796 		}
2797 
2798 		if (emlxs_sli_hba_reset(hba, 1, 1) != FC_SUCCESS) {
2799 			return (EMLXS_OFFLINE_FAILED);
2800 		}
2801 	}
2802 
2803 	if (AwcBuffer) {
2804 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2805 		    "AWC file: KERN: old=%s  new=%s ", vpd->postKernName,
2806 		    fw_image->awc.label);
2807 
2808 		rval = emlxs_proc_abs_2mb(hba,
2809 		    AwcAifHdr, AwcBuffer, FILE_TYPE_AWC, BWCflag, extType);
2810 
2811 		if (rval) {
2812 			goto SLI_DOWNLOAD_2MB_EXIT;
2813 		}
2814 	}
2815 
2816 	if (DwcBuffer) {
2817 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2818 		    "DWC file: TEST:             new=%s ",
2819 		    fw_image->prog[TEST_PROGRAM].label);
2820 
2821 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2822 		    "DWC file: STUB: old=%s  new=%s ", vpd->opFwName,
2823 		    fw_image->prog[FUNC_FIRMWARE].label);
2824 
2825 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2826 		    "DWC file: SLI1: old=%s  new=%s ", vpd->sli1FwName,
2827 		    fw_image->prog[SLI1_OVERLAY].label);
2828 
2829 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2830 		    "DWC file: SLI2: old=%s  new=%s ", vpd->sli2FwName,
2831 		    fw_image->prog[SLI2_OVERLAY].label);
2832 
2833 		if (vpd->sli3FwRev || fw_image->prog[SLI3_OVERLAY].version) {
2834 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2835 			    "DWC file: SLI3: old=%s  new=%s ",
2836 			    vpd->sli3FwName,
2837 			    fw_image->prog[SLI3_OVERLAY].label);
2838 		}
2839 
2840 		if (vpd->sli4FwRev || fw_image->prog[SLI4_OVERLAY].version) {
2841 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2842 			    "DWC file: SLI4: old=%s  new=%s ",
2843 			    vpd->sli4FwName,
2844 			    fw_image->prog[SLI4_OVERLAY].label);
2845 		}
2846 
2847 		rval = emlxs_proc_abs_2mb(hba,
2848 		    DwcAifHdr, DwcBuffer, FILE_TYPE_DWC, BWCflag, extType);
2849 
2850 		if (rval) {
2851 			goto SLI_DOWNLOAD_2MB_EXIT;
2852 		}
2853 	}
2854 
2855 	if (BwcBuffer) {
2856 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2857 		    "BWC file: BOOT: old=%s  new=%s ", vpd->fcode_version,
2858 		    fw_image->bwc.label);
2859 
2860 		rval = emlxs_proc_abs_2mb(hba,
2861 		    BwcAifHdr, BwcBuffer, FILE_TYPE_BWC, BWCflag, extType);
2862 	}
2863 
2864 SLI_DOWNLOAD_2MB_EXIT:
2865 
2866 	if (offline) {
2867 		(void) emlxs_online(hba);
2868 	}
2869 
2870 	return (rval);
2871 
2872 }  /* emlxs_start_abs_download_2mb() */
2873 
2874 
2875 /*
2876  *
2877  * FUNCTION NAME: emlxs_proc_abs_2mb
2878  *
2879  * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
2880  *              the port and download the file with sliIssueMbCommand()
2881  *
2882  *
2883  * PARAMETERS:
2884  *
2885  *
2886  * RETURNS:
2887  *
2888  */
2889 static uint32_t
2890 emlxs_proc_abs_2mb(emlxs_hba_t *hba,
2891     PAIF_HDR AifHdr,
2892     caddr_t EntireBuffer,
2893     uint32_t FileType, uint32_t BWCflag, uint32_t extType)
2894 {
2895 	emlxs_port_t *port = &PPORT;
2896 	caddr_t Buffer = NULL;
2897 	caddr_t DataBuffer = NULL;
2898 	uint32_t *Src;
2899 	uint32_t *Dst;
2900 	MAILBOXQ *mbox;
2901 	MAILBOX *mb;
2902 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
2903 	uint32_t rval = 0;
2904 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
2905 	uint32_t DlToAddr = AifHdr->ImageBase;
2906 	uint32_t DlCount;
2907 	WAKE_UP_PARMS AbsWakeUpParms;
2908 	uint32_t i;
2909 	uint32_t NextAddr;
2910 	uint32_t EraseByteCount;
2911 	uint32_t AreaId;
2912 	uint32_t RspProgress = 0;
2913 	uint32_t numBootImage = 0;
2914 	uint32_t ParamsChg = 0;
2915 	uint32_t BufferSize;
2916 
2917 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
2918 	    KM_NOSLEEP)) == NULL) {
2919 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2920 		    "%x: Unable to allocate data buffer.", FileType);
2921 
2922 		return (EMLXS_IMAGE_FAILED);
2923 	}
2924 
2925 	bzero(DataBuffer, sizeof (DL_SLIM_SEG_BYTE_COUNT));
2926 
2927 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2928 	    KM_NOSLEEP)) == NULL) {
2929 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2930 		    "%x: Unable to allocate mailbox buffer.", FileType);
2931 
2932 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2933 
2934 		return (EMLXS_IMAGE_FAILED);
2935 	}
2936 
2937 	mb = (MAILBOX *)mbox;
2938 
2939 	BufferSize = DlByteCount + sizeof (AIF_HDR) + sizeof (uint32_t);
2940 	Buffer = EntireBuffer + sizeof (AIF_HDR);
2941 
2942 	switch (FileType) {
2943 	case FILE_TYPE_AWC:
2944 		break;
2945 
2946 	case FILE_TYPE_BWC:
2947 		ParamsChg = emlxs_build_parms_2mb_bwc(hba,
2948 		    AifHdr, extType, &AbsWakeUpParms);
2949 
2950 		if (ParamsChg == FALSE) {
2951 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2952 			    "BWC build parms failed.");
2953 
2954 			rval = EMLXS_IMAGE_FAILED;
2955 
2956 			goto EXIT_ABS_DOWNLOAD;
2957 		}
2958 		break;
2959 
2960 	case FILE_TYPE_DWC:
2961 		ParamsChg = emlxs_build_parms_2mb_dwc(hba,
2962 		    Buffer,
2963 		    BufferSize,
2964 		    AifHdr, &AbsWakeUpParms, BWCflag, extType, &numBootImage);
2965 
2966 		if (ParamsChg == FALSE) {
2967 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2968 			    "DWC build parms failed.");
2969 
2970 			rval = EMLXS_IMAGE_FAILED;
2971 
2972 			goto EXIT_ABS_DOWNLOAD;
2973 		}
2974 		break;
2975 
2976 	default:
2977 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2978 		    "Invalid file type: %x", FileType);
2979 
2980 		rval = EMLXS_IMAGE_BAD;
2981 
2982 		goto EXIT_ABS_DOWNLOAD;
2983 
2984 	}
2985 
2986 	EraseByteCount = AifHdr->Area_Size;
2987 	AreaId = AifHdr->Area_ID;
2988 
2989 	emlxs_format_load_area_cmd(mb,
2990 	    DlToAddr,
2991 	    EraseByteCount,
2992 	    ERASE_FLASH,
2993 	    0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
2994 
2995 	if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) {
2996 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2997 		    "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
2998 		    FileType, mb->mbxCommand, mb->mbxStatus);
2999 
3000 		rval = EMLXS_IMAGE_FAILED;
3001 
3002 		goto EXIT_ABS_DOWNLOAD;
3003 	}
3004 
3005 	while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
3006 		NextAddr = mb->un.varLdArea.dl_to_adr;
3007 
3008 		emlxs_format_load_area_cmd(mb,
3009 		    NextAddr,
3010 		    EraseByteCount,
3011 		    ERASE_FLASH,
3012 		    0,
3013 		    DL_FROM_SLIM_OFFSET,
3014 		    AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
3015 
3016 		if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
3017 		    MBX_SUCCESS) {
3018 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3019 			    "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
3020 			    "status=%x", FileType, mb->mbxCommand,
3021 			    mb->mbxStatus);
3022 
3023 			rval = EMLXS_IMAGE_FAILED;
3024 
3025 			goto EXIT_ABS_DOWNLOAD;
3026 		}
3027 	}
3028 
3029 	while (DlByteCount) {
3030 		if (DlByteCount >= SegSize)
3031 			DlCount = SegSize;
3032 		else
3033 			DlCount = DlByteCount;
3034 
3035 		DlByteCount -= DlCount;
3036 
3037 		Dst = (uint32_t *)DataBuffer;
3038 		Src = (uint32_t *)Buffer;
3039 
3040 		for (i = 0; i < (DlCount / 4); i++) {
3041 			*Dst = *Src;
3042 			Dst++;
3043 			Src++;
3044 		}
3045 
3046 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
3047 		    (volatile uint32_t *)((volatile char *)hba->slim_addr +
3048 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
3049 
3050 		if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
3051 			emlxs_format_load_area_cmd(mb,
3052 			    DlToAddr,
3053 			    DlCount,
3054 			    PROGRAM_FLASH,
3055 			    (DlByteCount) ? 0 : 1,
3056 			    DL_FROM_SLIM_OFFSET,
3057 			    AreaId,
3058 			    MBX_LOAD_AREA,
3059 			    (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
3060 
3061 			if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) !=
3062 			    MBX_SUCCESS) {
3063 				EMLXS_MSGF(EMLXS_CONTEXT,
3064 				    &emlxs_download_failed_msg,
3065 				    "%x: Could not program 2MB Flash: Mailbox "
3066 				    "cmd=%x status=%x", FileType,
3067 				    mb->mbxCommand, mb->mbxStatus);
3068 
3069 				rval = EMLXS_IMAGE_FAILED;
3070 
3071 				goto EXIT_ABS_DOWNLOAD;
3072 			}
3073 		}
3074 
3075 		RspProgress = mb->un.varLdArea.progress;
3076 
3077 		Buffer += DlCount;
3078 		DlToAddr += DlCount;
3079 	}
3080 
3081 #ifdef FMA_SUPPORT
3082 	if (emlxs_fm_check_acc_handle(hba, hba->slim_acc_handle)
3083 	    != DDI_FM_OK) {
3084 		EMLXS_MSGF(EMLXS_CONTEXT,
3085 		    &emlxs_invalid_access_handle_msg, NULL);
3086 
3087 		rval = EMLXS_IMAGE_FAILED;
3088 
3089 		goto EXIT_ABS_DOWNLOAD;
3090 	}
3091 #endif  /* FMA_SUPPORT */
3092 
3093 	if (RspProgress != RSP_DOWNLOAD_DONE) {
3094 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3095 		    "%x: Failed download response received. %x", FileType,
3096 		    RspProgress);
3097 
3098 		rval = EMLXS_IMAGE_FAILED;
3099 
3100 		goto EXIT_ABS_DOWNLOAD;
3101 	}
3102 
3103 	if (ParamsChg) {
3104 		if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
3105 		    &AbsWakeUpParms)) {
3106 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3107 			    "%x: Unable to update parms.", FileType);
3108 
3109 			rval = EMLXS_IMAGE_FAILED;
3110 		}
3111 	}
3112 
3113 EXIT_ABS_DOWNLOAD:
3114 
3115 	if (DataBuffer) {
3116 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
3117 	}
3118 
3119 	if (mbox) {
3120 		kmem_free(mbox, sizeof (MAILBOXQ));
3121 	}
3122 
3123 	return (rval);
3124 
3125 }  /* emlxs_proc_abs_2mb() */
3126 
3127 
3128 static void
3129 emlxs_format_load_area_cmd(MAILBOX * mb,
3130     uint32_t Base,
3131     uint32_t DlByteCount,
3132     uint32_t Function,
3133     uint32_t Complete,
3134     uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
3135 {
3136 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
3137 
3138 	mb->mbxCommand = MbxCmd;
3139 	mb->mbxOwner = OWN_HOST;
3140 	mb->un.varLdArea.update_flash = 1;
3141 	mb->un.varLdArea.erase_or_prog = Function;
3142 	mb->un.varLdArea.dl_to_adr = Base;
3143 	mb->un.varLdArea.dl_len = DlByteCount;
3144 	mb->un.varLdArea.load_cmplt = Complete;
3145 	mb->un.varLdArea.method = DL_FROM_SLIM;
3146 	mb->un.varLdArea.area_id = AreaId;
3147 	mb->un.varLdArea.step = StepCmd;
3148 	mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
3149 
3150 }  /* emlxs_format_load_area_cmd() */
3151 
3152 
3153 /* ARGSUSED */
3154 static uint32_t
3155 emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
3156     PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
3157 {
3158 	emlxs_port_t *port = &PPORT;
3159 	uint32_t pId[2];
3160 	uint32_t returnStat;
3161 
3162 	/* Read wakeup paramters */
3163 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
3164 	    CFG_DATA_NO_REGION) {
3165 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3166 		    "Unable to get BWC parameters.");
3167 		return (FALSE);
3168 	}
3169 
3170 	pId[0] = AifHdr->AVersion;
3171 	pId[1] = 0;
3172 
3173 	if (extType == BWCext) {
3174 		AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
3175 		AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
3176 		AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
3177 		AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
3178 	}
3179 
3180 	else if (extType == ALLext) {
3181 		if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
3182 			/* case of EROM inactive */
3183 			AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
3184 			AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
3185 		} else {
3186 			/* case of EROM active */
3187 			if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
3188 				/* same ID */
3189 				AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
3190 				AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
3191 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
3192 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
3193 			} else {
3194 				/* different ID */
3195 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
3196 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
3197 
3198 				returnStat =
3199 				    emlxs_update_exp_rom(hba, AbsWakeUpParms);
3200 
3201 				if (returnStat) {
3202 					AbsWakeUpParms->u0.boot_bios_wd[0] =
3203 					    pId[0];
3204 					AbsWakeUpParms->u0.boot_bios_wd[1] =
3205 					    pId[1];
3206 				}
3207 			}
3208 		}
3209 	}
3210 
3211 	return (TRUE);
3212 
3213 }  /* emlxs_build_parms_2mb_bwc() */
3214 
3215 
3216 /* ARGSUSED */
3217 static uint32_t
3218 emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba,
3219     caddr_t Buffer,
3220     uint32_t BufferSize,
3221     PAIF_HDR AifHeader,
3222     PWAKE_UP_PARMS AbsWakeUpParms,
3223     uint32_t BWCflag, uint32_t extType, uint32_t *numBootImage)
3224 {
3225 	emlxs_port_t *port = &PPORT;
3226 	uint32_t NextImage;
3227 	uint32_t i;
3228 	IMAGE_HDR ImageHdr;
3229 	uint32_t *ptr1;
3230 	uint32_t *ptr2;
3231 	PROG_ID BootId[MAX_BOOTID];
3232 	uint32_t ChangeParams = FALSE;
3233 	WAKE_UP_PARMS WakeUpParms;
3234 	caddr_t Sptr;
3235 	caddr_t Dptr;
3236 
3237 	bzero(&BootId, (sizeof (PROG_ID)) * MAX_BOOTID);
3238 
3239 	/* Read wakeup paramters */
3240 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
3241 	    CFG_DATA_NO_REGION) {
3242 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3243 		    "Unable to get DWC parameters.");
3244 		return (FALSE);
3245 	}
3246 
3247 	bcopy((caddr_t)AbsWakeUpParms, (caddr_t)&WakeUpParms,
3248 	    sizeof (WAKE_UP_PARMS));
3249 
3250 	if (((BWCflag == ALL_WITHOUT_BWC) || (extType == DWCext)) &&
3251 	    (WakeUpParms.u0.boot_bios_wd[0])) {
3252 		*numBootImage = 0;
3253 	}
3254 
3255 	/* incoming buffer is without aif header */
3256 	NextImage = 0x84 - sizeof (AIF_HDR);
3257 	BufferSize -= (sizeof (AIF_HDR) + sizeof (uint32_t));
3258 
3259 	while (BufferSize > NextImage) {
3260 		Sptr = &Buffer[NextImage];
3261 		Dptr = (caddr_t)&ImageHdr;
3262 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
3263 			Dptr[i] = Sptr[i];
3264 		}
3265 
3266 		if (ImageHdr.BlockSize == 0xffffffff) {
3267 			break;
3268 		}
3269 
3270 		switch (ImageHdr.Id.Type) {
3271 		case TEST_PROGRAM:
3272 			break;
3273 
3274 		case FUNC_FIRMWARE:
3275 			AbsWakeUpParms->prog_id = ImageHdr.Id;
3276 			ChangeParams = TRUE;
3277 			break;
3278 
3279 		case BOOT_BIOS:
3280 			if (!WakeUpParms.u0.boot_bios_wd[0]) {
3281 				if (extType == DWCext) {
3282 					break;
3283 				} else if (BWCflag == ALL_WITHOUT_BWC) {
3284 					/* for possible future changes */
3285 					break;
3286 				}
3287 			}
3288 			ChangeParams = TRUE;
3289 
3290 			if (*numBootImage < MAX_BOOTID) {
3291 				BootId[*numBootImage] = ImageHdr.Id;
3292 				(*numBootImage)++;
3293 			}
3294 			break;
3295 
3296 		case SLI1_OVERLAY:
3297 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
3298 			ChangeParams = TRUE;
3299 			break;
3300 
3301 		case SLI2_OVERLAY:
3302 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
3303 			ChangeParams = TRUE;
3304 			break;
3305 
3306 		case SLI3_OVERLAY:
3307 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
3308 			ChangeParams = TRUE;
3309 			break;
3310 
3311 		case SLI4_OVERLAY:
3312 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
3313 			ChangeParams = TRUE;
3314 			break;
3315 		}
3316 
3317 		NextImage += ImageHdr.BlockSize;
3318 	}
3319 
3320 	if ((ChangeParams) && ((BWCflag == ALL_WITHOUT_BWC) ||
3321 	    (extType == DWCext))) {
3322 
3323 		if (*numBootImage > 1) {
3324 			for (i = 0; i < *numBootImage; i++) {
3325 				ptr1 =
3326 				    (uint32_t *)&WakeUpParms.u0.
3327 				    boot_bios_id;
3328 				ptr2 = (uint32_t *)&BootId[i];
3329 
3330 				if (ptr1[0] == ptr2[0]) {
3331 					AbsWakeUpParms->u1.EROM_prog_id =
3332 					    BootId[i];
3333 					(void) emlxs_update_exp_rom(hba,
3334 					    AbsWakeUpParms);
3335 					break;
3336 				}
3337 			}
3338 		} else {
3339 			if (*numBootImage == 1) {
3340 				ptr2 = (uint32_t *)&BootId[0];
3341 
3342 				if (WakeUpParms.u0.boot_bios_wd[0] == ptr2[0]) {
3343 					AbsWakeUpParms->u1.EROM_prog_id =
3344 					    BootId[0];
3345 					(void) emlxs_update_exp_rom(hba,
3346 					    AbsWakeUpParms);
3347 				}
3348 			}
3349 		}
3350 	}
3351 
3352 	return (ChangeParams);
3353 
3354 
3355 }  /* emlxs_build_parms_2mb_dwc() */
3356 
3357 
3358 extern uint32_t
3359 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
3360     uint32_t *MaxIbusSize)
3361 {
3362 	emlxs_port_t *port = &PPORT;
3363 	MAILBOXQ *mbox;
3364 	MAILBOX *mb;
3365 	uint32_t *Uptr;
3366 	uint32_t rval = 0;
3367 
3368 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3369 	    KM_NOSLEEP)) == NULL) {
3370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3371 		    "Unable to allocate mailbox buffer.");
3372 
3373 		return (1);
3374 	}
3375 
3376 	mb = (MAILBOX *)mbox;
3377 
3378 	emlxs_format_dump(mb, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
3379 
3380 	if ((rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0)) !=
3381 	    MBX_SUCCESS) {
3382 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3383 		    "Unable to get SRAM size: Mailbox cmd=%x status=%x",
3384 		    mb->mbxCommand, mb->mbxStatus);
3385 
3386 		rval = 1;
3387 
3388 		goto Exit_Function;
3389 	}
3390 
3391 	Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
3392 
3393 	*MaxRbusSize = Uptr[0];
3394 	*MaxIbusSize = Uptr[1];
3395 
3396 Exit_Function:
3397 
3398 	if (mbox) {
3399 		kmem_free(mbox, sizeof (MAILBOXQ));
3400 	}
3401 
3402 	return (rval);
3403 
3404 }  /* emlxs_get_max_sram() */
3405 
3406 
3407 static uint32_t
3408 emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
3409 {
3410 	uint8_t *ptr;
3411 	uint8_t ver;
3412 
3413 	ver = version & 0xff;
3414 	ptr = hba->model_info.pt_FF;
3415 
3416 	while (*ptr) {
3417 		if (*ptr++ == ver) {
3418 			return (1);
3419 		}
3420 	}
3421 
3422 	return (0);
3423 
3424 }  /* emlxs_kern_check() */
3425 
3426 static uint32_t
3427 emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
3428 {
3429 	uint8_t *ptr;
3430 	uint8_t ver;
3431 
3432 	ver = version & 0xff;
3433 	ptr = hba->model_info.pt_2;
3434 
3435 	while (*ptr) {
3436 		if (*ptr++ == ver) {
3437 			return (1);
3438 		}
3439 	}
3440 
3441 	return (0);
3442 
3443 }  /* emlxs_stub_check() */
3444 
3445 static uint32_t
3446 emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
3447 {
3448 	uint8_t *ptr;
3449 	uint8_t ver;
3450 
3451 	ver = version & 0xff;
3452 	ptr = hba->model_info.pt_3;
3453 
3454 	while (*ptr) {
3455 		if (*ptr++ == ver) {
3456 			return (1);
3457 		}
3458 	}
3459 
3460 	return (0);
3461 
3462 }  /* emlxs_bios_check() */
3463 
3464 static uint32_t
3465 emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
3466 {
3467 	uint8_t *ptr;
3468 	uint8_t ver;
3469 
3470 	ver = version & 0xff;
3471 	ptr = hba->model_info.pt_6;
3472 
3473 	while (*ptr) {
3474 		if (*ptr++ == ver) {
3475 			return (1);
3476 		}
3477 	}
3478 
3479 	return (0);
3480 
3481 }  /* emlxs_sli1_check() */
3482 
3483 static uint32_t
3484 emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version)
3485 {
3486 	uint8_t *ptr;
3487 	uint8_t ver;
3488 
3489 	ver = version & 0xff;
3490 	ptr = hba->model_info.pt_7;
3491 
3492 	while (*ptr) {
3493 		if (*ptr++ == ver) {
3494 			return (1);
3495 		}
3496 	}
3497 
3498 	return (0);
3499 
3500 }  /* emlxs_sli2_check() */
3501 
3502 static uint32_t
3503 emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
3504 {
3505 	uint8_t *ptr;
3506 	uint8_t ver;
3507 
3508 	ver = version & 0xff;
3509 	ptr = hba->model_info.pt_B;
3510 
3511 	while (*ptr) {
3512 		if (*ptr++ == ver) {
3513 			return (1);
3514 		}
3515 	}
3516 
3517 	return (0);
3518 
3519 }  /* emlxs_sli3_check() */
3520 
3521 
3522 static uint32_t
3523 emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
3524 {
3525 	uint8_t *ptr;
3526 	uint8_t ver;
3527 
3528 	ver = version & 0xff;
3529 	ptr = hba->model_info.pt_E;
3530 
3531 	while (*ptr) {
3532 		if (*ptr++ == ver) {
3533 			return (1);
3534 		}
3535 	}
3536 
3537 	return (0);
3538 
3539 }  /* emlxs_sli4_check() */
3540 
3541 
3542 static uint32_t
3543 emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
3544 {
3545 	uint8_t *ptr;
3546 	uint8_t ver;
3547 
3548 	ver = version & 0xff;
3549 	ptr = hba->model_info.pt_A;
3550 
3551 	while (*ptr) {
3552 		if (*ptr++ == ver) {
3553 			return (1);
3554 		}
3555 	}
3556 
3557 	return (0);
3558 
3559 }  /* emlxs_sbus_fcode_check() */
3560 
3561 static uint32_t
3562 emlxs_type_check(uint32_t type)
3563 {
3564 	if (type == 0xff) {
3565 		return (KERNEL_CODE);
3566 	}
3567 
3568 	if (type >= MAX_PROG_TYPES) {
3569 		return (RESERVED_D);
3570 	}
3571 
3572 	return (type);
3573 
3574 }  /* emlxs_type_check() */
3575 
3576 
3577 
3578 extern int32_t
3579 emlxs_boot_code_disable(emlxs_hba_t *hba)
3580 {
3581 	emlxs_port_t *port = &PPORT;
3582 	PROG_ID Id;
3583 	emlxs_vpd_t *vpd;
3584 
3585 	vpd = &VPD;
3586 
3587 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
3588 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3589 		    "emlxs_boot_code_disable: Unable to read wake up parms.");
3590 
3591 		return (FC_FAILURE);
3592 	}
3593 
3594 	/* Check if boot code is already disabled */
3595 	if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
3596 		return (FC_SUCCESS);
3597 	}
3598 
3599 	/* Make sure EROM entry has copy of boot bios entry */
3600 	if (!(hba->model_info.chip &
3601 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
3602 	    (hba->wakeup_parms.u0.boot_bios_wd[0] !=
3603 	    hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
3604 	    (hba->wakeup_parms.u0.boot_bios_wd[1] !=
3605 	    hba->wakeup_parms.u1.EROM_prog_wd[1])) {
3606 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
3607 		    &hba->wakeup_parms.u0.boot_bios_id, 1);
3608 	}
3609 
3610 	/* Update the bios id with a zero id */
3611 	/* Don't load the EROM this time */
3612 	bzero(&Id, sizeof (PROG_ID));
3613 	(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0);
3614 
3615 	/* Now read the parms again to verify */
3616 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
3617 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
3618 	    vpd->boot_version);
3619 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
3620 
3621 	/* Return the result */
3622 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
3623 	    FC_SUCCESS : FC_FAILURE);
3624 
3625 }  /* emlxs_boot_code_disable() */
3626 
3627 
3628 extern int32_t
3629 emlxs_boot_code_enable(emlxs_hba_t *hba)
3630 {
3631 	emlxs_port_t *port = &PPORT;
3632 	emlxs_vpd_t *vpd;
3633 	PROG_ID load_list[MAX_LOAD_ENTRY];
3634 	uint32_t i;
3635 
3636 	vpd = &VPD;
3637 
3638 	/* Read the wakeup parms */
3639 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
3640 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3641 		    "emlxs_boot_code_enable: Unable to read wake up parms.");
3642 
3643 		return (FC_FAILURE);
3644 	}
3645 
3646 	/* Check if boot code is already enabled */
3647 	if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
3648 		return (FC_SUCCESS);
3649 	}
3650 
3651 	if (!(hba->model_info.chip &
3652 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
3653 		if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) {
3654 			return (EMLXS_NO_BOOT_CODE);
3655 		}
3656 
3657 		/* Update the parms with the boot image id */
3658 		/* Don't load the EROM this time */
3659 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
3660 		    &hba->wakeup_parms.u1.EROM_prog_id, 0);
3661 	} else {	/* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
3662 
3663 		if (emlxs_get_load_list(hba, load_list)) {
3664 			return (FC_FAILURE);
3665 		}
3666 
3667 		/* Scan load list for a boot image */
3668 		for (i = 0; i < MAX_LOAD_ENTRY; i++) {
3669 			if (load_list[i].Type == BOOT_BIOS) {
3670 				/* Update the parms with the boot image id */
3671 				/* Don't load the EROM this time */
3672 				(void) emlxs_update_boot_wakeup_parms(hba,
3673 				    &hba->wakeup_parms, &load_list[i], 0);
3674 
3675 				break;
3676 			}
3677 		}
3678 
3679 		if (i == MAX_LOAD_ENTRY) {
3680 			return (EMLXS_NO_BOOT_CODE);
3681 		}
3682 	}
3683 
3684 	/* Now read the parms again to verify */
3685 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
3686 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
3687 	    vpd->boot_version);
3688 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
3689 
3690 	/* return the result */
3691 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
3692 	    FC_SUCCESS : FC_FAILURE);
3693 
3694 }  /* emlxs_boot_code_enable() */
3695 
3696 
3697 
3698 extern int32_t
3699 emlxs_boot_code_state(emlxs_hba_t *hba)
3700 {
3701 	emlxs_port_t *port = &PPORT;
3702 
3703 	/* Read the wakeup parms */
3704 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
3705 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
3706 		    "emlxs_boot_code_state: Unable to read wake up parms.");
3707 
3708 		return (FC_FAILURE);
3709 	}
3710 
3711 	/* return the result */
3712 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
3713 	    FC_SUCCESS : FC_FAILURE);
3714 
3715 }  /* emlxs_boot_code_state() */
3716