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