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