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