1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
236a573d82SSukumar Swaminathan  * Copyright 2010 Emulex.  All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
2782527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C);
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte #define	MAX_BOOTID	10
34fcf3ce44SJohn Forte 
35291a2b48SSukumar Swaminathan static uint32_t	emlxs_erase_fcode_flash(emlxs_hba_t *hba);
3682527734SSukumar Swaminathan 
37291a2b48SSukumar Swaminathan static uint32_t	emlxs_write_fcode_flash(emlxs_hba_t *hba,
38291a2b48SSukumar Swaminathan 			PIMAGE_HDR ImageHdr, caddr_t Buffer);
39fcf3ce44SJohn Forte 
40291a2b48SSukumar Swaminathan static int32_t	emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
416a573d82SSukumar Swaminathan 			uint32_t BufferSize, PAIF_HDR AifHeader);
42291a2b48SSukumar Swaminathan static uint32_t	emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
43291a2b48SSukumar Swaminathan 			uint32_t Size, emlxs_fw_image_t *fw_image);
4482527734SSukumar Swaminathan static void	emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq,
4582527734SSukumar Swaminathan 			uint32_t Type, uint32_t RegionId, uint32_t WordCnt,
4682527734SSukumar Swaminathan 			uint32_t BaseAddr);
47291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
486a573d82SSukumar Swaminathan 			caddr_t Buffer, uint32_t len,
496a573d82SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
50291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
51291a2b48SSukumar Swaminathan 			uint32_t len, uint32_t offline,
52291a2b48SSukumar Swaminathan 			emlxs_fw_image_t *fw_image);
536a573d82SSukumar Swaminathan static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba,
54291a2b48SSukumar Swaminathan 			caddr_t EntireBuffer, uint32_t FileType,
556a573d82SSukumar Swaminathan 			uint32_t extType);
5682527734SSukumar Swaminathan static void	emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base,
57291a2b48SSukumar Swaminathan 			uint32_t DlByteCount, uint32_t Function,
58291a2b48SSukumar Swaminathan 			uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
59291a2b48SSukumar Swaminathan 			uint8_t MbxCmd, uint32_t StepCmd);
60291a2b48SSukumar Swaminathan static uint32_t	emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
61291a2b48SSukumar Swaminathan 			uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
62291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_exp_rom(emlxs_hba_t *hba,
63291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
64291a2b48SSukumar Swaminathan extern uint32_t	emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
65291a2b48SSukumar Swaminathan 			uint32_t *MaxIbusSize);
6682527734SSukumar Swaminathan static void	emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base,
67291a2b48SSukumar Swaminathan 			uint32_t DlByteCount, uint32_t Function,
68291a2b48SSukumar Swaminathan 			uint32_t Complete, uint32_t BdeAddress,
696a573d82SSukumar Swaminathan 			uint32_t BdeSize, PROG_ID *ProgId, uint32_t keep);
7082527734SSukumar Swaminathan static void	emlxs_format_update_parms(MAILBOXQ *mbq,
71291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
7282527734SSukumar Swaminathan static void	emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
73291a2b48SSukumar Swaminathan 			uint32_t region_id, uint32_t size);
74291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_wakeup_parms(emlxs_hba_t *hba,
75291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS AbsWakeUpParms,
76291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
77291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba,
78291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id,
79291a2b48SSukumar Swaminathan 			uint32_t proc_erom);
80291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba,
81291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
82291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba,
83291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
84291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba,
85291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
86291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba,
87291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
88291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba,
89291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
90291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
91291a2b48SSukumar Swaminathan 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
926a573d82SSukumar Swaminathan 			uint32_t dwc_flag);
93291a2b48SSukumar Swaminathan static uint32_t	emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
94fcf3ce44SJohn Forte 
95291a2b48SSukumar Swaminathan static uint32_t	emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
9682527734SSukumar Swaminathan 
97291a2b48SSukumar Swaminathan static void	emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr);
9882527734SSukumar Swaminathan 
99291a2b48SSukumar Swaminathan static void	emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
10082527734SSukumar Swaminathan 
101*a9800bebSGarrett D'Amore 
102291a2b48SSukumar Swaminathan static uint32_t	emlxs_type_check(uint32_t type);
10382527734SSukumar Swaminathan 
104291a2b48SSukumar Swaminathan static uint32_t	emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
10582527734SSukumar Swaminathan 
106291a2b48SSukumar Swaminathan static uint32_t	emlxs_stub_check(emlxs_hba_t *hba, uint32_t version);
10782527734SSukumar Swaminathan 
108291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version);
10982527734SSukumar Swaminathan 
110291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version);
11182527734SSukumar Swaminathan 
112291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version);
11382527734SSukumar Swaminathan 
114291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version);
11582527734SSukumar Swaminathan 
116291a2b48SSukumar Swaminathan static uint32_t	emlxs_bios_check(emlxs_hba_t *hba, uint32_t version);
11782527734SSukumar Swaminathan 
118291a2b48SSukumar Swaminathan static uint32_t	emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version);
11982527734SSukumar Swaminathan 
120291a2b48SSukumar Swaminathan static uint32_t	emlxs_validate_version(emlxs_hba_t *hba,
121291a2b48SSukumar Swaminathan 			emlxs_fw_file_t *file, uint32_t id, uint32_t type,
122291a2b48SSukumar Swaminathan 			char *file_type);
123*a9800bebSGarrett D'Amore static uint32_t emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
12482527734SSukumar Swaminathan 			uint32_t len, emlxs_be_fw_image_t *fw_image);
125*a9800bebSGarrett D'Amore static uint32_t emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
126*a9800bebSGarrett D'Amore 			uint32_t len, emlxs_be_fw_image_t *fw_image);
127*a9800bebSGarrett D'Amore 
128*a9800bebSGarrett D'Amore 
12982527734SSukumar Swaminathan static int32_t emlxs_sli4_verify_crc(emlxs_hba_t *hba,
13082527734SSukumar Swaminathan 			emlxs_be_fw_file_t *file,
13182527734SSukumar Swaminathan 			MAILBOXQ *mbq, MATCHMAP *mp);
13282527734SSukumar Swaminathan static int32_t emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
13382527734SSukumar Swaminathan 			emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp);
13482527734SSukumar Swaminathan static int32_t emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer,
13582527734SSukumar Swaminathan 			uint32_t len, uint32_t offline);
136*a9800bebSGarrett D'Amore static uint32_t emlxs_be_version(caddr_t buffer, uint32_t size,
137*a9800bebSGarrett D'Amore 			uint32_t *plus_flag);
1386a573d82SSukumar Swaminathan static uint32_t emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer,
1396a573d82SSukumar Swaminathan 			emlxs_fw_image_t *fw_image);
1406a573d82SSukumar Swaminathan static uint32_t emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId);
1416a573d82SSukumar Swaminathan 
1426a573d82SSukumar Swaminathan static void emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *image);
1436a573d82SSukumar Swaminathan 
1446a573d82SSukumar Swaminathan static uint32_t emlxs_clean_flash(emlxs_hba_t *hba,
1456a573d82SSukumar Swaminathan 			PWAKE_UP_PARMS OldWakeUpParms,
1466a573d82SSukumar Swaminathan 			PWAKE_UP_PARMS NewWakeUpParms);
1476a573d82SSukumar Swaminathan 
148291a2b48SSukumar Swaminathan /* ************************************************************************* */
149fcf3ce44SJohn Forte 
150fcf3ce44SJohn Forte extern int32_t
151fcf3ce44SJohn Forte emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
152fcf3ce44SJohn Forte     uint32_t offline)
153fcf3ce44SJohn Forte {
154fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
155fcf3ce44SJohn Forte 	uint32_t *Uptr;
156fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
157fcf3ce44SJohn Forte 	AIF_HDR AifHdr;
158fcf3ce44SJohn Forte 	uint32_t ImageType;
159fcf3ce44SJohn Forte 	WAKE_UP_PARMS WakeUpParms;
160fcf3ce44SJohn Forte 	uint32_t rval = 0;
161fcf3ce44SJohn Forte 	emlxs_fw_image_t fw_image;
162fcf3ce44SJohn Forte 	uint32_t i;
163fcf3ce44SJohn Forte 
16482527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
165fcf3ce44SJohn Forte 	caddr_t local_buffer;
166fcf3ce44SJohn Forte 	uint32_t *bptr1;
167fcf3ce44SJohn Forte 	uint32_t *bptr2;
16882527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
16982527734SSukumar Swaminathan 
17082527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
17182527734SSukumar Swaminathan 		rval = emlxs_sli4_fw_download(hba, buffer, len, offline);
17282527734SSukumar Swaminathan 		return (rval);
17382527734SSukumar Swaminathan 	}
174fcf3ce44SJohn Forte 
175fcf3ce44SJohn Forte 	if (buffer == NULL || len == 0) {
176fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
177fcf3ce44SJohn Forte 	}
17882527734SSukumar Swaminathan 
17982527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
180fcf3ce44SJohn Forte 	/* We need to swap the image buffer before we start */
181fcf3ce44SJohn Forte 
182fcf3ce44SJohn Forte 	/*
183fcf3ce44SJohn Forte 	 * Use KM_SLEEP to allocate a temporary buffer
184fcf3ce44SJohn Forte 	 */
185fcf3ce44SJohn Forte 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 	/* Perform a 32 bit swap of the image */
188fcf3ce44SJohn Forte 	bptr1 = (uint32_t *)local_buffer;
189fcf3ce44SJohn Forte 	bptr2 = (uint32_t *)buffer;
190fcf3ce44SJohn Forte 	for (i = 0; i < (len / 4); i++) {
19182527734SSukumar Swaminathan 		*bptr1 = LE_SWAP32(*bptr2);
192fcf3ce44SJohn Forte 		bptr1++;
193fcf3ce44SJohn Forte 		bptr2++;
194fcf3ce44SJohn Forte 	}
195fcf3ce44SJohn Forte 
196fcf3ce44SJohn Forte 	/* Replace the original buffer */
197fcf3ce44SJohn Forte 	buffer = local_buffer;
19882527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
199fcf3ce44SJohn Forte 
200fcf3ce44SJohn Forte 	bzero(&fw_image, sizeof (emlxs_fw_image_t));
201fcf3ce44SJohn Forte 	for (i = 0; i < MAX_PROG_TYPES; i++) {
202fcf3ce44SJohn Forte 		(void) strcpy(fw_image.prog[i].label, "none");
203fcf3ce44SJohn Forte 	}
204fcf3ce44SJohn Forte 
205fcf3ce44SJohn Forte 	/* Validate image */
206fcf3ce44SJohn Forte 	if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) {
207fcf3ce44SJohn Forte 		goto done;
208fcf3ce44SJohn Forte 	}
209291a2b48SSukumar Swaminathan 
2106a573d82SSukumar Swaminathan 	/* Verify image */
2116a573d82SSukumar Swaminathan 	emlxs_verify_image(hba, &fw_image);
2126a573d82SSukumar Swaminathan 
213fcf3ce44SJohn Forte 	/* Get image type */
214fcf3ce44SJohn Forte 	Uptr = (uint32_t *)buffer;
215fcf3ce44SJohn Forte 	ImageType = *Uptr;
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte 	/*
218291a2b48SSukumar Swaminathan 	 * Pegasus and beyond FW download is done differently
219291a2b48SSukumar Swaminathan 	 * for absolute download.
220fcf3ce44SJohn Forte 	 */
221fcf3ce44SJohn Forte 
222fcf3ce44SJohn Forte 	/* Check for absolute image */
223fcf3ce44SJohn Forte 	if ((ImageType == NOP_IMAGE_TYPE) &&
224fcf3ce44SJohn Forte 	    !(hba->model_info.chip &
225fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
226fcf3ce44SJohn Forte 		/*
227fcf3ce44SJohn Forte 		 * Because 2Mb flash download file format is different from
228fcf3ce44SJohn Forte 		 * 512k, it needs to be handled differently
229fcf3ce44SJohn Forte 		 */
230fcf3ce44SJohn Forte 		if (rval = emlxs_start_abs_download_2mb(hba, buffer, len,
231fcf3ce44SJohn Forte 		    offline, &fw_image)) {
232fcf3ce44SJohn Forte 			goto done;
233fcf3ce44SJohn Forte 		}
234291a2b48SSukumar Swaminathan 
235fcf3ce44SJohn Forte 		/* Offline already handled */
236fcf3ce44SJohn Forte 		offline = 0;
237fcf3ce44SJohn Forte 
238fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
239fcf3ce44SJohn Forte 	}
240291a2b48SSukumar Swaminathan 
241fcf3ce44SJohn Forte 	/* Pre-pegasus adapters only */
242fcf3ce44SJohn Forte 
2436a573d82SSukumar Swaminathan 	/* Initialize headers */
2446a573d82SSukumar Swaminathan 	if (ImageType == NOP_IMAGE_TYPE) {
245fcf3ce44SJohn Forte 		bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
246fcf3ce44SJohn Forte 		bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
2476a573d82SSukumar Swaminathan 	} else { /* PRG file */
248fcf3ce44SJohn Forte 		bzero((void *)&AifHdr, sizeof (AIF_HDR));
249fcf3ce44SJohn Forte 		bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
250fcf3ce44SJohn Forte 	}
251fcf3ce44SJohn Forte 
2526a573d82SSukumar Swaminathan 	/* Everything checks out, now to just do it */
253fcf3ce44SJohn Forte 
254fcf3ce44SJohn Forte 	if (offline) {
255fcf3ce44SJohn Forte 		if (emlxs_offline(hba) != FC_SUCCESS) {
256fcf3ce44SJohn Forte 			offline = 0;
257fcf3ce44SJohn Forte 
258fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
259fcf3ce44SJohn Forte 			    "Unable to take adapter offline.");
260fcf3ce44SJohn Forte 
261fcf3ce44SJohn Forte 			rval = EMLXS_OFFLINE_FAILED;
262fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
263fcf3ce44SJohn Forte 		}
264291a2b48SSukumar Swaminathan 
26582527734SSukumar Swaminathan 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
266fcf3ce44SJohn Forte 			offline = 0;
267fcf3ce44SJohn Forte 
268fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
269fcf3ce44SJohn Forte 			    "Unable to restart adapter.");
270fcf3ce44SJohn Forte 
271fcf3ce44SJohn Forte 			rval = EMLXS_OFFLINE_FAILED;
272fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
273fcf3ce44SJohn Forte 		}
274fcf3ce44SJohn Forte 	}
275291a2b48SSukumar Swaminathan 
2766a573d82SSukumar Swaminathan 	/* Pre-pegasus adapters */
2776a573d82SSukumar Swaminathan 
278fcf3ce44SJohn Forte 	if (ImageHdr.Id.Type == SBUS_FCODE) {
279fcf3ce44SJohn Forte 		/* Erase Flash */
280fcf3ce44SJohn Forte 		if (emlxs_erase_fcode_flash(hba)) {
281fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
282fcf3ce44SJohn Forte 			    "Unable to erase flash.");
283fcf3ce44SJohn Forte 
284fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
285fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
286fcf3ce44SJohn Forte 		}
287291a2b48SSukumar Swaminathan 
288fcf3ce44SJohn Forte 		/* Write FCODE */
289fcf3ce44SJohn Forte 		if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) {
290fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
291fcf3ce44SJohn Forte 			    "Unable to write flash.");
292fcf3ce44SJohn Forte 
293fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
294fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
295fcf3ce44SJohn Forte 		}
296291a2b48SSukumar Swaminathan 
2976a573d82SSukumar Swaminathan 		goto SLI_DOWNLOAD_EXIT;
2986a573d82SSukumar Swaminathan 	}
299fcf3ce44SJohn Forte 
3006a573d82SSukumar Swaminathan 	/* Pre-pegasus PCI adapters */
301291a2b48SSukumar Swaminathan 
3026a573d82SSukumar Swaminathan 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
3036a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3046a573d82SSukumar Swaminathan 		    "Unable to get parameters.");
305fcf3ce44SJohn Forte 
3066a573d82SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
307fcf3ce44SJohn Forte 
3086a573d82SSukumar Swaminathan 		goto SLI_DOWNLOAD_EXIT;
3096a573d82SSukumar Swaminathan 	}
310291a2b48SSukumar Swaminathan 
3116a573d82SSukumar Swaminathan 	if (ImageType == NOP_IMAGE_TYPE) {
3126a573d82SSukumar Swaminathan 		if (emlxs_start_abs_download(hba, &AifHdr,
3136a573d82SSukumar Swaminathan 		    buffer, len, &WakeUpParms)) {
3146a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3156a573d82SSukumar Swaminathan 			    &emlxs_download_failed_msg,
3166a573d82SSukumar Swaminathan 			    "Failed to program flash.");
317fcf3ce44SJohn Forte 
318fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
319fcf3ce44SJohn Forte 
320fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
321fcf3ce44SJohn Forte 		}
322291a2b48SSukumar Swaminathan 
3236a573d82SSukumar Swaminathan 	} else { /* Relative PRG file */
3246a573d82SSukumar Swaminathan 		if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
3256a573d82SSukumar Swaminathan 		    &WakeUpParms, 0)) {
3266a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3276a573d82SSukumar Swaminathan 			    &emlxs_download_failed_msg,
3286a573d82SSukumar Swaminathan 			    "Failed to program flash.");
329fcf3ce44SJohn Forte 
3306a573d82SSukumar Swaminathan 			rval = EMLXS_IMAGE_FAILED;
331fcf3ce44SJohn Forte 
3326a573d82SSukumar Swaminathan 			goto SLI_DOWNLOAD_EXIT;
333fcf3ce44SJohn Forte 		}
3346a573d82SSukumar Swaminathan 	}
335fcf3ce44SJohn Forte 
336fcf3ce44SJohn Forte SLI_DOWNLOAD_EXIT:
337fcf3ce44SJohn Forte 
338fcf3ce44SJohn Forte 	if (offline) {
339fcf3ce44SJohn Forte 		(void) emlxs_online(hba);
340fcf3ce44SJohn Forte 	}
341291a2b48SSukumar Swaminathan 
342fcf3ce44SJohn Forte 	if (rval == 0) {
343fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
344fcf3ce44SJohn Forte 		    "Status good.");
345fcf3ce44SJohn Forte 	}
346291a2b48SSukumar Swaminathan 
347fcf3ce44SJohn Forte done:
348fcf3ce44SJohn Forte 
34982527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
350fcf3ce44SJohn Forte 	/* Free the local buffer */
351fcf3ce44SJohn Forte 	kmem_free(local_buffer, len);
35282527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
35382527734SSukumar Swaminathan 
35482527734SSukumar Swaminathan 	return (rval);
35582527734SSukumar Swaminathan 
35682527734SSukumar Swaminathan } /* emlxs_fw_download */
35782527734SSukumar Swaminathan 
35882527734SSukumar Swaminathan 
359*a9800bebSGarrett D'Amore extern void
36082527734SSukumar Swaminathan emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size)
36182527734SSukumar Swaminathan {
36282527734SSukumar Swaminathan 	while (size--) {
36382527734SSukumar Swaminathan 		*buffer++ = value;
36482527734SSukumar Swaminathan 	}
36582527734SSukumar Swaminathan 
36682527734SSukumar Swaminathan } /* emlxs_memset () */
36782527734SSukumar Swaminathan 
36882527734SSukumar Swaminathan 
36982527734SSukumar Swaminathan static int32_t
37082527734SSukumar Swaminathan emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
37182527734SSukumar Swaminathan     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
37282527734SSukumar Swaminathan {
37382527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
37482527734SSukumar Swaminathan 	uint8_t *image_ptr;
37582527734SSukumar Swaminathan 	uint32_t *wptr;
37682527734SSukumar Swaminathan 	uint8_t *payload;
37782527734SSukumar Swaminathan 	MAILBOX4 *mb;
37882527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
37982527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
38082527734SSukumar Swaminathan 	uint32_t	image_size;
38182527734SSukumar Swaminathan 	uint32_t	block_size;
38282527734SSukumar Swaminathan 	uint32_t	xfer_size;
38382527734SSukumar Swaminathan 	uint32_t	block_offset;
38482527734SSukumar Swaminathan 	uint32_t	count;
38582527734SSukumar Swaminathan 	uint32_t	rval = 0;
38682527734SSukumar Swaminathan 
38782527734SSukumar Swaminathan 	if (file->image_size == 0) {
38882527734SSukumar Swaminathan 		return (0);
38982527734SSukumar Swaminathan 	}
39082527734SSukumar Swaminathan 
39182527734SSukumar Swaminathan 	image_ptr  = (uint8_t *)buffer + file->image_offset;
39282527734SSukumar Swaminathan 	image_size = file->image_size;
39382527734SSukumar Swaminathan 	block_size = file->block_size;
39482527734SSukumar Swaminathan 	block_offset = 0;
39582527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
39682527734SSukumar Swaminathan 
39782527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
39882527734SSukumar Swaminathan 	    "%s: Downloading...", file->label);
39982527734SSukumar Swaminathan 
40082527734SSukumar Swaminathan 	while (block_size) {
40182527734SSukumar Swaminathan 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
40282527734SSukumar Swaminathan 		bzero((void *) mp->virt, mp->size);
40382527734SSukumar Swaminathan 
40482527734SSukumar Swaminathan 		xfer_size = min(BE_MAX_XFER_SIZE, block_size);
40582527734SSukumar Swaminathan 
40682527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.embedded = 0;
407*a9800bebSGarrett D'Amore 		mbq->nonembed = (void *)mp;
40882527734SSukumar Swaminathan 		mbq->mbox_cmpl = NULL;
40982527734SSukumar Swaminathan 
41082527734SSukumar Swaminathan 		mb->mbxCommand = MBX_SLI_CONFIG;
41182527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
41282527734SSukumar Swaminathan 
41382527734SSukumar Swaminathan 		hdr_req = (mbox_req_hdr_t *)mp->virt;
41482527734SSukumar Swaminathan 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
41582527734SSukumar Swaminathan 		hdr_req->opcode = COMMON_OPCODE_WRITE_FLASHROM;
41682527734SSukumar Swaminathan 		hdr_req->timeout = 0;
41782527734SSukumar Swaminathan 		hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
41882527734SSukumar Swaminathan 		    xfer_size;
41982527734SSukumar Swaminathan 
42082527734SSukumar Swaminathan 		flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
42182527734SSukumar Swaminathan 		flashrom->params.opcode = ((block_size == xfer_size)?
42282527734SSukumar Swaminathan 		    MGMT_FLASHROM_OPCODE_FLASH:MGMT_FLASHROM_OPCODE_SAVE);
42382527734SSukumar Swaminathan 		flashrom->params.optype = file->type;
42482527734SSukumar Swaminathan 		flashrom->params.data_buffer_size = xfer_size;
42582527734SSukumar Swaminathan 		flashrom->params.offset = block_offset;
42682527734SSukumar Swaminathan 
42782527734SSukumar Swaminathan 		/* Build data buffer payload */
42882527734SSukumar Swaminathan 		payload = (uint8_t *)(&flashrom->params.data_buffer);
42982527734SSukumar Swaminathan 		emlxs_memset(payload, 0xff, xfer_size);
43082527734SSukumar Swaminathan 
43182527734SSukumar Swaminathan 		/* Copy remaining image into payload */
43282527734SSukumar Swaminathan 		if (image_size) {
43382527734SSukumar Swaminathan 			count = min(image_size, xfer_size);
43482527734SSukumar Swaminathan 			BE_SWAP32_BCOPY(image_ptr, payload, count);
43582527734SSukumar Swaminathan 			image_size -= count;
43682527734SSukumar Swaminathan 			image_ptr  += count;
43782527734SSukumar Swaminathan 		}
43882527734SSukumar Swaminathan 
43982527734SSukumar Swaminathan 		if (flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) {
4406a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&payload[(xfer_size - 12)];
441*a9800bebSGarrett D'Amore 
4426a573d82SSukumar Swaminathan 			wptr[0] = file->load_address;
4436a573d82SSukumar Swaminathan 			wptr[1] = file->image_size;
4446a573d82SSukumar Swaminathan 			wptr[2] = file->block_crc;
44582527734SSukumar Swaminathan 		}
44682527734SSukumar Swaminathan 
44782527734SSukumar Swaminathan 		/* Send write request */
44882527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
44982527734SSukumar Swaminathan 		    MBX_SUCCESS) {
45082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
45182527734SSukumar Swaminathan 			    "%s: Unable to download image. status=%x",
45282527734SSukumar Swaminathan 			    file->label, mb->mbxStatus);
45382527734SSukumar Swaminathan 			rval = EMLXS_IMAGE_FAILED;
45482527734SSukumar Swaminathan 			goto done;
45582527734SSukumar Swaminathan 		}
45682527734SSukumar Swaminathan 
45782527734SSukumar Swaminathan 		block_size -= xfer_size;
45882527734SSukumar Swaminathan 		block_offset += xfer_size;
45982527734SSukumar Swaminathan 	}
46082527734SSukumar Swaminathan 
46182527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
46282527734SSukumar Swaminathan 	    "%s: Download complete.", file->label);
46382527734SSukumar Swaminathan done:
46482527734SSukumar Swaminathan 
46582527734SSukumar Swaminathan 	return (rval);
46682527734SSukumar Swaminathan 
46782527734SSukumar Swaminathan } /* emlxs_sli4_flash_image() */
46882527734SSukumar Swaminathan 
46982527734SSukumar Swaminathan 
47082527734SSukumar Swaminathan 
47182527734SSukumar Swaminathan 
47282527734SSukumar Swaminathan static int32_t
47382527734SSukumar Swaminathan emlxs_sli4_verify_crc(emlxs_hba_t *hba,
47482527734SSukumar Swaminathan     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
47582527734SSukumar Swaminathan {
47682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
47782527734SSukumar Swaminathan 	uint32_t *wptr;
47882527734SSukumar Swaminathan 	uint8_t *payload;
47982527734SSukumar Swaminathan 	MAILBOX4 *mb;
48082527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
48182527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
48282527734SSukumar Swaminathan 	uint32_t	xfer_size;
48382527734SSukumar Swaminathan 	uint32_t	block_offset;
48482527734SSukumar Swaminathan 	uint32_t	rval = 0;
48582527734SSukumar Swaminathan 	uint32_t	value;
48682527734SSukumar Swaminathan 
48782527734SSukumar Swaminathan 	xfer_size = 8;
48882527734SSukumar Swaminathan 	block_offset = file->block_size - xfer_size;
48982527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
49082527734SSukumar Swaminathan 
49182527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
49282527734SSukumar Swaminathan 	    "%s: Verifying CRC...", file->label);
49382527734SSukumar Swaminathan 
49482527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
49582527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
49682527734SSukumar Swaminathan 
49782527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
498*a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
49982527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
50082527734SSukumar Swaminathan 
50182527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
50282527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
50382527734SSukumar Swaminathan 
50482527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
50582527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
50682527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
50782527734SSukumar Swaminathan 	hdr_req->timeout = 0;
50882527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
50982527734SSukumar Swaminathan 	    xfer_size;
51082527734SSukumar Swaminathan 
51182527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
51282527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
51382527734SSukumar Swaminathan 	flashrom->params.optype = file->type;
51482527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
51582527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
51682527734SSukumar Swaminathan 
51782527734SSukumar Swaminathan 	/* Send read request */
51882527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
51982527734SSukumar Swaminathan 	    MBX_SUCCESS) {
52082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
52182527734SSukumar Swaminathan 		    "%s: Unable to read CRC. status=%x",
52282527734SSukumar Swaminathan 		    file->label, mb->mbxStatus);
52382527734SSukumar Swaminathan 
524*a9800bebSGarrett D'Amore 		rval = 2;
52582527734SSukumar Swaminathan 		goto done;
52682527734SSukumar Swaminathan 	}
52782527734SSukumar Swaminathan 
52882527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
52982527734SSukumar Swaminathan 	wptr = (uint32_t *)(payload + xfer_size - 8);
53082527734SSukumar Swaminathan 
53182527734SSukumar Swaminathan 	/* Verify image size */
53282527734SSukumar Swaminathan 	value = *wptr++;
53382527734SSukumar Swaminathan 	if (value != file->image_size) {
53482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
53582527734SSukumar Swaminathan 		    "%s: Image size mismatch. %08x != %08x",
53682527734SSukumar Swaminathan 		    file->label, value, file->image_size);
53782527734SSukumar Swaminathan 
538*a9800bebSGarrett D'Amore 		rval = 1;
53982527734SSukumar Swaminathan 		goto done;
54082527734SSukumar Swaminathan 	}
54182527734SSukumar Swaminathan 
54282527734SSukumar Swaminathan 	/* Verify block crc */
54382527734SSukumar Swaminathan 	value = *wptr;
54482527734SSukumar Swaminathan 	if (value != file->block_crc) {
54582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
54682527734SSukumar Swaminathan 		    "%s: CRC mismatch. %08x != %08x",
54782527734SSukumar Swaminathan 		    file->label, value, file->block_crc);
548*a9800bebSGarrett D'Amore 		rval = 1;
54982527734SSukumar Swaminathan 	}
55082527734SSukumar Swaminathan 
55182527734SSukumar Swaminathan done:
55282527734SSukumar Swaminathan 
55382527734SSukumar Swaminathan 	if (rval == 0) {
55482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
55582527734SSukumar Swaminathan 		    "%s: CRC verified.", file->label);
55682527734SSukumar Swaminathan 	}
55782527734SSukumar Swaminathan 
55882527734SSukumar Swaminathan 	return (rval);
55982527734SSukumar Swaminathan 
56082527734SSukumar Swaminathan } /* emlxs_sli4_verify_crc() */
56182527734SSukumar Swaminathan 
56282527734SSukumar Swaminathan 
56382527734SSukumar Swaminathan extern int32_t
56482527734SSukumar Swaminathan emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw)
56582527734SSukumar Swaminathan {
56682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
56782527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
56882527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
56982527734SSukumar Swaminathan 	MAILBOX4 *mb;
57082527734SSukumar Swaminathan 	uint32_t *wptr;
57182527734SSukumar Swaminathan 	uint8_t *payload;
57282527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
57382527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
57482527734SSukumar Swaminathan 	uint32_t	xfer_size;
57582527734SSukumar Swaminathan 	uint32_t	block_offset;
57682527734SSukumar Swaminathan 	uint32_t	rval = 0;
57782527734SSukumar Swaminathan 
57882527734SSukumar Swaminathan 	bzero((void *) fw, sizeof (emlxs_firmware_t));
57982527734SSukumar Swaminathan 
58082527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
58182527734SSukumar Swaminathan 	    KM_SLEEP)) == NULL) {
58282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
58382527734SSukumar Swaminathan 		    "read_fw_version: Unable to allocate mailbox buffer.");
58482527734SSukumar Swaminathan 
58582527734SSukumar Swaminathan 		rval = 1;
58682527734SSukumar Swaminathan 		goto done;
58782527734SSukumar Swaminathan 	}
58882527734SSukumar Swaminathan 
58982527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
59082527734SSukumar Swaminathan 	    sizeof (IOCTL_COMMON_FLASHROM) + 32))) == NULL) {
59182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
59282527734SSukumar Swaminathan 		    "read_fw_version: Unable to allocate payload buffer.");
59382527734SSukumar Swaminathan 
59482527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
59582527734SSukumar Swaminathan 		goto done;
59682527734SSukumar Swaminathan 	}
59782527734SSukumar Swaminathan 
59882527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
59982527734SSukumar Swaminathan 
60082527734SSukumar Swaminathan 	/* Read CRC and size */
60182527734SSukumar Swaminathan 	xfer_size = 8;
60282527734SSukumar Swaminathan 	block_offset = 0x140000 - xfer_size;
60382527734SSukumar Swaminathan 
60482527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
60582527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
60682527734SSukumar Swaminathan 
60782527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
608*a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
60982527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
61082527734SSukumar Swaminathan 
61182527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
61282527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
61382527734SSukumar Swaminathan 
61482527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
61582527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
61682527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
61782527734SSukumar Swaminathan 	hdr_req->timeout = 0;
61882527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
61982527734SSukumar Swaminathan 	    xfer_size;
62082527734SSukumar Swaminathan 
62182527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
62282527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
62382527734SSukumar Swaminathan 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
62482527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
62582527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
62682527734SSukumar Swaminathan 
62782527734SSukumar Swaminathan 	/* Send read request */
62882527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
62982527734SSukumar Swaminathan 	    MBX_SUCCESS) {
63082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
63182527734SSukumar Swaminathan 		    "read_fw_version: Unable to read CRC. status=%x",
63282527734SSukumar Swaminathan 		    mb->mbxStatus);
63382527734SSukumar Swaminathan 
63482527734SSukumar Swaminathan 		rval = 1;
63582527734SSukumar Swaminathan 		goto done;
63682527734SSukumar Swaminathan 	}
63782527734SSukumar Swaminathan 
63882527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
63982527734SSukumar Swaminathan 
64082527734SSukumar Swaminathan 	wptr = (uint32_t *)payload;
64182527734SSukumar Swaminathan 	fw->size = *wptr++; /* image size */
64282527734SSukumar Swaminathan 	fw->sli4 = *wptr;   /* block crc */
64382527734SSukumar Swaminathan 	fw->kern = *wptr;
64482527734SSukumar Swaminathan 	fw->stub = *wptr;
64582527734SSukumar Swaminathan 
64682527734SSukumar Swaminathan 	/* Read version label */
64782527734SSukumar Swaminathan 	xfer_size = 32;
64882527734SSukumar Swaminathan 	block_offset = 0x30;
64982527734SSukumar Swaminathan 
65082527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
65182527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
65282527734SSukumar Swaminathan 
65382527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
654*a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
65582527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
65682527734SSukumar Swaminathan 
65782527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
65882527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
65982527734SSukumar Swaminathan 
66082527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
66182527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
66282527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
66382527734SSukumar Swaminathan 	hdr_req->timeout = 0;
66482527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
66582527734SSukumar Swaminathan 	    xfer_size;
66682527734SSukumar Swaminathan 
66782527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
66882527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
66982527734SSukumar Swaminathan 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
67082527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
67182527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
67282527734SSukumar Swaminathan 
67382527734SSukumar Swaminathan 	/* Send read request */
67482527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
67582527734SSukumar Swaminathan 	    MBX_SUCCESS) {
67682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
67782527734SSukumar Swaminathan 		    "read_fw_version: Unable to read version string. status=%x",
67882527734SSukumar Swaminathan 		    mb->mbxStatus);
67982527734SSukumar Swaminathan 
68082527734SSukumar Swaminathan 		rval = 1;
68182527734SSukumar Swaminathan 		goto done;
68282527734SSukumar Swaminathan 	}
68382527734SSukumar Swaminathan 
68482527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
68582527734SSukumar Swaminathan 	BE_SWAP32_BCOPY(payload, (uint8_t *)fw->label, 32);
68682527734SSukumar Swaminathan 
68782527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
68882527734SSukumar Swaminathan 	    "FCOE FIRMWARE: size=%x version=%s (0x%08x)",
68982527734SSukumar Swaminathan 	    fw->size, fw->label, fw->sli4);
69082527734SSukumar Swaminathan 
69182527734SSukumar Swaminathan done:
69282527734SSukumar Swaminathan 
69382527734SSukumar Swaminathan 	if (mbq) {
694*a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
69582527734SSukumar Swaminathan 	}
69682527734SSukumar Swaminathan 
69782527734SSukumar Swaminathan 	if (mp) {
698*a9800bebSGarrett D'Amore 		emlxs_mem_buf_free(hba, mp);
69982527734SSukumar Swaminathan 	}
70082527734SSukumar Swaminathan 
70182527734SSukumar Swaminathan 	return (rval);
70282527734SSukumar Swaminathan 
70382527734SSukumar Swaminathan } /* emlxs_sli4_read_fw_version() */
70482527734SSukumar Swaminathan 
70582527734SSukumar Swaminathan 
70682527734SSukumar Swaminathan static uint32_t
707*a9800bebSGarrett D'Amore emlxs_be_version(caddr_t buffer, uint32_t size, uint32_t *plus_flag)
708*a9800bebSGarrett D'Amore {
709*a9800bebSGarrett D'Amore 	emlxs_be2_ufi_header_t *ufi_hdr;
710*a9800bebSGarrett D'Amore 	char signature[BE2_SIGNATURE_SIZE];
711*a9800bebSGarrett D'Amore 	uint32_t be_version = 0;
712*a9800bebSGarrett D'Amore 
713*a9800bebSGarrett D'Amore 	if (size < sizeof (emlxs_be2_ufi_header_t)) {
714*a9800bebSGarrett D'Amore 		return (0);
715*a9800bebSGarrett D'Amore 	}
716*a9800bebSGarrett D'Amore 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
717*a9800bebSGarrett D'Amore 
718*a9800bebSGarrett D'Amore 	(void) sprintf(signature, "%s+", BE_SIGNATURE);
719*a9800bebSGarrett D'Amore 
720*a9800bebSGarrett D'Amore 	/* Check if this is a UFI image */
721*a9800bebSGarrett D'Amore 	if (strncmp(signature, (char *)ufi_hdr->signature,
722*a9800bebSGarrett D'Amore 	    strlen(BE_SIGNATURE)) != 0) {
723*a9800bebSGarrett D'Amore 		return (0);
724*a9800bebSGarrett D'Amore 	}
725*a9800bebSGarrett D'Amore 
726*a9800bebSGarrett D'Amore 	/* Check if this is a UFI plus image */
727*a9800bebSGarrett D'Amore 	if (plus_flag) {
728*a9800bebSGarrett D'Amore 		/* Check if this is a UFI plus image */
729*a9800bebSGarrett D'Amore 		if (strncmp(signature, (char *)ufi_hdr->signature,
730*a9800bebSGarrett D'Amore 		    strlen(BE_SIGNATURE)+1) == 0) {
731*a9800bebSGarrett D'Amore 			*plus_flag = 1;
732*a9800bebSGarrett D'Amore 		} else {
733*a9800bebSGarrett D'Amore 			*plus_flag = 0;
734*a9800bebSGarrett D'Amore 		}
735*a9800bebSGarrett D'Amore 	}
736*a9800bebSGarrett D'Amore 
737*a9800bebSGarrett D'Amore 	if ((ufi_hdr->build[0] >= '1') && (ufi_hdr->build[0] <= '9')) {
738*a9800bebSGarrett D'Amore 		be_version = ufi_hdr->build[0] - '0';
739*a9800bebSGarrett D'Amore 	}
740*a9800bebSGarrett D'Amore 
741*a9800bebSGarrett D'Amore 	return (be_version);
742*a9800bebSGarrett D'Amore 
743*a9800bebSGarrett D'Amore } /* emlxs_be_version() */
744*a9800bebSGarrett D'Amore 
745*a9800bebSGarrett D'Amore 
746*a9800bebSGarrett D'Amore static uint32_t
747*a9800bebSGarrett D'Amore emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
74882527734SSukumar Swaminathan     uint32_t len, emlxs_be_fw_image_t *fw_image)
74982527734SSukumar Swaminathan {
75082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
751*a9800bebSGarrett D'Amore 	emlxs_be2_ufi_header_t *ufi_hdr;
752*a9800bebSGarrett D'Amore 	emlxs_be2_flash_dir_t *flash_dir;
753*a9800bebSGarrett D'Amore 	emlxs_be2_flash_entry_t *entry;
75482527734SSukumar Swaminathan 	uint8_t *bptr;
75582527734SSukumar Swaminathan 	uint32_t *wptr;
75682527734SSukumar Swaminathan 	uint32_t i;
75782527734SSukumar Swaminathan 	uint32_t k;
75882527734SSukumar Swaminathan 	uint32_t mask;
75982527734SSukumar Swaminathan 	uint32_t value;
76082527734SSukumar Swaminathan 	uint32_t image_size;
76182527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file;
76282527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file2;
76382527734SSukumar Swaminathan 	uint32_t ufi_plus = 0;
764*a9800bebSGarrett D'Amore 	uint32_t be_version = 0;
765*a9800bebSGarrett D'Amore 	uint32_t found;
76682527734SSukumar Swaminathan 
76782527734SSukumar Swaminathan 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
76882527734SSukumar Swaminathan 
769*a9800bebSGarrett D'Amore 	if (hba->model_info.chip != EMLXS_BE2_CHIP) {
77082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
77182527734SSukumar Swaminathan 		    "Invalid adapter model.");
77282527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
77382527734SSukumar Swaminathan 	}
77482527734SSukumar Swaminathan 
775*a9800bebSGarrett D'Amore 	if (len < (sizeof (emlxs_be2_ufi_header_t) +
776*a9800bebSGarrett D'Amore 	    sizeof (emlxs_be2_flash_dir_t))) {
77782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
77882527734SSukumar Swaminathan 		    "Image too small. (%d < %d)",
779*a9800bebSGarrett D'Amore 		    len, (sizeof (emlxs_be2_ufi_header_t) +
780*a9800bebSGarrett D'Amore 		    sizeof (emlxs_be2_flash_dir_t)));
78182527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
78282527734SSukumar Swaminathan 	}
78382527734SSukumar Swaminathan 
784*a9800bebSGarrett D'Amore 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
785*a9800bebSGarrett D'Amore 
786*a9800bebSGarrett D'Amore 	/* Check if this is a standard BE2 image */
787*a9800bebSGarrett D'Amore 	if (be_version != 2) {
78882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
78982527734SSukumar Swaminathan 		    "Invalid image provided.");
79082527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
79182527734SSukumar Swaminathan 	}
79282527734SSukumar Swaminathan 
793*a9800bebSGarrett D'Amore 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
79482527734SSukumar Swaminathan 
79582527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
79682527734SSukumar Swaminathan 	/* Big Endian Swapping */
79782527734SSukumar Swaminathan 	/* Swap ufi header */
79882527734SSukumar Swaminathan 	ufi_hdr->checksum =
79982527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->checksum);
80082527734SSukumar Swaminathan 	ufi_hdr->antidote =
80182527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->antidote);
80282527734SSukumar Swaminathan 	ufi_hdr->controller.vendor_id =
80382527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.vendor_id);
80482527734SSukumar Swaminathan 	ufi_hdr->controller.device_id =
80582527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.device_id);
80682527734SSukumar Swaminathan 	ufi_hdr->controller.sub_vendor_id =
80782527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.sub_vendor_id);
80882527734SSukumar Swaminathan 	ufi_hdr->controller.sub_device_id =
80982527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.sub_device_id);
81082527734SSukumar Swaminathan 	ufi_hdr->file_length =
81182527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->file_length);
81282527734SSukumar Swaminathan 	ufi_hdr->chunk_num =
81382527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->chunk_num);
81482527734SSukumar Swaminathan 	ufi_hdr->chunk_cnt =
81582527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->chunk_cnt);
81682527734SSukumar Swaminathan 	ufi_hdr->image_cnt =
81782527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->image_cnt);
81882527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
81982527734SSukumar Swaminathan 
82082527734SSukumar Swaminathan 	if (len != ufi_hdr->file_length) {
82182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
82282527734SSukumar Swaminathan 		    "Invalid image size (%d != %d)",
82382527734SSukumar Swaminathan 		    len, ufi_hdr->file_length);
82482527734SSukumar Swaminathan 
82582527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
82682527734SSukumar Swaminathan 	}
82782527734SSukumar Swaminathan 
82882527734SSukumar Swaminathan 	/* Scan for flash dir signature */
82982527734SSukumar Swaminathan 	bptr = (uint8_t *)buffer;
83082527734SSukumar Swaminathan 	flash_dir = NULL;
83182527734SSukumar Swaminathan 	for (i = 0; i < len; i++, bptr++) {
83282527734SSukumar Swaminathan 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
83382527734SSukumar Swaminathan 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
834*a9800bebSGarrett D'Amore 			flash_dir = (emlxs_be2_flash_dir_t *)bptr;
83582527734SSukumar Swaminathan 			break;
83682527734SSukumar Swaminathan 		}
83782527734SSukumar Swaminathan 	}
83882527734SSukumar Swaminathan 
83982527734SSukumar Swaminathan 	if (!flash_dir) {
84082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
84182527734SSukumar Swaminathan 		    "Unable to find flash directory.");
84282527734SSukumar Swaminathan 
84382527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
84482527734SSukumar Swaminathan 	}
84582527734SSukumar Swaminathan 
84682527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
84782527734SSukumar Swaminathan 	/* Big Endian Swapping */
84882527734SSukumar Swaminathan 	/* Swap flash dir */
84982527734SSukumar Swaminathan 	flash_dir->header.format_rev =
85082527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.format_rev);
85182527734SSukumar Swaminathan 	flash_dir->header.checksum =
85282527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.checksum);
85382527734SSukumar Swaminathan 	flash_dir->header.antidote =
85482527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.antidote);
85582527734SSukumar Swaminathan 	flash_dir->header.build_num =
85682527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.build_num);
85782527734SSukumar Swaminathan 	flash_dir->header.active_entry_mask =
85882527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.active_entry_mask);
85982527734SSukumar Swaminathan 	flash_dir->header.valid_entry_mask =
86082527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.valid_entry_mask);
86182527734SSukumar Swaminathan 	flash_dir->header.orig_content_mask =
86282527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.orig_content_mask);
86382527734SSukumar Swaminathan 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
86482527734SSukumar Swaminathan 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
86582527734SSukumar Swaminathan 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
86682527734SSukumar Swaminathan 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
86782527734SSukumar Swaminathan 	flash_dir->header.resv4 = SWAP32(flash_dir->header.resv4);
86882527734SSukumar Swaminathan 
86982527734SSukumar Swaminathan 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
87082527734SSukumar Swaminathan 		flash_dir->header.controller[i].vendor_id =
87182527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].vendor_id);
87282527734SSukumar Swaminathan 		flash_dir->header.controller[i].device_id =
87382527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].device_id);
87482527734SSukumar Swaminathan 		flash_dir->header.controller[i].sub_vendor_id =
87582527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
87682527734SSukumar Swaminathan 		flash_dir->header.controller[i].sub_device_id =
87782527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
87882527734SSukumar Swaminathan 	}
87982527734SSukumar Swaminathan 
88082527734SSukumar Swaminathan 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++,  mask <<= 1) {
88182527734SSukumar Swaminathan 
88282527734SSukumar Swaminathan 		if (!(flash_dir->header.valid_entry_mask & mask)) {
88382527734SSukumar Swaminathan 			continue;
88482527734SSukumar Swaminathan 		}
88582527734SSukumar Swaminathan 
88682527734SSukumar Swaminathan 		entry = &flash_dir->entry[i];
887*a9800bebSGarrett D'Amore 
888*a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
889*a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
890*a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
89182527734SSukumar Swaminathan 			continue;
89282527734SSukumar Swaminathan 		}
89382527734SSukumar Swaminathan 
89482527734SSukumar Swaminathan 		flash_dir->entry[i].type =
89582527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].type);
89682527734SSukumar Swaminathan 		flash_dir->entry[i].offset =
89782527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].offset);
89882527734SSukumar Swaminathan 		flash_dir->entry[i].pad_size =
89982527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].pad_size);
90082527734SSukumar Swaminathan 		flash_dir->entry[i].image_size =
90182527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].image_size);
90282527734SSukumar Swaminathan 		flash_dir->entry[i].checksum =
90382527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].checksum);
90482527734SSukumar Swaminathan 		flash_dir->entry[i].entry_point =
90582527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].entry_point);
90682527734SSukumar Swaminathan 		flash_dir->entry[i].resv0 =
90782527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].resv0);
90882527734SSukumar Swaminathan 		flash_dir->entry[i].resv1 =
90982527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].resv1);
91082527734SSukumar Swaminathan 	}
91182527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
91282527734SSukumar Swaminathan 
913*a9800bebSGarrett D'Amore 	/* Verify adapter model */
914*a9800bebSGarrett D'Amore 	found = 0;
915*a9800bebSGarrett D'Amore 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
916*a9800bebSGarrett D'Amore 		if (flash_dir->header.controller[i].device_id ==
917*a9800bebSGarrett D'Amore 		    hba->model_info.device_id) {
918*a9800bebSGarrett D'Amore 			found = 1;
919*a9800bebSGarrett D'Amore 		}
920*a9800bebSGarrett D'Amore 	}
921*a9800bebSGarrett D'Amore 
922*a9800bebSGarrett D'Amore 	if (!found) {
923*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
924*a9800bebSGarrett D'Amore 		    "Invalid adapter device id=0x%x.",
925*a9800bebSGarrett D'Amore 		    hba->model_info.device_id);
926*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
927*a9800bebSGarrett D'Amore 	}
928*a9800bebSGarrett D'Amore 
92982527734SSukumar Swaminathan 	/* Build fw_image table */
930*a9800bebSGarrett D'Amore 	fw_image->be_version = 2;
931*a9800bebSGarrett D'Amore 	fw_image->ufi_plus = ufi_plus;
93282527734SSukumar Swaminathan 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) {
93382527734SSukumar Swaminathan 
93482527734SSukumar Swaminathan 		if (!(flash_dir->header.valid_entry_mask & mask)) {
93582527734SSukumar Swaminathan 			continue;
93682527734SSukumar Swaminathan 		}
93782527734SSukumar Swaminathan 
93882527734SSukumar Swaminathan 		entry = &flash_dir->entry[i];
939*a9800bebSGarrett D'Amore 
940*a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
941*a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
942*a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
94382527734SSukumar Swaminathan 			continue;
94482527734SSukumar Swaminathan 		}
94582527734SSukumar Swaminathan 
94682527734SSukumar Swaminathan 		switch (entry->type) {
94782527734SSukumar Swaminathan 		case BE_FLASHTYPE_REDBOOT:
94882527734SSukumar Swaminathan 			file = &fw_image->file[REDBOOT_FLASHTYPE];
94982527734SSukumar Swaminathan 			(void) strcpy(file->label, "REDBOOT");
95082527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
95182527734SSukumar Swaminathan 			break;
95282527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_BIOS:
95382527734SSukumar Swaminathan 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
95482527734SSukumar Swaminathan 			(void) strcpy(file->label, "ISCSI BIOS");
95582527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
95682527734SSukumar Swaminathan 			break;
95782527734SSukumar Swaminathan 		case BE_FLASHTYPE_PXE_BIOS:
95882527734SSukumar Swaminathan 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
95982527734SSukumar Swaminathan 			(void) strcpy(file->label, "PXE BIOS");
96082527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
96182527734SSukumar Swaminathan 			break;
96282527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_BIOS:
96382527734SSukumar Swaminathan 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
96482527734SSukumar Swaminathan 			(void) strcpy(file->label, "FCOE BIOS");
96582527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
96682527734SSukumar Swaminathan 			break;
96782527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
96882527734SSukumar Swaminathan 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
96982527734SSukumar Swaminathan 			(void) strcpy(file->label, "ISCSI FIRMWARE");
97082527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
97182527734SSukumar Swaminathan 			break;
97282527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_FIRMWARE:
97382527734SSukumar Swaminathan 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
97482527734SSukumar Swaminathan 			(void) strcpy(file->label, "FCOE FIRMWARE");
97582527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
97682527734SSukumar Swaminathan 			break;
97782527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_BACKUP:
97882527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_BACKUP:
97982527734SSukumar Swaminathan 			continue;
98082527734SSukumar Swaminathan 
98182527734SSukumar Swaminathan 		default:
98282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
98382527734SSukumar Swaminathan 			    "Unknown image type found.  type=%x",
98482527734SSukumar Swaminathan 			    entry->type);
98582527734SSukumar Swaminathan 			continue;
98682527734SSukumar Swaminathan 		}
98782527734SSukumar Swaminathan 
988*a9800bebSGarrett D'Amore 		file->be_version = fw_image->be_version;
989*a9800bebSGarrett D'Amore 		file->ufi_plus = fw_image->ufi_plus;
99082527734SSukumar Swaminathan 		file->image_size = entry->image_size;
99182527734SSukumar Swaminathan 		image_size = BE_SWAP32(entry->image_size);
99282527734SSukumar Swaminathan 
99382527734SSukumar Swaminathan 		if (ufi_plus) {
99482527734SSukumar Swaminathan 			file->image_offset = entry->offset;
99582527734SSukumar Swaminathan 			file->block_size   = entry->pad_size;
99682527734SSukumar Swaminathan 			file->block_crc    = entry->checksum;
9976a573d82SSukumar Swaminathan 			file->load_address = entry->entry_point;
998*a9800bebSGarrett D'Amore 
99982527734SSukumar Swaminathan 		} else {
100082527734SSukumar Swaminathan 			file->image_offset = entry->offset +
1001*a9800bebSGarrett D'Amore 			    sizeof (emlxs_be2_ufi_header_t);
100282527734SSukumar Swaminathan 
100382527734SSukumar Swaminathan 			/* Get entry block size and crc */
100482527734SSukumar Swaminathan 			k = file->image_offset + file->image_size;
100582527734SSukumar Swaminathan 			k &= 0xFFFFFFFC;
100682527734SSukumar Swaminathan 
100782527734SSukumar Swaminathan 			wptr = (uint32_t *)(buffer +  k);
100882527734SSukumar Swaminathan 			for (; k < len; k += 4) {
100982527734SSukumar Swaminathan 				if (*wptr++ == image_size) {
101082527734SSukumar Swaminathan 					/* Calculate block_size */
101182527734SSukumar Swaminathan 					file->block_size = (k + 8) -
101282527734SSukumar Swaminathan 					    file->image_offset;
101382527734SSukumar Swaminathan 
10146a573d82SSukumar Swaminathan 					/* Read load_address */
10156a573d82SSukumar Swaminathan 					value = *(wptr - 2);
10166a573d82SSukumar Swaminathan 					file->load_address = BE_SWAP32(value);
10176a573d82SSukumar Swaminathan 
101882527734SSukumar Swaminathan 					/* Read block_crc */
101982527734SSukumar Swaminathan 					value = *wptr;
102082527734SSukumar Swaminathan 					file->block_crc = BE_SWAP32(value);
102182527734SSukumar Swaminathan 
102282527734SSukumar Swaminathan 					break;
102382527734SSukumar Swaminathan 				}
102482527734SSukumar Swaminathan 			}
102582527734SSukumar Swaminathan 
102682527734SSukumar Swaminathan 			if (k >= len) {
102782527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
102882527734SSukumar Swaminathan 				    "%s: End of block not found. offset=%x",
102982527734SSukumar Swaminathan 				    file->label, file->image_offset);
103082527734SSukumar Swaminathan 
103182527734SSukumar Swaminathan 				bzero(fw_image, sizeof (emlxs_be_fw_image_t));
103282527734SSukumar Swaminathan 				return (EMLXS_IMAGE_BAD);
103382527734SSukumar Swaminathan 			}
103482527734SSukumar Swaminathan 		}
103582527734SSukumar Swaminathan 
103682527734SSukumar Swaminathan 		/* Make sure image will fit in block specified */
10376a573d82SSukumar Swaminathan 		if (file->image_size + 12 > file->block_size) {
103882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
103982527734SSukumar Swaminathan 			    "%s: Image too large for block. image=%x block=%x",
104082527734SSukumar Swaminathan 			    file->label, file->image_size, file->block_size);
104182527734SSukumar Swaminathan 
104282527734SSukumar Swaminathan 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
104382527734SSukumar Swaminathan 			return (EMLXS_IMAGE_BAD);
104482527734SSukumar Swaminathan 		}
104582527734SSukumar Swaminathan 
104682527734SSukumar Swaminathan 		/* Automatically create a backup file entry for firmware */
104782527734SSukumar Swaminathan 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
104882527734SSukumar Swaminathan 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1049*a9800bebSGarrett D'Amore 
1050*a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1051*a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
105282527734SSukumar Swaminathan 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1053*a9800bebSGarrett D'Amore 			(void) strcpy(file2->label, "FCOE BACKUP");
105482527734SSukumar Swaminathan 
105582527734SSukumar Swaminathan 			/* Save FCOE version info */
105682527734SSukumar Swaminathan 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1057*a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
105882527734SSukumar Swaminathan 			    BE_VERSION_SIZE);
1059*a9800bebSGarrett D'Amore 			fw_image->fcoe_version = file->block_crc;
106082527734SSukumar Swaminathan 
106182527734SSukumar Swaminathan 		} else if (file->type ==
106282527734SSukumar Swaminathan 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
106382527734SSukumar Swaminathan 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1064*a9800bebSGarrett D'Amore 
1065*a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1066*a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
1067*a9800bebSGarrett D'Amore 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
106882527734SSukumar Swaminathan 			(void) strcpy(file2->label, "ISCSI BACKUP");
1069*a9800bebSGarrett D'Amore 
1070*a9800bebSGarrett D'Amore 			/* Save ISCSI version info */
1071*a9800bebSGarrett D'Amore 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1072*a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1073*a9800bebSGarrett D'Amore 			    BE_VERSION_SIZE);
1074*a9800bebSGarrett D'Amore 			fw_image->iscsi_version = file->block_crc;
1075*a9800bebSGarrett D'Amore 		}
1076*a9800bebSGarrett D'Amore 	}
1077*a9800bebSGarrett D'Amore 
1078*a9800bebSGarrett D'Amore 	if (fw_image->fcoe_version == 0) {
1079*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1080*a9800bebSGarrett D'Amore 		    "Unable to find FCOE firmware component.");
1081*a9800bebSGarrett D'Amore 
1082*a9800bebSGarrett D'Amore 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1083*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1084*a9800bebSGarrett D'Amore 	}
1085*a9800bebSGarrett D'Amore 
1086*a9800bebSGarrett D'Amore 	/* Display contents */
1087*a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1088*a9800bebSGarrett D'Amore 	    "BE2 UFI Image: %08x, %s", fw_image->fcoe_version,
1089*a9800bebSGarrett D'Amore 	    fw_image->fcoe_label);
1090*a9800bebSGarrett D'Amore 
1091*a9800bebSGarrett D'Amore 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1092*a9800bebSGarrett D'Amore 		file = &fw_image->file[i];
1093*a9800bebSGarrett D'Amore 
1094*a9800bebSGarrett D'Amore 		if (file->image_size == 0) {
1095*a9800bebSGarrett D'Amore 			continue;
1096*a9800bebSGarrett D'Amore 		}
1097*a9800bebSGarrett D'Amore 
1098*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1099*a9800bebSGarrett D'Amore 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1100*a9800bebSGarrett D'Amore 		    "load=%x",
1101*a9800bebSGarrett D'Amore 		    file->label, file->be_version, (file->ufi_plus)?"+":"",
1102*a9800bebSGarrett D'Amore 		    file->type, file->block_size, file->image_size,
1103*a9800bebSGarrett D'Amore 		    file->image_offset, file->block_crc, file->load_address);
1104*a9800bebSGarrett D'Amore 	}
1105*a9800bebSGarrett D'Amore 
1106*a9800bebSGarrett D'Amore 	return (0);
1107*a9800bebSGarrett D'Amore 
1108*a9800bebSGarrett D'Amore } /* emlxs_be2_validate_image() */
1109*a9800bebSGarrett D'Amore 
1110*a9800bebSGarrett D'Amore 
1111*a9800bebSGarrett D'Amore static uint32_t
1112*a9800bebSGarrett D'Amore emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
1113*a9800bebSGarrett D'Amore     uint32_t len, emlxs_be_fw_image_t *fw_image)
1114*a9800bebSGarrett D'Amore {
1115*a9800bebSGarrett D'Amore 	emlxs_port_t *port = &PPORT;
1116*a9800bebSGarrett D'Amore 	emlxs_be3_ufi_header_t *ufi_hdr;
1117*a9800bebSGarrett D'Amore 	emlxs_be3_flash_dir_t *flash_dir;
1118*a9800bebSGarrett D'Amore 	emlxs_be3_flash_entry_t *entry;
1119*a9800bebSGarrett D'Amore 	emlxs_be3_image_header_t *flash_image_hdr;
1120*a9800bebSGarrett D'Amore 	emlxs_be3_image_header_t *image_hdr;
1121*a9800bebSGarrett D'Amore 	uint8_t *bptr;
1122*a9800bebSGarrett D'Amore 	uint32_t *wptr;
1123*a9800bebSGarrett D'Amore 	uint32_t i;
1124*a9800bebSGarrett D'Amore 	uint32_t value;
1125*a9800bebSGarrett D'Amore 	emlxs_be_fw_file_t *file;
1126*a9800bebSGarrett D'Amore 	emlxs_be_fw_file_t *file2;
1127*a9800bebSGarrett D'Amore 	uint32_t ufi_plus = 0;
1128*a9800bebSGarrett D'Amore 	uint32_t be_version = 0;
1129*a9800bebSGarrett D'Amore 	uint32_t found;
1130*a9800bebSGarrett D'Amore 
1131*a9800bebSGarrett D'Amore 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1132*a9800bebSGarrett D'Amore 
1133*a9800bebSGarrett D'Amore 	if (hba->model_info.chip != EMLXS_BE3_CHIP) {
1134*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1135*a9800bebSGarrett D'Amore 		    "Invalid adapter model.");
1136*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1137*a9800bebSGarrett D'Amore 	}
1138*a9800bebSGarrett D'Amore 
1139*a9800bebSGarrett D'Amore 	if (len < (sizeof (emlxs_be3_ufi_header_t) +
1140*a9800bebSGarrett D'Amore 	    sizeof (emlxs_be3_flash_dir_t))) {
1141*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1142*a9800bebSGarrett D'Amore 		    "Image too small. (%d < %d)",
1143*a9800bebSGarrett D'Amore 		    len, (sizeof (emlxs_be3_ufi_header_t) +
1144*a9800bebSGarrett D'Amore 		    sizeof (emlxs_be3_flash_dir_t)));
1145*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1146*a9800bebSGarrett D'Amore 	}
1147*a9800bebSGarrett D'Amore 
1148*a9800bebSGarrett D'Amore 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
1149*a9800bebSGarrett D'Amore 
1150*a9800bebSGarrett D'Amore 	/* Check if this is a standard BE3 image */
1151*a9800bebSGarrett D'Amore 	if (be_version != 3) {
1152*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1153*a9800bebSGarrett D'Amore 		    "Invalid image provided.");
1154*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1155*a9800bebSGarrett D'Amore 	}
1156*a9800bebSGarrett D'Amore 
1157*a9800bebSGarrett D'Amore 	ufi_hdr = (emlxs_be3_ufi_header_t *)buffer;
1158*a9800bebSGarrett D'Amore 
1159*a9800bebSGarrett D'Amore #ifdef EMLXS_BIG_ENDIAN
1160*a9800bebSGarrett D'Amore 	/* Big Endian Swapping */
1161*a9800bebSGarrett D'Amore 	/* Swap ufi header */
1162*a9800bebSGarrett D'Amore 	ufi_hdr->ufi_version =
1163*a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->ufi_version);
1164*a9800bebSGarrett D'Amore 	ufi_hdr->file_length =
1165*a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->file_length);
1166*a9800bebSGarrett D'Amore 	ufi_hdr->checksum =
1167*a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->checksum);
1168*a9800bebSGarrett D'Amore 	ufi_hdr->antidote =
1169*a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->antidote);
1170*a9800bebSGarrett D'Amore 	ufi_hdr->image_cnt =
1171*a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->image_cnt);
1172*a9800bebSGarrett D'Amore #endif /* EMLXS_BIG_ENDIAN */
1173*a9800bebSGarrett D'Amore 
1174*a9800bebSGarrett D'Amore 	if (len != ufi_hdr->file_length) {
1175*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1176*a9800bebSGarrett D'Amore 		    "Invalid image size (%d != %d)",
1177*a9800bebSGarrett D'Amore 		    len, ufi_hdr->file_length);
1178*a9800bebSGarrett D'Amore 
1179*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1180*a9800bebSGarrett D'Amore 	}
1181*a9800bebSGarrett D'Amore 
1182*a9800bebSGarrett D'Amore 	flash_image_hdr = NULL;
1183*a9800bebSGarrett D'Amore 	image_hdr = (emlxs_be3_image_header_t *)(buffer +
1184*a9800bebSGarrett D'Amore 	    sizeof (emlxs_be3_ufi_header_t));
1185*a9800bebSGarrett D'Amore 	for (i = 0; i < ufi_hdr->image_cnt; i++, image_hdr++) {
1186*a9800bebSGarrett D'Amore #ifdef EMLXS_BIG_ENDIAN
1187*a9800bebSGarrett D'Amore 		image_hdr->id = SWAP32(image_hdr->id);
1188*a9800bebSGarrett D'Amore 		image_hdr->offset = SWAP32(image_hdr->offset);
1189*a9800bebSGarrett D'Amore 		image_hdr->length = SWAP32(image_hdr->length);
1190*a9800bebSGarrett D'Amore 		image_hdr->checksum = SWAP32(image_hdr->checksum);
1191*a9800bebSGarrett D'Amore #endif /* EMLXS_BIG_ENDIAN */
1192*a9800bebSGarrett D'Amore 
1193*a9800bebSGarrett D'Amore 		if (image_hdr->id == UFI_BE3_FLASH_ID) {
1194*a9800bebSGarrett D'Amore 			flash_image_hdr = image_hdr;
1195*a9800bebSGarrett D'Amore 		}
1196*a9800bebSGarrett D'Amore 	}
1197*a9800bebSGarrett D'Amore 
1198*a9800bebSGarrett D'Amore 	if (!flash_image_hdr) {
1199*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1200*a9800bebSGarrett D'Amore 		    "No flash image found.");
1201*a9800bebSGarrett D'Amore 
1202*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1203*a9800bebSGarrett D'Amore 	}
1204*a9800bebSGarrett D'Amore 
1205*a9800bebSGarrett D'Amore 	/* Scan for flash dir signature */
1206*a9800bebSGarrett D'Amore 	bptr = (uint8_t *)buffer + flash_image_hdr->offset;
1207*a9800bebSGarrett D'Amore 	flash_dir = NULL;
1208*a9800bebSGarrett D'Amore 	for (i = 0; i < flash_image_hdr->length; i++, bptr++) {
1209*a9800bebSGarrett D'Amore 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
1210*a9800bebSGarrett D'Amore 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
1211*a9800bebSGarrett D'Amore 			flash_dir = (emlxs_be3_flash_dir_t *)bptr;
1212*a9800bebSGarrett D'Amore 			break;
1213*a9800bebSGarrett D'Amore 		}
1214*a9800bebSGarrett D'Amore 	}
1215*a9800bebSGarrett D'Amore 
1216*a9800bebSGarrett D'Amore 	if (!flash_dir) {
1217*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1218*a9800bebSGarrett D'Amore 		    "Unable to find flash directory.");
1219*a9800bebSGarrett D'Amore 
1220*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1221*a9800bebSGarrett D'Amore 	}
1222*a9800bebSGarrett D'Amore 
1223*a9800bebSGarrett D'Amore #ifdef EMLXS_BIG_ENDIAN
1224*a9800bebSGarrett D'Amore 	/* Big Endian Swapping */
1225*a9800bebSGarrett D'Amore 	/* Swap flash dir */
1226*a9800bebSGarrett D'Amore 	flash_dir->header.format_rev =
1227*a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.format_rev);
1228*a9800bebSGarrett D'Amore 	flash_dir->header.checksum =
1229*a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.checksum);
1230*a9800bebSGarrett D'Amore 	flash_dir->header.antidote =
1231*a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.antidote);
1232*a9800bebSGarrett D'Amore 	flash_dir->header.entry_count =
1233*a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.entry_count);
1234*a9800bebSGarrett D'Amore 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
1235*a9800bebSGarrett D'Amore 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
1236*a9800bebSGarrett D'Amore 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
1237*a9800bebSGarrett D'Amore 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
1238*a9800bebSGarrett D'Amore 
1239*a9800bebSGarrett D'Amore 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1240*a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].vendor_id =
1241*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].vendor_id);
1242*a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].device_id =
1243*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].device_id);
1244*a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].sub_vendor_id =
1245*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
1246*a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].sub_device_id =
1247*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
1248*a9800bebSGarrett D'Amore 	}
1249*a9800bebSGarrett D'Amore 
1250*a9800bebSGarrett D'Amore 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1251*a9800bebSGarrett D'Amore 		entry = &flash_dir->entry[i];
1252*a9800bebSGarrett D'Amore 
1253*a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
1254*a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
1255*a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
1256*a9800bebSGarrett D'Amore 			continue;
1257*a9800bebSGarrett D'Amore 		}
1258*a9800bebSGarrett D'Amore 
1259*a9800bebSGarrett D'Amore 		flash_dir->entry[i].type =
1260*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].type);
1261*a9800bebSGarrett D'Amore 		flash_dir->entry[i].offset =
1262*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].offset);
1263*a9800bebSGarrett D'Amore 		flash_dir->entry[i].block_size =
1264*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].block_size);
1265*a9800bebSGarrett D'Amore 		flash_dir->entry[i].image_size =
1266*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].image_size);
1267*a9800bebSGarrett D'Amore 		flash_dir->entry[i].checksum =
1268*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].checksum);
1269*a9800bebSGarrett D'Amore 		flash_dir->entry[i].entry_point =
1270*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].entry_point);
1271*a9800bebSGarrett D'Amore 		flash_dir->entry[i].resv0 =
1272*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].resv0);
1273*a9800bebSGarrett D'Amore 		flash_dir->entry[i].resv1 =
1274*a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].resv1);
1275*a9800bebSGarrett D'Amore 	}
1276*a9800bebSGarrett D'Amore #endif /* EMLXS_BIG_ENDIAN */
1277*a9800bebSGarrett D'Amore 
1278*a9800bebSGarrett D'Amore 	/* Verify image checksum */
1279*a9800bebSGarrett D'Amore 	if (flash_dir->header.checksum != flash_image_hdr->checksum) {
1280*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1281*a9800bebSGarrett D'Amore 		    "Invalid flash directory checksum. (%x != %x)\n",
1282*a9800bebSGarrett D'Amore 		    flash_dir->header.checksum, flash_image_hdr->checksum);
1283*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1284*a9800bebSGarrett D'Amore 	}
1285*a9800bebSGarrett D'Amore 
1286*a9800bebSGarrett D'Amore 	/* Verify adapter model */
1287*a9800bebSGarrett D'Amore 	found = 0;
1288*a9800bebSGarrett D'Amore 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1289*a9800bebSGarrett D'Amore 		if (flash_dir->header.controller[i].device_id ==
1290*a9800bebSGarrett D'Amore 		    hba->model_info.device_id) {
1291*a9800bebSGarrett D'Amore 			found = 1;
1292*a9800bebSGarrett D'Amore 		}
1293*a9800bebSGarrett D'Amore 	}
1294*a9800bebSGarrett D'Amore 
1295*a9800bebSGarrett D'Amore 	if (!found) {
1296*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1297*a9800bebSGarrett D'Amore 		    "Invalid adapter device id=0x%x.",
1298*a9800bebSGarrett D'Amore 		    hba->model_info.device_id);
1299*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1300*a9800bebSGarrett D'Amore 	}
1301*a9800bebSGarrett D'Amore 
1302*a9800bebSGarrett D'Amore 	/* Build fw_image table */
1303*a9800bebSGarrett D'Amore 	fw_image->be_version = 3;
1304*a9800bebSGarrett D'Amore 	fw_image->ufi_plus = ufi_plus;
1305*a9800bebSGarrett D'Amore 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1306*a9800bebSGarrett D'Amore 		entry = &flash_dir->entry[i];
1307*a9800bebSGarrett D'Amore 
1308*a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
1309*a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
1310*a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
1311*a9800bebSGarrett D'Amore 			continue;
1312*a9800bebSGarrett D'Amore 		}
1313*a9800bebSGarrett D'Amore 
1314*a9800bebSGarrett D'Amore 		switch (entry->type) {
1315*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_REDBOOT:
1316*a9800bebSGarrett D'Amore 			file = &fw_image->file[REDBOOT_FLASHTYPE];
1317*a9800bebSGarrett D'Amore 			(void) strcpy(file->label, "REDBOOT");
1318*a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
1319*a9800bebSGarrett D'Amore 			break;
1320*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_ISCSI_BIOS:
1321*a9800bebSGarrett D'Amore 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1322*a9800bebSGarrett D'Amore 			(void) strcpy(file->label, "ISCSI BIOS");
1323*a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
1324*a9800bebSGarrett D'Amore 			break;
1325*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_PXE_BIOS:
1326*a9800bebSGarrett D'Amore 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1327*a9800bebSGarrett D'Amore 			(void) strcpy(file->label, "PXE BIOS");
1328*a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
1329*a9800bebSGarrett D'Amore 			break;
1330*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FCOE_BIOS:
1331*a9800bebSGarrett D'Amore 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1332*a9800bebSGarrett D'Amore 			(void) strcpy(file->label, "FCOE BIOS");
1333*a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
1334*a9800bebSGarrett D'Amore 			break;
1335*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
1336*a9800bebSGarrett D'Amore 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1337*a9800bebSGarrett D'Amore 			(void) strcpy(file->label, "ISCSI FIRMWARE");
1338*a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
1339*a9800bebSGarrett D'Amore 			break;
1340*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FCOE_FIRMWARE:
1341*a9800bebSGarrett D'Amore 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1342*a9800bebSGarrett D'Amore 			(void) strcpy(file->label, "FCOE FIRMWARE");
1343*a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
1344*a9800bebSGarrett D'Amore 			break;
1345*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_NCSI_FIRMWARE:
1346*a9800bebSGarrett D'Amore 			file = &fw_image->file[NCSI_FIRMWARE_FLASHTYPE];
1347*a9800bebSGarrett D'Amore 			(void) strcpy(file->label, "NCSI FIRMWARE");
1348*a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_NCSI_FIRMWARE;
1349*a9800bebSGarrett D'Amore 			break;
1350*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FLASH_ISM:
1351*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FCOE_BACKUP:
1352*a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_ISCSI_BACKUP:
1353*a9800bebSGarrett D'Amore 			continue;
1354*a9800bebSGarrett D'Amore 
1355*a9800bebSGarrett D'Amore 		default:
1356*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1357*a9800bebSGarrett D'Amore 			    "Unknown image type found.  type=%x",
1358*a9800bebSGarrett D'Amore 			    entry->type);
1359*a9800bebSGarrett D'Amore 			continue;
1360*a9800bebSGarrett D'Amore 		}
1361*a9800bebSGarrett D'Amore 
1362*a9800bebSGarrett D'Amore 		file->be_version = fw_image->be_version;
1363*a9800bebSGarrett D'Amore 		file->ufi_plus = fw_image->ufi_plus;
1364*a9800bebSGarrett D'Amore 		file->image_size = entry->image_size;
1365*a9800bebSGarrett D'Amore 
1366*a9800bebSGarrett D'Amore 		if (ufi_plus) {
1367*a9800bebSGarrett D'Amore 			file->image_offset = entry->offset;
1368*a9800bebSGarrett D'Amore 			file->block_size   = entry->block_size;
1369*a9800bebSGarrett D'Amore 			file->block_crc    = entry->checksum;
1370*a9800bebSGarrett D'Amore 			file->load_address = entry->entry_point;
1371*a9800bebSGarrett D'Amore 		} else {
1372*a9800bebSGarrett D'Amore 			file->image_offset = entry->offset +
1373*a9800bebSGarrett D'Amore 			    flash_image_hdr->offset;
1374*a9800bebSGarrett D'Amore 			file->block_size   = entry->block_size;
1375*a9800bebSGarrett D'Amore 
1376*a9800bebSGarrett D'Amore 			wptr = (uint32_t *)(buffer +  file->image_offset +
1377*a9800bebSGarrett D'Amore 			    file->block_size);
1378*a9800bebSGarrett D'Amore 
1379*a9800bebSGarrett D'Amore 			/* Read load address */
1380*a9800bebSGarrett D'Amore 			value = *(wptr - 3);
1381*a9800bebSGarrett D'Amore 			file->load_address = BE_SWAP32(value);
1382*a9800bebSGarrett D'Amore 
1383*a9800bebSGarrett D'Amore 			/* Read block_crc */
1384*a9800bebSGarrett D'Amore 			value = *(wptr - 1);
1385*a9800bebSGarrett D'Amore 			file->block_crc = BE_SWAP32(value);
1386*a9800bebSGarrett D'Amore 		}
1387*a9800bebSGarrett D'Amore 
1388*a9800bebSGarrett D'Amore 		/* Make sure image will fit in block specified */
1389*a9800bebSGarrett D'Amore 		if (file->image_size + 12 > file->block_size) {
1390*a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1391*a9800bebSGarrett D'Amore 			    "%s: Image too large for block. image=%x block=%x",
1392*a9800bebSGarrett D'Amore 			    file->label, file->image_size, file->block_size);
1393*a9800bebSGarrett D'Amore 
1394*a9800bebSGarrett D'Amore 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1395*a9800bebSGarrett D'Amore 			return (EMLXS_IMAGE_BAD);
1396*a9800bebSGarrett D'Amore 		}
1397*a9800bebSGarrett D'Amore 
1398*a9800bebSGarrett D'Amore 		/* Automatically create a backup file entry for firmware */
1399*a9800bebSGarrett D'Amore 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1400*a9800bebSGarrett D'Amore 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1401*a9800bebSGarrett D'Amore 
1402*a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1403*a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
1404*a9800bebSGarrett D'Amore 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1405*a9800bebSGarrett D'Amore 			(void) strcpy(file2->label, "FCOE BACKUP");
1406*a9800bebSGarrett D'Amore 
1407*a9800bebSGarrett D'Amore 			/* Save FCOE version info */
1408*a9800bebSGarrett D'Amore 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1409*a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
1410*a9800bebSGarrett D'Amore 			    BE_VERSION_SIZE);
1411*a9800bebSGarrett D'Amore 			fw_image->fcoe_version = file->block_crc;
1412*a9800bebSGarrett D'Amore 
1413*a9800bebSGarrett D'Amore 		} else if (file->type ==
1414*a9800bebSGarrett D'Amore 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1415*a9800bebSGarrett D'Amore 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1416*a9800bebSGarrett D'Amore 
1417*a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1418*a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
141982527734SSukumar Swaminathan 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1420*a9800bebSGarrett D'Amore 			(void) strcpy(file2->label, "ISCSI BACKUP");
1421*a9800bebSGarrett D'Amore 
1422*a9800bebSGarrett D'Amore 			/* Save ISCSI version info */
1423*a9800bebSGarrett D'Amore 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1424*a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1425*a9800bebSGarrett D'Amore 			    BE_VERSION_SIZE);
1426*a9800bebSGarrett D'Amore 			fw_image->iscsi_version = file->block_crc;
142782527734SSukumar Swaminathan 		}
142882527734SSukumar Swaminathan 	}
142982527734SSukumar Swaminathan 
1430*a9800bebSGarrett D'Amore 	if (fw_image->fcoe_version == 0) {
143182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
143282527734SSukumar Swaminathan 		    "Unable to find FCOE firmware component.");
143382527734SSukumar Swaminathan 
143482527734SSukumar Swaminathan 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
143582527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
143682527734SSukumar Swaminathan 	}
143782527734SSukumar Swaminathan 
143882527734SSukumar Swaminathan 	/* Display contents */
143982527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1440*a9800bebSGarrett D'Amore 	    "BE3 UFI Image: %08x, %s", fw_image->fcoe_version,
1441*a9800bebSGarrett D'Amore 	    fw_image->fcoe_label);
144282527734SSukumar Swaminathan 
144382527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
144482527734SSukumar Swaminathan 		file = &fw_image->file[i];
144582527734SSukumar Swaminathan 
144682527734SSukumar Swaminathan 		if (file->image_size == 0) {
144782527734SSukumar Swaminathan 			continue;
144882527734SSukumar Swaminathan 		}
144982527734SSukumar Swaminathan 
145082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1451*a9800bebSGarrett D'Amore 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1452*a9800bebSGarrett D'Amore 		    "load=%x",
1453*a9800bebSGarrett D'Amore 		    file->label, file->be_version, (file->ufi_plus)? "+":"",
1454*a9800bebSGarrett D'Amore 		    file->type, file->block_size, file->image_size,
1455*a9800bebSGarrett D'Amore 		    file->image_offset, file->block_crc, file->load_address);
145682527734SSukumar Swaminathan 	}
145782527734SSukumar Swaminathan 
145882527734SSukumar Swaminathan 	return (0);
145982527734SSukumar Swaminathan 
1460*a9800bebSGarrett D'Amore } /* emlxs_be3_validate_image() */
146182527734SSukumar Swaminathan 
146282527734SSukumar Swaminathan 
146382527734SSukumar Swaminathan static int32_t
146482527734SSukumar Swaminathan emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
146582527734SSukumar Swaminathan     uint32_t offline)
146682527734SSukumar Swaminathan {
146782527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
146882527734SSukumar Swaminathan 	uint32_t i;
146982527734SSukumar Swaminathan 	uint32_t update = 0;
147082527734SSukumar Swaminathan 	uint32_t rval = 0;
147182527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
147282527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
147382527734SSukumar Swaminathan 	emlxs_be_fw_image_t fw_image;
147482527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file;
1475*a9800bebSGarrett D'Amore 	uint32_t be_version;
147682527734SSukumar Swaminathan 
147782527734SSukumar Swaminathan 	/* For now we will not take the driver offline during a download */
147882527734SSukumar Swaminathan 	offline = 0;
147982527734SSukumar Swaminathan 
148082527734SSukumar Swaminathan 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
148182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
148282527734SSukumar Swaminathan 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
148382527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
148482527734SSukumar Swaminathan 	}
148582527734SSukumar Swaminathan 
148682527734SSukumar Swaminathan 	if (buffer == NULL || len == 0) {
148782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
148882527734SSukumar Swaminathan 		    "Empty buffer provided. buf=%p size=%d", buffer, len);
148982527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
149082527734SSukumar Swaminathan 	}
149182527734SSukumar Swaminathan 
1492*a9800bebSGarrett D'Amore 	be_version = emlxs_be_version(buffer, len, 0);
1493*a9800bebSGarrett D'Amore 
1494*a9800bebSGarrett D'Amore 	switch (be_version) {
1495*a9800bebSGarrett D'Amore 	case 0:
1496*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1497*a9800bebSGarrett D'Amore 		    "Invalid image provided. Non-UFI format.");
1498*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1499*a9800bebSGarrett D'Amore 	case 2:
1500*a9800bebSGarrett D'Amore 		rval = emlxs_be2_validate_image(hba, buffer, len, &fw_image);
1501*a9800bebSGarrett D'Amore 		if (rval) {
1502*a9800bebSGarrett D'Amore 			return (rval);
1503*a9800bebSGarrett D'Amore 		}
1504*a9800bebSGarrett D'Amore 		break;
1505*a9800bebSGarrett D'Amore 	case 3:
1506*a9800bebSGarrett D'Amore 		rval = emlxs_be3_validate_image(hba, buffer, len, &fw_image);
1507*a9800bebSGarrett D'Amore 		if (rval) {
1508*a9800bebSGarrett D'Amore 			return (rval);
1509*a9800bebSGarrett D'Amore 		}
1510*a9800bebSGarrett D'Amore 		break;
1511*a9800bebSGarrett D'Amore 	default:
1512*a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1513*a9800bebSGarrett D'Amore 		    "Invalid image provided. Unknown BE version. (%x)",
1514*a9800bebSGarrett D'Amore 		    be_version);
1515*a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
151682527734SSukumar Swaminathan 	}
151782527734SSukumar Swaminathan 
151882527734SSukumar Swaminathan 	/* Allocate resources */
151982527734SSukumar Swaminathan 
152082527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
152182527734SSukumar Swaminathan 	    KM_SLEEP)) == NULL) {
152282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
152382527734SSukumar Swaminathan 		    "Unable to allocate mailbox buffer.");
152482527734SSukumar Swaminathan 
152582527734SSukumar Swaminathan 		offline = 0;
152682527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
152782527734SSukumar Swaminathan 		goto done;
152882527734SSukumar Swaminathan 	}
152982527734SSukumar Swaminathan 
153082527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
153182527734SSukumar Swaminathan 	    sizeof (IOCTL_COMMON_FLASHROM) + BE_MAX_XFER_SIZE))) == NULL) {
153282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
153382527734SSukumar Swaminathan 		    "Unable to allocate flash buffer.");
153482527734SSukumar Swaminathan 
153582527734SSukumar Swaminathan 		offline = 0;
153682527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
153782527734SSukumar Swaminathan 		goto done;
153882527734SSukumar Swaminathan 	}
153982527734SSukumar Swaminathan 
154082527734SSukumar Swaminathan 	/* Check if update is required */
154182527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
154282527734SSukumar Swaminathan 		file = &fw_image.file[i];
154382527734SSukumar Swaminathan 
154482527734SSukumar Swaminathan 		if (file->image_size == 0) {
154582527734SSukumar Swaminathan 			continue;
154682527734SSukumar Swaminathan 		}
154782527734SSukumar Swaminathan 
154882527734SSukumar Swaminathan 		rval = emlxs_sli4_verify_crc(hba, file, mbq, mp);
1549fcf3ce44SJohn Forte 
155082527734SSukumar Swaminathan 		if (rval == 0) {
1551*a9800bebSGarrett D'Amore 			/* Do not update */
155282527734SSukumar Swaminathan 			file->image_size = 0;
155382527734SSukumar Swaminathan 			continue;
155482527734SSukumar Swaminathan 		}
155582527734SSukumar Swaminathan 
155682527734SSukumar Swaminathan 		update++;
155782527734SSukumar Swaminathan 	}
155882527734SSukumar Swaminathan 
155982527734SSukumar Swaminathan 	if (!update) {
156082527734SSukumar Swaminathan 		offline = 0;
1561*a9800bebSGarrett D'Amore 		rval = 0;
156282527734SSukumar Swaminathan 		goto done;
156382527734SSukumar Swaminathan 	}
156482527734SSukumar Swaminathan 
156582527734SSukumar Swaminathan 	/*
156682527734SSukumar Swaminathan 	 * Everything checks out, now to just do it
156782527734SSukumar Swaminathan 	 */
156882527734SSukumar Swaminathan 	if (offline) {
156982527734SSukumar Swaminathan 		if (emlxs_offline(hba) != FC_SUCCESS) {
157082527734SSukumar Swaminathan 
157182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
157282527734SSukumar Swaminathan 			    "Unable to take adapter offline.");
157382527734SSukumar Swaminathan 
157482527734SSukumar Swaminathan 			offline = 0;
157582527734SSukumar Swaminathan 			rval = EMLXS_OFFLINE_FAILED;
157682527734SSukumar Swaminathan 			goto done;
157782527734SSukumar Swaminathan 		}
157882527734SSukumar Swaminathan 	}
157982527734SSukumar Swaminathan 
158082527734SSukumar Swaminathan 	/* Download entries which require update */
158182527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
158282527734SSukumar Swaminathan 		file = &fw_image.file[i];
158382527734SSukumar Swaminathan 
158482527734SSukumar Swaminathan 		if (file->image_size == 0) {
158582527734SSukumar Swaminathan 			continue;
158682527734SSukumar Swaminathan 		}
158782527734SSukumar Swaminathan 
158882527734SSukumar Swaminathan 		rval = emlxs_sli4_flash_image(hba, buffer, file, mbq, mp);
158982527734SSukumar Swaminathan 
159082527734SSukumar Swaminathan 		if (rval != 0) {
159182527734SSukumar Swaminathan 			goto done;
159282527734SSukumar Swaminathan 		}
159382527734SSukumar Swaminathan 	}
159482527734SSukumar Swaminathan 
159582527734SSukumar Swaminathan done:
159682527734SSukumar Swaminathan 	if (mbq) {
1597*a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
159882527734SSukumar Swaminathan 	}
159982527734SSukumar Swaminathan 
160082527734SSukumar Swaminathan 	if (mp) {
1601*a9800bebSGarrett D'Amore 		emlxs_mem_buf_free(hba, mp);
160282527734SSukumar Swaminathan 	}
160382527734SSukumar Swaminathan 
160482527734SSukumar Swaminathan 	if (offline) {
160582527734SSukumar Swaminathan 		(void) emlxs_online(hba);
160682527734SSukumar Swaminathan 	}
160782527734SSukumar Swaminathan 
160882527734SSukumar Swaminathan 	if (rval == 0) {
160982527734SSukumar Swaminathan 		if (update) {
161082527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
161182527734SSukumar Swaminathan 			    "Status good.");
161282527734SSukumar Swaminathan 
161382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
161482527734SSukumar Swaminathan 			    "Please reboot system or power cycle adapter "
1615*a9800bebSGarrett D'Amore 			    "to activate new firmware: %s",
1616*a9800bebSGarrett D'Amore 			    fw_image.fcoe_label);
161782527734SSukumar Swaminathan 
161882527734SSukumar Swaminathan 		} else {
161982527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
162082527734SSukumar Swaminathan 			    "No firmware update required.");
162182527734SSukumar Swaminathan 		}
162282527734SSukumar Swaminathan 	}
162382527734SSukumar Swaminathan 
162482527734SSukumar Swaminathan 	return (rval);
162582527734SSukumar Swaminathan 
162682527734SSukumar Swaminathan } /* emlxs_sli4_fw_download() */
1627fcf3ce44SJohn Forte 
1628fcf3ce44SJohn Forte 
1629fcf3ce44SJohn Forte extern int32_t
1630fcf3ce44SJohn Forte emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer,
1631fcf3ce44SJohn Forte     uint32_t len)
1632fcf3ce44SJohn Forte {
1633fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1634fcf3ce44SJohn Forte 	MAILBOXQ *mbox = NULL;
1635fcf3ce44SJohn Forte 	MAILBOX *mb;
1636fcf3ce44SJohn Forte 	uint32_t rval = 0;
1637fcf3ce44SJohn Forte 	uint32_t region_id;
1638fcf3ce44SJohn Forte 	uint32_t id;
163982527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
1640fcf3ce44SJohn Forte 	caddr_t local_buffer;
1641fcf3ce44SJohn Forte 	uint32_t *bptr1;
1642fcf3ce44SJohn Forte 	uint32_t *bptr2;
1643fcf3ce44SJohn Forte 	uint32_t i;
164482527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
1645fcf3ce44SJohn Forte 
1646fcf3ce44SJohn Forte 	if (buffer == NULL || len == 0) {
1647fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1648fcf3ce44SJohn Forte 	}
164982527734SSukumar Swaminathan 
165082527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
1651fcf3ce44SJohn Forte 	/* We need to swap the image buffer before we start */
1652fcf3ce44SJohn Forte 
1653fcf3ce44SJohn Forte 	/*
1654fcf3ce44SJohn Forte 	 * Use KM_SLEEP to allocate a temporary buffer
1655fcf3ce44SJohn Forte 	 */
1656fcf3ce44SJohn Forte 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
1657fcf3ce44SJohn Forte 
1658fcf3ce44SJohn Forte 	/* Perform a 32 bit swap of the image */
1659fcf3ce44SJohn Forte 	bptr1 = (uint32_t *)local_buffer;
1660fcf3ce44SJohn Forte 	bptr2 = (uint32_t *)buffer;
1661fcf3ce44SJohn Forte 
1662fcf3ce44SJohn Forte 	for (i = 0; i < (len / 4); i++) {
166382527734SSukumar Swaminathan 		*bptr1 = SWAP32(*bptr2);
1664fcf3ce44SJohn Forte 		bptr1++;
1665fcf3ce44SJohn Forte 		bptr2++;
1666fcf3ce44SJohn Forte 	}
1667fcf3ce44SJohn Forte 
1668fcf3ce44SJohn Forte 	/* Replace the original buffer */
1669fcf3ce44SJohn Forte 	buffer = local_buffer;
1670fcf3ce44SJohn Forte 
167182527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
1672fcf3ce44SJohn Forte 
1673fcf3ce44SJohn Forte 	if (len > 128) {
1674fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1675291a2b48SSukumar Swaminathan 		    "Invalid image length: 0x%x > 128", len);
1676fcf3ce44SJohn Forte 
1677fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1678fcf3ce44SJohn Forte 	}
1679291a2b48SSukumar Swaminathan 
1680fcf3ce44SJohn Forte 	/* Check the region number */
1681fcf3ce44SJohn Forte 	if ((region > 2) && (region != 0xff)) {
1682fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1683291a2b48SSukumar Swaminathan 		    "Invalid region id: 0x%x", region);
1684fcf3ce44SJohn Forte 
1685fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1686fcf3ce44SJohn Forte 
1687fcf3ce44SJohn Forte 	}
1688291a2b48SSukumar Swaminathan 
1689fcf3ce44SJohn Forte 	/* Check the image vendor id */
1690fcf3ce44SJohn Forte 	id = *(int32_t *)buffer;
1691fcf3ce44SJohn Forte 	if ((id & 0xffff) != 0x10df) {
1692fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1693291a2b48SSukumar Swaminathan 		    "Invalid image id: 0x%x", id);
1694fcf3ce44SJohn Forte 
1695fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1696fcf3ce44SJohn Forte 	}
1697291a2b48SSukumar Swaminathan 
1698291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1699291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1700fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1701fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
1702fcf3ce44SJohn Forte 
1703fcf3ce44SJohn Forte 		rval = 1;
1704fcf3ce44SJohn Forte 
1705fcf3ce44SJohn Forte 		goto done;
1706fcf3ce44SJohn Forte 	}
1707291a2b48SSukumar Swaminathan 
1708fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
1709fcf3ce44SJohn Forte 
1710fcf3ce44SJohn Forte 	/*
1711fcf3ce44SJohn Forte 	 * Everything checks out, now to just do it
1712fcf3ce44SJohn Forte 	 */
1713fcf3ce44SJohn Forte 	if (emlxs_offline(hba) != FC_SUCCESS) {
1714fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1715fcf3ce44SJohn Forte 		    "Unable to take HBA offline.");
1716fcf3ce44SJohn Forte 
1717fcf3ce44SJohn Forte 		rval = EMLXS_OFFLINE_FAILED;
1718fcf3ce44SJohn Forte 
1719fcf3ce44SJohn Forte 		goto done;
1720fcf3ce44SJohn Forte 	}
1721291a2b48SSukumar Swaminathan 
172282527734SSukumar Swaminathan 	if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
1723fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1724fcf3ce44SJohn Forte 		    "Unable to restart adapter.");
1725fcf3ce44SJohn Forte 
1726fcf3ce44SJohn Forte 		rval = EMLXS_OFFLINE_FAILED;
1727fcf3ce44SJohn Forte 
1728fcf3ce44SJohn Forte 		goto done;
1729fcf3ce44SJohn Forte 	}
1730291a2b48SSukumar Swaminathan 
1731fcf3ce44SJohn Forte 	/* Check if default region is requested */
1732fcf3ce44SJohn Forte 	if (region == 0xff) {
1733fcf3ce44SJohn Forte 		/*
1734291a2b48SSukumar Swaminathan 		 * Sun-branded Helios and Zypher have different
1735291a2b48SSukumar Swaminathan 		 * default PCI region
1736fcf3ce44SJohn Forte 		 */
1737fcf3ce44SJohn Forte 		if ((hba->model_info.flags & EMLXS_SUN_BRANDED) &&
1738fcf3ce44SJohn Forte 		    (hba->model_info.chip &
1739fcf3ce44SJohn Forte 		    (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
1740fcf3ce44SJohn Forte 			region = 2;
1741fcf3ce44SJohn Forte 		} else {
1742fcf3ce44SJohn Forte 			region = 0;
1743fcf3ce44SJohn Forte 		}
1744fcf3ce44SJohn Forte 	}
1745291a2b48SSukumar Swaminathan 
1746fcf3ce44SJohn Forte 	/* Set region id based on PCI region requested */
1747fcf3ce44SJohn Forte 	region_id = DEF_PCI_CFG_REGION_ID + region;
1748fcf3ce44SJohn Forte 
1749fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1750291a2b48SSukumar Swaminathan 	    "PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
1751291a2b48SSukumar Swaminathan 	    region_id, id, len);
1752fcf3ce44SJohn Forte 
1753fcf3ce44SJohn Forte 	/* Copy the data buffer to SLIM */
1754fcf3ce44SJohn Forte 	WRITE_SLIM_COPY(hba, (uint32_t *)buffer,
175582527734SSukumar Swaminathan 	    (volatile uint32_t *)((volatile char *)hba->sli.sli3.slim_addr +
1756291a2b48SSukumar Swaminathan 	    sizeof (MAILBOX)), (len / sizeof (uint32_t)));
1757fcf3ce44SJohn Forte 
17584baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
175982527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
17604baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
17614baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
17624baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
17634baa2c25SSukumar Swaminathan 		rval = 1;
17644baa2c25SSukumar Swaminathan 	}
17654baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
17664baa2c25SSukumar Swaminathan 
176782527734SSukumar Swaminathan 	emlxs_format_update_pci_cfg(hba, mbox, region_id, len);
1768fcf3ce44SJohn Forte 
176982527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
1770fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1771291a2b48SSukumar Swaminathan 		    "Unable to update PCI configuration: Mailbox cmd=%x "
1772291a2b48SSukumar Swaminathan 		    "status=%x info=%d", mb->mbxCommand, mb->mbxStatus,
1773fcf3ce44SJohn Forte 		    mb->un.varUpdateCfg.rsp_info);
1774fcf3ce44SJohn Forte 
1775fcf3ce44SJohn Forte 		rval = 1;
1776fcf3ce44SJohn Forte 	}
1777291a2b48SSukumar Swaminathan 
1778fcf3ce44SJohn Forte 	(void) emlxs_online(hba);
1779fcf3ce44SJohn Forte 
1780fcf3ce44SJohn Forte 	if (rval == 0) {
1781fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1782fcf3ce44SJohn Forte 		    "Status good.");
1783fcf3ce44SJohn Forte 	}
1784291a2b48SSukumar Swaminathan 
1785fcf3ce44SJohn Forte done:
1786fcf3ce44SJohn Forte 
1787fcf3ce44SJohn Forte 	if (mbox) {
1788fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
1789fcf3ce44SJohn Forte 	}
179082527734SSukumar Swaminathan 
179182527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
1792fcf3ce44SJohn Forte 	/* Free the local buffer */
1793fcf3ce44SJohn Forte 	kmem_free(local_buffer, len);
179482527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
1795fcf3ce44SJohn Forte 
1796fcf3ce44SJohn Forte 	return (rval);
1797fcf3ce44SJohn Forte 
179882527734SSukumar Swaminathan } /* emlxs_cfl_download */
1799fcf3ce44SJohn Forte 
1800fcf3ce44SJohn Forte 
1801fcf3ce44SJohn Forte static uint32_t
1802fcf3ce44SJohn Forte emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr)
1803fcf3ce44SJohn Forte {
1804fcf3ce44SJohn Forte 	uint32_t Temp;
1805fcf3ce44SJohn Forte 	uint32_t CkSum;
1806fcf3ce44SJohn Forte 
1807fcf3ce44SJohn Forte 	EndAddr++;
1808fcf3ce44SJohn Forte 	CkSum = SLI_CKSUM_SEED;
1809fcf3ce44SJohn Forte 
1810fcf3ce44SJohn Forte 	CkSum = (CkSum >> 1) | (CkSum << 31);
1811fcf3ce44SJohn Forte 	while (StartAddr != EndAddr) {
1812fcf3ce44SJohn Forte 		CkSum = (CkSum << 1) | (CkSum >> 31);
1813fcf3ce44SJohn Forte 		Temp = *StartAddr;
1814fcf3ce44SJohn Forte 
1815fcf3ce44SJohn Forte 		CkSum ^= Temp;
1816fcf3ce44SJohn Forte 		StartAddr++;
1817fcf3ce44SJohn Forte 	}
1818fcf3ce44SJohn Forte 
1819fcf3ce44SJohn Forte 	return (CkSum << 1) | (CkSum >> 31);
1820fcf3ce44SJohn Forte 
182182527734SSukumar Swaminathan } /* emlxs_valid_cksum() */
1822fcf3ce44SJohn Forte 
1823fcf3ce44SJohn Forte 
1824fcf3ce44SJohn Forte static void
1825fcf3ce44SJohn Forte emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr)
1826fcf3ce44SJohn Forte {
1827fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1828fcf3ce44SJohn Forte 
1829291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: ");
1830fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1831fcf3ce44SJohn Forte 	    "AIF Header: compress_br = 0x%x", AifHdr->CompressBr);
1832fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1833fcf3ce44SJohn Forte 	    "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr);
1834fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1835fcf3ce44SJohn Forte 	    "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr);
1836fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1837fcf3ce44SJohn Forte 	    "AIF Header: entry_br = 0x%x", AifHdr->EntryBr);
1838fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1839fcf3ce44SJohn Forte 	    "AIF Header: area_id = 0x%x", AifHdr->Area_ID);
1840fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1841fcf3ce44SJohn Forte 	    "AIF Header: rosize = 0x%x", AifHdr->RoSize);
1842fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1843fcf3ce44SJohn Forte 	    "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize);
1844fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1845fcf3ce44SJohn Forte 	    "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize);
1846fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1847fcf3ce44SJohn Forte 	    "AIF Header: dbgtype = 0x%x", AifHdr->DbgType);
1848fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1849fcf3ce44SJohn Forte 	    "AIF Header: imagebase = 0x%x", AifHdr->ImageBase);
1850fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1851fcf3ce44SJohn Forte 	    "AIF Header: area_size = 0x%x", AifHdr->Area_Size);
1852fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1853fcf3ce44SJohn Forte 	    "AIF Header: address_mode = 0x%x", AifHdr->AddressMode);
1854fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1855fcf3ce44SJohn Forte 	    "AIF Header: database = 0x%x", AifHdr->DataBase);
1856fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1857fcf3ce44SJohn Forte 	    "AIF Header: aversion = 0x%x", AifHdr->AVersion);
1858fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1859fcf3ce44SJohn Forte 	    "AIF Header: spare2 = 0x%x", AifHdr->Spare2);
1860fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1861fcf3ce44SJohn Forte 	    "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi);
1862fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1863fcf3ce44SJohn Forte 	    "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]);
1864fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1865fcf3ce44SJohn Forte 	    "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]);
1866fcf3ce44SJohn Forte 
186782527734SSukumar Swaminathan } /* emlxs_disp_aif_header() */
1868fcf3ce44SJohn Forte 
1869fcf3ce44SJohn Forte 
1870fcf3ce44SJohn Forte 
1871fcf3ce44SJohn Forte static void
1872fcf3ce44SJohn Forte emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image)
1873fcf3ce44SJohn Forte {
1874fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1875fcf3ce44SJohn Forte 
1876291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: ");
1877fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1878fcf3ce44SJohn Forte 	    "Img Header: BlockSize = 0x%x", image->BlockSize);
1879fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1880fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Type = 0x%x", image->Id.Type);
1881fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1882fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Id = 0x%x", image->Id.Id);
1883fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1884fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver);
1885fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1886fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev);
1887fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1888fcf3ce44SJohn Forte 	    "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp);
1889fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1890fcf3ce44SJohn Forte 	    "Img Header: Flags = 0x%x", image->Flags);
1891fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1892fcf3ce44SJohn Forte 	    "Img Header: EntryAdr = 0x%x", image->EntryAdr);
1893fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1894fcf3ce44SJohn Forte 	    "Img Header: InitAdr = 0x%x", image->InitAdr);
1895fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1896fcf3ce44SJohn Forte 	    "Img Header: ExitAdr = 0x%x", image->ExitAdr);
1897fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1898fcf3ce44SJohn Forte 	    "Img Header: ImageBase = 0x%x", image->ImageBase);
1899fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1900fcf3ce44SJohn Forte 	    "Img Header: ImageSize = 0x%x", image->ImageSize);
1901fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1902fcf3ce44SJohn Forte 	    "Img Header: ZinitSize = 0x%x", image->ZinitSize);
1903fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1904fcf3ce44SJohn Forte 	    "Img Header: RelocSize = 0x%x", image->RelocSize);
1905fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1906fcf3ce44SJohn Forte 	    "Img Header: HdrCks = 0x%x", image->HdrCks);
1907fcf3ce44SJohn Forte 
190882527734SSukumar Swaminathan } /* emlxs_dump_image_header() */
1909fcf3ce44SJohn Forte 
1910fcf3ce44SJohn Forte 
1911fcf3ce44SJohn Forte static void
191282527734SSukumar Swaminathan emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t Type,
191382527734SSukumar Swaminathan     uint32_t RegionId, uint32_t WordCount, uint32_t BaseAddr)
1914fcf3ce44SJohn Forte {
1915fcf3ce44SJohn Forte 
191682527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
191782527734SSukumar Swaminathan 		MAILBOX4 *mb = (MAILBOX4 *)mbq;
191882527734SSukumar Swaminathan 
191982527734SSukumar Swaminathan 		/* Clear the local dump_region */
192082527734SSukumar Swaminathan 		bzero(hba->sli.sli4.dump_region.virt,
192182527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size);
192282527734SSukumar Swaminathan 
192382527734SSukumar Swaminathan 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
192482527734SSukumar Swaminathan 
192582527734SSukumar Swaminathan 		mb->mbxCommand = MBX_DUMP_MEMORY;
192682527734SSukumar Swaminathan 		mb->un.varDmp4.type = Type;
192782527734SSukumar Swaminathan 		mb->un.varDmp4.entry_index = BaseAddr;
192882527734SSukumar Swaminathan 		mb->un.varDmp4.region_id = RegionId;
192982527734SSukumar Swaminathan 
193082527734SSukumar Swaminathan 		mb->un.varDmp4.available_cnt = min((WordCount*4),
193182527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size);
193282527734SSukumar Swaminathan 		mb->un.varDmp4.addrHigh =
193382527734SSukumar Swaminathan 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
193482527734SSukumar Swaminathan 		mb->un.varDmp4.addrLow =
193582527734SSukumar Swaminathan 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
193682527734SSukumar Swaminathan 		mb->un.varDmp4.rsp_cnt = 0;
193782527734SSukumar Swaminathan 
193882527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
193982527734SSukumar Swaminathan 
194082527734SSukumar Swaminathan 	} else {
194182527734SSukumar Swaminathan 		MAILBOX *mb = (MAILBOX *)mbq;
194282527734SSukumar Swaminathan 
194382527734SSukumar Swaminathan 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
194482527734SSukumar Swaminathan 
194582527734SSukumar Swaminathan 		mb->mbxCommand = MBX_DUMP_MEMORY;
194682527734SSukumar Swaminathan 		mb->un.varDmp.type = Type;
194782527734SSukumar Swaminathan 		mb->un.varDmp.region_id = RegionId;
194882527734SSukumar Swaminathan 		mb->un.varDmp.word_cnt = WordCount;
194982527734SSukumar Swaminathan 		mb->un.varDmp.base_adr = BaseAddr;
195082527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
195182527734SSukumar Swaminathan 	}
195282527734SSukumar Swaminathan 
195382527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1954fcf3ce44SJohn Forte 
1955fcf3ce44SJohn Forte 	return;
1956fcf3ce44SJohn Forte 
195782527734SSukumar Swaminathan } /* emlxs_format_dump() */
1958fcf3ce44SJohn Forte 
1959fcf3ce44SJohn Forte 
1960fcf3ce44SJohn Forte /* ARGSUSED */
1961fcf3ce44SJohn Forte static uint32_t
1962291a2b48SSukumar Swaminathan emlxs_start_abs_download(emlxs_hba_t *hba,
1963291a2b48SSukumar Swaminathan     PAIF_HDR AifHdr,
1964291a2b48SSukumar Swaminathan     caddr_t Buffer,
19656a573d82SSukumar Swaminathan     uint32_t len,
19666a573d82SSukumar Swaminathan     PWAKE_UP_PARMS WakeUpParms)
1967fcf3ce44SJohn Forte {
1968fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1969fcf3ce44SJohn Forte 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
1970fcf3ce44SJohn Forte 	uint32_t *Src;
1971fcf3ce44SJohn Forte 	uint32_t *Dst;
1972fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
1973fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
1974fcf3ce44SJohn Forte 	MAILBOX *mb;
1975fcf3ce44SJohn Forte 	uint32_t rval = 1;
1976fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
1977fcf3ce44SJohn Forte 	uint32_t DlToAddr = AifHdr->ImageBase;
1978fcf3ce44SJohn Forte 	uint32_t DlCount;
1979fcf3ce44SJohn Forte 	uint32_t i;
19806a573d82SSukumar Swaminathan 	WAKE_UP_PARMS AbsWakeUpParms;
19816a573d82SSukumar Swaminathan 	int32_t AbsChangeParams;
1982fcf3ce44SJohn Forte 
19836a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1984fcf3ce44SJohn Forte 	    "Performing absolute download...");
1985fcf3ce44SJohn Forte 
1986291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
1987291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1988fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1989fcf3ce44SJohn Forte 		    "Unable to allocate data buffer.");
1990fcf3ce44SJohn Forte 
1991fcf3ce44SJohn Forte 		return (rval);
1992fcf3ce44SJohn Forte 	}
1993291a2b48SSukumar Swaminathan 
1994291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1995291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1996fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1997fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
1998fcf3ce44SJohn Forte 
1999fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2000fcf3ce44SJohn Forte 
2001fcf3ce44SJohn Forte 		return (rval);
2002fcf3ce44SJohn Forte 	}
2003fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2004fcf3ce44SJohn Forte 
20056a573d82SSukumar Swaminathan 	AbsChangeParams = emlxs_build_parms(Buffer,
20066a573d82SSukumar Swaminathan 	    &AbsWakeUpParms, len, AifHdr);
20076a573d82SSukumar Swaminathan 
2008fcf3ce44SJohn Forte 	Buffer += sizeof (AIF_HDR);
2009fcf3ce44SJohn Forte 
20106a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Erasing flash...");
2011fcf3ce44SJohn Forte 
20126a573d82SSukumar Swaminathan 	if (AifHdr->ImageBase == 0x20000) {
20136a573d82SSukumar Swaminathan 		/* DWC File */
201482527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0,
20156a573d82SSukumar Swaminathan 		    0, 0, NULL, 0);
2016fcf3ce44SJohn Forte 	} else {
201782527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount,
20186a573d82SSukumar Swaminathan 		    ERASE_FLASH, 0, 0, 0, NULL, 0);
2019fcf3ce44SJohn Forte 	}
2020fcf3ce44SJohn Forte 
202182527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2022fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2023fcf3ce44SJohn Forte 		    "Unable to erase Flash: Mailbox cmd=%x status=%x",
2024fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
2025fcf3ce44SJohn Forte 
2026fcf3ce44SJohn Forte 		rval = 1;
2027fcf3ce44SJohn Forte 
2028fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
2029fcf3ce44SJohn Forte 	}
2030291a2b48SSukumar Swaminathan 
20316a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2032291a2b48SSukumar Swaminathan 	    "Programming flash...");
2033fcf3ce44SJohn Forte 
2034fcf3ce44SJohn Forte 	while (DlByteCount) {
2035fcf3ce44SJohn Forte 
2036fcf3ce44SJohn Forte 		if (DlByteCount > SegSize) {
2037fcf3ce44SJohn Forte 			DlCount = SegSize;
2038fcf3ce44SJohn Forte 		} else {
2039fcf3ce44SJohn Forte 			DlCount = DlByteCount;
2040fcf3ce44SJohn Forte 		}
2041fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
2042fcf3ce44SJohn Forte 
2043fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
2044fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
2045fcf3ce44SJohn Forte 
2046fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
2047fcf3ce44SJohn Forte 			*Dst = *Src;
2048fcf3ce44SJohn Forte 			Dst++;
2049fcf3ce44SJohn Forte 			Src++;
2050fcf3ce44SJohn Forte 		}
2051fcf3ce44SJohn Forte 
2052fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
205382527734SSukumar Swaminathan 		    (volatile uint32_t *)
205482527734SSukumar Swaminathan 		    ((volatile char *)hba->sli.sli3.slim_addr +
2055291a2b48SSukumar Swaminathan 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2056fcf3ce44SJohn Forte 
205782527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, DlToAddr, DlCount,
20586a573d82SSukumar Swaminathan 		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL, 0);
2059fcf3ce44SJohn Forte 
206082527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2061291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
2062fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2063fcf3ce44SJohn Forte 			    "Unable to program Flash: Mailbox cmd=%x status=%x",
2064fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
2065fcf3ce44SJohn Forte 
2066fcf3ce44SJohn Forte 			rval = 1;
2067fcf3ce44SJohn Forte 
2068fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
2069fcf3ce44SJohn Forte 		}
2070291a2b48SSukumar Swaminathan 
2071fcf3ce44SJohn Forte 		Buffer += DlCount;
2072fcf3ce44SJohn Forte 		DlToAddr += DlCount;
2073fcf3ce44SJohn Forte 	}
2074fcf3ce44SJohn Forte 
20754baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
207682527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
20774baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
20784baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
20794baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
20804baa2c25SSukumar Swaminathan 
20814baa2c25SSukumar Swaminathan 		rval = 1;
20824baa2c25SSukumar Swaminathan 
20834baa2c25SSukumar Swaminathan 		goto EXIT_ABS_DOWNLOAD;
20844baa2c25SSukumar Swaminathan 	}
20854baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
20864baa2c25SSukumar Swaminathan 
2087fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
2088fcf3ce44SJohn Forte 
20896a573d82SSukumar Swaminathan 	if (AbsChangeParams) {
2090291a2b48SSukumar Swaminathan 		rval =
20916a573d82SSukumar Swaminathan 		    emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
2092fcf3ce44SJohn Forte 		    WakeUpParms);
2093fcf3ce44SJohn Forte 	}
2094fcf3ce44SJohn Forte 
2095fcf3ce44SJohn Forte EXIT_ABS_DOWNLOAD:
2096fcf3ce44SJohn Forte 	if (DataBuffer) {
2097fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2098fcf3ce44SJohn Forte 	}
2099291a2b48SSukumar Swaminathan 
2100fcf3ce44SJohn Forte 	if (mbox) {
2101fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2102fcf3ce44SJohn Forte 	}
2103291a2b48SSukumar Swaminathan 
2104fcf3ce44SJohn Forte 	return (rval);
2105fcf3ce44SJohn Forte 
210682527734SSukumar Swaminathan } /* emlxs_start_abs_download() */
2107fcf3ce44SJohn Forte 
2108fcf3ce44SJohn Forte 
2109fcf3ce44SJohn Forte /* ARGSUSED */
2110fcf3ce44SJohn Forte static void
211182527734SSukumar Swaminathan emlxs_format_prog_flash(MAILBOXQ *mbq,
2112291a2b48SSukumar Swaminathan     uint32_t Base,
2113291a2b48SSukumar Swaminathan     uint32_t DlByteCount,
2114291a2b48SSukumar Swaminathan     uint32_t Function,
2115291a2b48SSukumar Swaminathan     uint32_t Complete,
21166a573d82SSukumar Swaminathan     uint32_t BdeAddress,
21176a573d82SSukumar Swaminathan     uint32_t BdeSize,
21186a573d82SSukumar Swaminathan     PROG_ID *ProgId,
21196a573d82SSukumar Swaminathan     uint32_t keep)
2120fcf3ce44SJohn Forte {
212182527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
212282527734SSukumar Swaminathan 
2123291a2b48SSukumar Swaminathan 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2124fcf3ce44SJohn Forte 
21256a573d82SSukumar Swaminathan 	if (ProgId) {
2126fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_DOWN_LOAD;
21276a573d82SSukumar Swaminathan 	} else {
2128fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_SM;
21296a573d82SSukumar Swaminathan 	}
2130fcf3ce44SJohn Forte 
2131fcf3ce44SJohn Forte 	mb->un.varLdSM.load_cmplt = Complete;
2132fcf3ce44SJohn Forte 	mb->un.varLdSM.method = DL_FROM_SLIM;
2133fcf3ce44SJohn Forte 	mb->un.varLdSM.update_flash = 1;
2134fcf3ce44SJohn Forte 	mb->un.varLdSM.erase_or_prog = Function;
2135fcf3ce44SJohn Forte 	mb->un.varLdSM.dl_to_adr = Base;
2136fcf3ce44SJohn Forte 	mb->un.varLdSM.dl_len = DlByteCount;
21376a573d82SSukumar Swaminathan 	mb->un.varLdSM.keep = keep;
2138fcf3ce44SJohn Forte 
2139fcf3ce44SJohn Forte 	if (BdeSize) {
2140fcf3ce44SJohn Forte 		mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
2141fcf3ce44SJohn Forte 	} else if (ProgId) {
2142fcf3ce44SJohn Forte 		mb->un.varLdSM.un.prog_id = *ProgId;
2143fcf3ce44SJohn Forte 	} else {
2144fcf3ce44SJohn Forte 		mb->un.varLdSM.un.dl_from_slim_offset = 0;
2145fcf3ce44SJohn Forte 	}
2146fcf3ce44SJohn Forte 
2147fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
214882527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
2149fcf3ce44SJohn Forte 
215082527734SSukumar Swaminathan } /* emlxs_format_prog_flash() */
2151fcf3ce44SJohn Forte 
2152fcf3ce44SJohn Forte 
2153fcf3ce44SJohn Forte static void
215482527734SSukumar Swaminathan emlxs_format_update_parms(MAILBOXQ *mbq, PWAKE_UP_PARMS WakeUpParms)
2155fcf3ce44SJohn Forte {
215682527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
215782527734SSukumar Swaminathan 
2158fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2159fcf3ce44SJohn Forte 
2160fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UPDATE_CFG;
2161fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2162fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID;
2163fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS);
2164fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS);
2165fcf3ce44SJohn Forte 
2166291a2b48SSukumar Swaminathan 	bcopy((caddr_t)WakeUpParms,
2167291a2b48SSukumar Swaminathan 	    (caddr_t)&(mb->un.varUpdateCfg.cfg_data),
2168fcf3ce44SJohn Forte 	    sizeof (WAKE_UP_PARMS));
216982527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
2170fcf3ce44SJohn Forte 
217182527734SSukumar Swaminathan } /* emlxs_format_update_parms () */
2172fcf3ce44SJohn Forte 
2173fcf3ce44SJohn Forte 
2174fcf3ce44SJohn Forte /* ARGSUSED */
2175fcf3ce44SJohn Forte static void
217682527734SSukumar Swaminathan emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
2177fcf3ce44SJohn Forte     uint32_t region_id, uint32_t size)
2178fcf3ce44SJohn Forte {
217982527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
218082527734SSukumar Swaminathan 
2181fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2182fcf3ce44SJohn Forte 
2183fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UPDATE_CFG;
2184fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.Vbit = 1;
2185fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.Obit = 1;
2186fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET;
2187fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2188fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.region_id = region_id;
2189fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.entry_len = size;
2190fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.byte_len = size;
219182527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
2192fcf3ce44SJohn Forte 
219382527734SSukumar Swaminathan } /* emlxs_format_update_pci_cfg() */
2194fcf3ce44SJohn Forte 
2195fcf3ce44SJohn Forte 
2196fcf3ce44SJohn Forte 
2197fcf3ce44SJohn Forte static uint32_t
2198fcf3ce44SJohn Forte emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2199fcf3ce44SJohn Forte     PROG_ID * prog_id, uint32_t proc_erom)
2200fcf3ce44SJohn Forte {
2201fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2202fcf3ce44SJohn Forte 	MAILBOX *mb;
2203fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2204fcf3ce44SJohn Forte 	uint32_t rval = 0;
22056a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2206fcf3ce44SJohn Forte 
2207291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2208291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2209fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2210fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2211fcf3ce44SJohn Forte 
2212fcf3ce44SJohn Forte 		return (1);
2213fcf3ce44SJohn Forte 	}
2214fcf3ce44SJohn Forte 
2215291a2b48SSukumar Swaminathan 	mb = (MAILBOX *)mbox;
2216291a2b48SSukumar Swaminathan 
2217291a2b48SSukumar Swaminathan 	if (proc_erom && !(hba->model_info.chip &
2218fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2219fcf3ce44SJohn Forte 		WakeUpParms->u1.EROM_prog_id = *prog_id;
2220fcf3ce44SJohn Forte 		(void) emlxs_update_exp_rom(hba, WakeUpParms);
2221fcf3ce44SJohn Forte 	}
2222291a2b48SSukumar Swaminathan 
22236a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->u0.boot_bios_id;
2224fcf3ce44SJohn Forte 	WakeUpParms->u0.boot_bios_id = *prog_id;
2225fcf3ce44SJohn Forte 
222682527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2227fcf3ce44SJohn Forte 
222882527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2229fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2230291a2b48SSukumar Swaminathan 		    "Unable to update boot wakeup parms: Mailbox cmd=%x "
2231291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2232fcf3ce44SJohn Forte 
22336a573d82SSukumar Swaminathan 		WakeUpParms->u0.boot_bios_id = old_prog_id;
2234fcf3ce44SJohn Forte 		rval = 1;
2235fcf3ce44SJohn Forte 	}
2236291a2b48SSukumar Swaminathan 
2237fcf3ce44SJohn Forte 	if (mbox) {
2238fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2239fcf3ce44SJohn Forte 	}
2240291a2b48SSukumar Swaminathan 
2241fcf3ce44SJohn Forte 	return (rval);
2242fcf3ce44SJohn Forte 
224382527734SSukumar Swaminathan } /* emlxs_update_boot_wakeup_parms() */
2244fcf3ce44SJohn Forte 
2245fcf3ce44SJohn Forte 
2246fcf3ce44SJohn Forte 
2247fcf3ce44SJohn Forte static uint32_t
2248fcf3ce44SJohn Forte emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2249fcf3ce44SJohn Forte     PROG_ID *prog_id)
2250fcf3ce44SJohn Forte {
2251fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2252fcf3ce44SJohn Forte 	uint32_t rval = 0;
2253fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2254fcf3ce44SJohn Forte 	MAILBOX *mb;
22556a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2256fcf3ce44SJohn Forte 
2257291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2258291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2259fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2260fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2261fcf3ce44SJohn Forte 
2262fcf3ce44SJohn Forte 		return (1);
2263fcf3ce44SJohn Forte 	}
2264291a2b48SSukumar Swaminathan 
22656a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
22666a573d82SSukumar Swaminathan 	    "FF: Updating parms...");
22676a573d82SSukumar Swaminathan 
2268fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2269fcf3ce44SJohn Forte 
22706a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->prog_id;
2271fcf3ce44SJohn Forte 	WakeUpParms->prog_id = *prog_id;
2272fcf3ce44SJohn Forte 
227382527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2274fcf3ce44SJohn Forte 
227582527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2276fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2277291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
2278291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2279fcf3ce44SJohn Forte 
22806a573d82SSukumar Swaminathan 		WakeUpParms->prog_id = old_prog_id;
2281fcf3ce44SJohn Forte 		rval = 1;
2282fcf3ce44SJohn Forte 	}
2283291a2b48SSukumar Swaminathan 
2284fcf3ce44SJohn Forte 	if (mbox) {
2285fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2286fcf3ce44SJohn Forte 	}
2287291a2b48SSukumar Swaminathan 
2288fcf3ce44SJohn Forte 	return (rval);
2289fcf3ce44SJohn Forte 
229082527734SSukumar Swaminathan } /* emlxs_update_ff_wakeup_parms() */
2291fcf3ce44SJohn Forte 
2292fcf3ce44SJohn Forte 
2293fcf3ce44SJohn Forte static uint32_t
2294fcf3ce44SJohn Forte emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2295291a2b48SSukumar Swaminathan     PROG_ID * prog_id)
2296fcf3ce44SJohn Forte {
2297fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2298fcf3ce44SJohn Forte 	uint32_t rval = 0;
2299fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2300fcf3ce44SJohn Forte 	MAILBOX *mb;
23016a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2302fcf3ce44SJohn Forte 
2303291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2304291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2305fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2306fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2307fcf3ce44SJohn Forte 
2308fcf3ce44SJohn Forte 		return (1);
2309fcf3ce44SJohn Forte 	}
2310291a2b48SSukumar Swaminathan 
23116a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
23126a573d82SSukumar Swaminathan 	    "SLI1: Updating parms...");
23136a573d82SSukumar Swaminathan 
2314fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2315fcf3ce44SJohn Forte 
23166a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli1_prog_id;
2317fcf3ce44SJohn Forte 	WakeUpParms->sli1_prog_id = *prog_id;
2318fcf3ce44SJohn Forte 
231982527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2320fcf3ce44SJohn Forte 
232182527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2322fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2323291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2324291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2325fcf3ce44SJohn Forte 
23266a573d82SSukumar Swaminathan 		WakeUpParms->sli1_prog_id = old_prog_id;
2327fcf3ce44SJohn Forte 		rval = 1;
2328fcf3ce44SJohn Forte 	}
2329291a2b48SSukumar Swaminathan 
2330fcf3ce44SJohn Forte 	if (mbox) {
2331fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2332fcf3ce44SJohn Forte 	}
2333291a2b48SSukumar Swaminathan 
2334fcf3ce44SJohn Forte 	return (rval);
2335fcf3ce44SJohn Forte 
233682527734SSukumar Swaminathan } /* emlxs_update_sli1_wakeup_parms() */
2337fcf3ce44SJohn Forte 
2338fcf3ce44SJohn Forte 
2339fcf3ce44SJohn Forte static uint32_t
2340fcf3ce44SJohn Forte emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2341291a2b48SSukumar Swaminathan     PROG_ID * prog_id)
2342fcf3ce44SJohn Forte {
2343fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2344fcf3ce44SJohn Forte 	uint32_t rval = 0;
2345fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2346fcf3ce44SJohn Forte 	MAILBOX *mb;
23476a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2348fcf3ce44SJohn Forte 
2349291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2350291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2351fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2352fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2353fcf3ce44SJohn Forte 
2354fcf3ce44SJohn Forte 		return (1);
2355fcf3ce44SJohn Forte 	}
2356291a2b48SSukumar Swaminathan 
23576a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
23586a573d82SSukumar Swaminathan 	    "SLI2: Updating parms...");
23596a573d82SSukumar Swaminathan 
2360fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2361fcf3ce44SJohn Forte 
23626a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli2_prog_id;
2363fcf3ce44SJohn Forte 	WakeUpParms->sli2_prog_id = *prog_id;
2364fcf3ce44SJohn Forte 
236582527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2366fcf3ce44SJohn Forte 
236782527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2368fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2369291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2370291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2371fcf3ce44SJohn Forte 
23726a573d82SSukumar Swaminathan 		WakeUpParms->sli2_prog_id = old_prog_id;
2373fcf3ce44SJohn Forte 		rval = 1;
2374fcf3ce44SJohn Forte 	}
2375291a2b48SSukumar Swaminathan 
2376fcf3ce44SJohn Forte 	if (mbox) {
2377fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2378fcf3ce44SJohn Forte 	}
2379291a2b48SSukumar Swaminathan 
2380fcf3ce44SJohn Forte 	return (rval);
2381fcf3ce44SJohn Forte 
238282527734SSukumar Swaminathan } /* emlxs_update_sli2_wakeup_parms() */
2383fcf3ce44SJohn Forte 
2384fcf3ce44SJohn Forte 
2385fcf3ce44SJohn Forte static uint32_t
2386fcf3ce44SJohn Forte emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2387fcf3ce44SJohn Forte     PROG_ID *prog_id)
2388fcf3ce44SJohn Forte {
2389fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2390fcf3ce44SJohn Forte 	uint32_t rval = 0;
2391fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2392fcf3ce44SJohn Forte 	MAILBOX *mb;
23936a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2394fcf3ce44SJohn Forte 
2395291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2396291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2397fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2398fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2399fcf3ce44SJohn Forte 
2400fcf3ce44SJohn Forte 		return (1);
2401fcf3ce44SJohn Forte 	}
2402291a2b48SSukumar Swaminathan 
24036a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
24046a573d82SSukumar Swaminathan 	    "SLI3: Updating parms...");
24056a573d82SSukumar Swaminathan 
2406fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2407fcf3ce44SJohn Forte 
24086a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli3_prog_id;
2409fcf3ce44SJohn Forte 	WakeUpParms->sli3_prog_id = *prog_id;
2410fcf3ce44SJohn Forte 
241182527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2412fcf3ce44SJohn Forte 
241382527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2414fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2415291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2416291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2417fcf3ce44SJohn Forte 
24186a573d82SSukumar Swaminathan 		WakeUpParms->sli3_prog_id = old_prog_id;
2419fcf3ce44SJohn Forte 		rval = 1;
2420fcf3ce44SJohn Forte 	}
2421291a2b48SSukumar Swaminathan 
2422fcf3ce44SJohn Forte 	if (mbox) {
2423fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2424fcf3ce44SJohn Forte 	}
2425291a2b48SSukumar Swaminathan 
2426fcf3ce44SJohn Forte 	return (rval);
2427fcf3ce44SJohn Forte 
242882527734SSukumar Swaminathan } /* emlxs_update_sli3_wakeup_parms() */
2429fcf3ce44SJohn Forte 
2430fcf3ce44SJohn Forte 
2431fcf3ce44SJohn Forte static uint32_t
2432fcf3ce44SJohn Forte emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2433fcf3ce44SJohn Forte     PROG_ID *prog_id)
2434fcf3ce44SJohn Forte {
2435fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2436fcf3ce44SJohn Forte 	uint32_t rval = 0;
2437fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2438fcf3ce44SJohn Forte 	MAILBOX *mb;
24396a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2440fcf3ce44SJohn Forte 
2441291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2442291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2443fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2444fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2445fcf3ce44SJohn Forte 
2446fcf3ce44SJohn Forte 		return (1);
2447fcf3ce44SJohn Forte 	}
2448291a2b48SSukumar Swaminathan 
24496a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
24506a573d82SSukumar Swaminathan 	    "SLI4: Updating parms...");
24516a573d82SSukumar Swaminathan 
2452fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2453fcf3ce44SJohn Forte 
24546a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli4_prog_id;
2455fcf3ce44SJohn Forte 	WakeUpParms->sli4_prog_id = *prog_id;
2456fcf3ce44SJohn Forte 
245782527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2458fcf3ce44SJohn Forte 
245982527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2460fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2461291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2462291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2463fcf3ce44SJohn Forte 
24646a573d82SSukumar Swaminathan 		WakeUpParms->sli4_prog_id = old_prog_id;
2465fcf3ce44SJohn Forte 		rval = 1;
2466fcf3ce44SJohn Forte 	}
2467291a2b48SSukumar Swaminathan 
2468fcf3ce44SJohn Forte 	if (mbox) {
2469fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2470fcf3ce44SJohn Forte 	}
2471291a2b48SSukumar Swaminathan 
2472fcf3ce44SJohn Forte 	return (rval);
2473fcf3ce44SJohn Forte 
247482527734SSukumar Swaminathan } /* emlxs_update_sli4_wakeup_parms() */
2475fcf3ce44SJohn Forte 
2476fcf3ce44SJohn Forte 
24776a573d82SSukumar Swaminathan static uint32_t
24786a573d82SSukumar Swaminathan emlxs_clean_flash(emlxs_hba_t *hba,
24796a573d82SSukumar Swaminathan     PWAKE_UP_PARMS OldWakeUpParms, PWAKE_UP_PARMS NewWakeUpParms)
24806a573d82SSukumar Swaminathan {
24816a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
24826a573d82SSukumar Swaminathan 	PROG_ID load_list[MAX_LOAD_ENTRY];
24836a573d82SSukumar Swaminathan 	PROG_ID *wakeup_list[MAX_LOAD_ENTRY];
24846a573d82SSukumar Swaminathan 	uint32_t count;
24856a573d82SSukumar Swaminathan 	uint32_t i;
24866a573d82SSukumar Swaminathan 	uint32_t j;
24876a573d82SSukumar Swaminathan 	uint32_t k = 0;
24886a573d82SSukumar Swaminathan 	uint32_t *wptr;
24896a573d82SSukumar Swaminathan 
24906a573d82SSukumar Swaminathan 	if (!NewWakeUpParms) {
24916a573d82SSukumar Swaminathan 		return (1);
24926a573d82SSukumar Swaminathan 	}
24936a573d82SSukumar Swaminathan 
24946a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
24956a573d82SSukumar Swaminathan 	    "Cleaning flash...");
24966a573d82SSukumar Swaminathan 
24976a573d82SSukumar Swaminathan 	/* If old wakeup parameter list is available, */
24986a573d82SSukumar Swaminathan 	/* then cleanup old entries */
24996a573d82SSukumar Swaminathan 	if (OldWakeUpParms) {
25006a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->prog_id, &NewWakeUpParms->prog_id,
25016a573d82SSukumar Swaminathan 		    sizeof (PROG_ID))) {
25026a573d82SSukumar Swaminathan 
25036a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->prog_id;
25046a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
25056a573d82SSukumar Swaminathan 			    "OLD:      prog_id: 0x%08x 0x%08x  Removing.",
25066a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
25076a573d82SSukumar Swaminathan 
25086a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
25096a573d82SSukumar Swaminathan 			    &OldWakeUpParms->prog_id);
25106a573d82SSukumar Swaminathan 		}
25116a573d82SSukumar Swaminathan 
25126a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->u0.boot_bios_id,
25136a573d82SSukumar Swaminathan 		    &NewWakeUpParms->u0.boot_bios_id, sizeof (PROG_ID))) {
25146a573d82SSukumar Swaminathan 
25156a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->u0.boot_bios_id;
25166a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
25176a573d82SSukumar Swaminathan 			    "OLD: boot_bios_id: 0x%08x 0x%08x  Removing.",
25186a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
25196a573d82SSukumar Swaminathan 
25206a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
25216a573d82SSukumar Swaminathan 			    &OldWakeUpParms->u0.boot_bios_id);
25226a573d82SSukumar Swaminathan 		}
25236a573d82SSukumar Swaminathan 
25246a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli1_prog_id,
25256a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli1_prog_id, sizeof (PROG_ID))) {
25266a573d82SSukumar Swaminathan 
25276a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli1_prog_id;
25286a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
25296a573d82SSukumar Swaminathan 			    "OLD: sli1_prog_id: 0x%08x 0x%08x  Removing.",
25306a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
25316a573d82SSukumar Swaminathan 
25326a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
25336a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli1_prog_id);
25346a573d82SSukumar Swaminathan 		}
25356a573d82SSukumar Swaminathan 
25366a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli2_prog_id,
25376a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli2_prog_id, sizeof (PROG_ID))) {
25386a573d82SSukumar Swaminathan 
25396a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli2_prog_id;
25406a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
25416a573d82SSukumar Swaminathan 			    "OLD: sli2_prog_id: 0x%08x 0x%08x  Removing.",
25426a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
25436a573d82SSukumar Swaminathan 
25446a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
25456a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli2_prog_id);
25466a573d82SSukumar Swaminathan 		}
25476a573d82SSukumar Swaminathan 
25486a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli3_prog_id,
25496a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli3_prog_id, sizeof (PROG_ID))) {
25506a573d82SSukumar Swaminathan 
25516a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli3_prog_id;
25526a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
25536a573d82SSukumar Swaminathan 			    "OLD: sli3_prog_id: 0x%08x 0x%08x  Removing.",
25546a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
25556a573d82SSukumar Swaminathan 
25566a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
25576a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli3_prog_id);
25586a573d82SSukumar Swaminathan 		}
25596a573d82SSukumar Swaminathan 
25606a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli4_prog_id,
25616a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli4_prog_id, sizeof (PROG_ID))) {
25626a573d82SSukumar Swaminathan 
25636a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli4_prog_id;
25646a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
25656a573d82SSukumar Swaminathan 			    "OLD: sli4_prog_id: 0x%08x 0x%08x  Removing.",
25666a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
25676a573d82SSukumar Swaminathan 
25686a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
25696a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli4_prog_id);
25706a573d82SSukumar Swaminathan 		}
25716a573d82SSukumar Swaminathan 
25726a573d82SSukumar Swaminathan 		return (0);
25736a573d82SSukumar Swaminathan 	}
25746a573d82SSukumar Swaminathan 
25756a573d82SSukumar Swaminathan 	/* Otherwise use the current load list */
25766a573d82SSukumar Swaminathan 	count = emlxs_get_load_list(hba, load_list);
25776a573d82SSukumar Swaminathan 
25786a573d82SSukumar Swaminathan 	if (!count) {
25796a573d82SSukumar Swaminathan 		return (1);
25806a573d82SSukumar Swaminathan 	}
25816a573d82SSukumar Swaminathan 
25826a573d82SSukumar Swaminathan 	/* Init the wakeup list */
25836a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->prog_id;
25846a573d82SSukumar Swaminathan 	if (*wptr) {
25856a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->prog_id;
25866a573d82SSukumar Swaminathan 	}
25876a573d82SSukumar Swaminathan 
25886a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->u0.boot_bios_id;
25896a573d82SSukumar Swaminathan 	if (*wptr) {
25906a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->u0.boot_bios_id;
25916a573d82SSukumar Swaminathan 	}
25926a573d82SSukumar Swaminathan 
25936a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli1_prog_id;
25946a573d82SSukumar Swaminathan 	if (*wptr) {
25956a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli1_prog_id;
25966a573d82SSukumar Swaminathan 	}
25976a573d82SSukumar Swaminathan 
25986a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli2_prog_id;
25996a573d82SSukumar Swaminathan 	if (*wptr) {
26006a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli2_prog_id;
26016a573d82SSukumar Swaminathan 	}
26026a573d82SSukumar Swaminathan 
26036a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli3_prog_id;
26046a573d82SSukumar Swaminathan 	if (*wptr) {
26056a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli3_prog_id;
26066a573d82SSukumar Swaminathan 	}
26076a573d82SSukumar Swaminathan 
26086a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli4_prog_id;
26096a573d82SSukumar Swaminathan 	if (*wptr) {
26106a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli4_prog_id;
26116a573d82SSukumar Swaminathan 	}
26126a573d82SSukumar Swaminathan 
26136a573d82SSukumar Swaminathan 	if (k == 0) {
26146a573d82SSukumar Swaminathan 		return (0);
26156a573d82SSukumar Swaminathan 	}
26166a573d82SSukumar Swaminathan 
26176a573d82SSukumar Swaminathan 	/* Match load list to wakeup list */
26186a573d82SSukumar Swaminathan 	for (i = 0; i < count; i++) {
26196a573d82SSukumar Swaminathan 
26206a573d82SSukumar Swaminathan 		wptr = (uint32_t *)&load_list[i];
26216a573d82SSukumar Swaminathan 
26226a573d82SSukumar Swaminathan 		for (j = 0; j < k; j++) {
26236a573d82SSukumar Swaminathan 			if (bcmp((uint8_t *)wakeup_list[j],
26246a573d82SSukumar Swaminathan 			    (uint8_t *)&load_list[i], sizeof (PROG_ID)) == 0) {
26256a573d82SSukumar Swaminathan 				break;
26266a573d82SSukumar Swaminathan 			}
26276a573d82SSukumar Swaminathan 		}
26286a573d82SSukumar Swaminathan 
26296a573d82SSukumar Swaminathan 		/* No match */
26306a573d82SSukumar Swaminathan 		if (j == k) {
26316a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
26326a573d82SSukumar Swaminathan 			    "Load List[%d]: %08x %08x  Removing.",
26336a573d82SSukumar Swaminathan 			    i, wptr[0], wptr[1]);
26346a573d82SSukumar Swaminathan 
26356a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba, &load_list[i]);
26366a573d82SSukumar Swaminathan 		} else {
26376a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
26386a573d82SSukumar Swaminathan 			    "Load List[%d]: %08x %08x  Preserving.",
26396a573d82SSukumar Swaminathan 			    i, wptr[0], wptr[1]);
26406a573d82SSukumar Swaminathan 		}
26416a573d82SSukumar Swaminathan 	}
26426a573d82SSukumar Swaminathan 
26436a573d82SSukumar Swaminathan 	return (0);
26446a573d82SSukumar Swaminathan 
26456a573d82SSukumar Swaminathan } /* emlxs_clean_flash() */
26466a573d82SSukumar Swaminathan 
26476a573d82SSukumar Swaminathan 
2648fcf3ce44SJohn Forte /* ARGSUSED */
2649fcf3ce44SJohn Forte static uint32_t
2650291a2b48SSukumar Swaminathan emlxs_start_rel_download(emlxs_hba_t *hba,
2651291a2b48SSukumar Swaminathan     PIMAGE_HDR ImageHdr,
2652291a2b48SSukumar Swaminathan     caddr_t Buffer,
2653291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS WakeUpParms,
26546a573d82SSukumar Swaminathan     uint32_t dwc_flag)
2655fcf3ce44SJohn Forte {
2656fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2657fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2658fcf3ce44SJohn Forte 	MAILBOX *mb;
2659fcf3ce44SJohn Forte 	uint32_t *Src;
2660fcf3ce44SJohn Forte 	uint32_t *Dst;
2661fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
26626a573d82SSukumar Swaminathan 	uint32_t rval = 0;
26636a573d82SSukumar Swaminathan 	uint32_t DlByteCount;
2664fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
2665fcf3ce44SJohn Forte 	uint32_t DlCount;
2666fcf3ce44SJohn Forte 	uint32_t i;
26676a573d82SSukumar Swaminathan 	uint32_t *wptr;
2668fcf3ce44SJohn Forte 
26696a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&ImageHdr->Id;
26706a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
26716a573d82SSukumar Swaminathan 	    "Relative download: %08x %08x", wptr[0], wptr[1]);
2672fcf3ce44SJohn Forte 
2673291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
2674291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2675fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2676fcf3ce44SJohn Forte 		    "Unable to allocate data buffer.");
2677fcf3ce44SJohn Forte 
26786a573d82SSukumar Swaminathan 		return (1);
2679fcf3ce44SJohn Forte 	}
2680291a2b48SSukumar Swaminathan 
2681291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2682291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2683fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2684fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2685fcf3ce44SJohn Forte 
2686fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2687fcf3ce44SJohn Forte 
26886a573d82SSukumar Swaminathan 		return (1);
2689fcf3ce44SJohn Forte 	}
2690291a2b48SSukumar Swaminathan 
2691fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2692fcf3ce44SJohn Forte 
26936a573d82SSukumar Swaminathan 	DlByteCount = ImageHdr->BlockSize;
26946a573d82SSukumar Swaminathan 
269582527734SSukumar Swaminathan 	emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
26966a573d82SSukumar Swaminathan 	    &ImageHdr->Id, 0);
26976a573d82SSukumar Swaminathan 
26986a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
26996a573d82SSukumar Swaminathan 	    "  Erasing flash...");
2700fcf3ce44SJohn Forte 
27016a573d82SSukumar Swaminathan 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
2702fcf3ce44SJohn Forte 
27036a573d82SSukumar Swaminathan 	if (rval) {
2704fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2705fcf3ce44SJohn Forte 		    "Unable to erase flash. Mailbox cmd=%x status=%x",
2706fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
2707fcf3ce44SJohn Forte 
2708fcf3ce44SJohn Forte 		goto EXIT_REL_DOWNLOAD;
2709fcf3ce44SJohn Forte 	}
2710291a2b48SSukumar Swaminathan 
27116a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
27126a573d82SSukumar Swaminathan 	    "  Programming flash...");
2713fcf3ce44SJohn Forte 
2714fcf3ce44SJohn Forte 	while (DlByteCount) {
2715fcf3ce44SJohn Forte 		if (DlByteCount > SegSize) {
2716fcf3ce44SJohn Forte 			DlCount = SegSize;
2717fcf3ce44SJohn Forte 		} else {
2718fcf3ce44SJohn Forte 			DlCount = DlByteCount;
2719fcf3ce44SJohn Forte 		}
2720fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
2721fcf3ce44SJohn Forte 
2722fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
2723fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
2724fcf3ce44SJohn Forte 
2725fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
2726fcf3ce44SJohn Forte 			*Dst = *Src;
2727fcf3ce44SJohn Forte 			Dst++;
2728fcf3ce44SJohn Forte 			Src++;
2729fcf3ce44SJohn Forte 		}
2730fcf3ce44SJohn Forte 
2731fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
273282527734SSukumar Swaminathan 		    (volatile uint32_t *)
273382527734SSukumar Swaminathan 		    ((volatile char *)hba->sli.sli3.slim_addr +
2734291a2b48SSukumar Swaminathan 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2735fcf3ce44SJohn Forte 
273682527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox,
2737291a2b48SSukumar Swaminathan 		    0,
2738291a2b48SSukumar Swaminathan 		    DlCount,
2739291a2b48SSukumar Swaminathan 		    PROGRAM_FLASH,
27406a573d82SSukumar Swaminathan 		    (DlByteCount) ? 0 : 1,
27416a573d82SSukumar Swaminathan 		    0, DlCount, &ImageHdr->Id, dwc_flag);
2742fcf3ce44SJohn Forte 
27436a573d82SSukumar Swaminathan 		rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
27446a573d82SSukumar Swaminathan 
27456a573d82SSukumar Swaminathan 		if (rval) {
2746fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2747fcf3ce44SJohn Forte 			    "Unable to program flash. Mailbox cmd=%x status=%x",
2748fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
2749fcf3ce44SJohn Forte 
2750fcf3ce44SJohn Forte 			goto EXIT_REL_DOWNLOAD;
2751fcf3ce44SJohn Forte 		}
2752291a2b48SSukumar Swaminathan 
2753fcf3ce44SJohn Forte 		Buffer += DlCount;
2754fcf3ce44SJohn Forte 	}
2755fcf3ce44SJohn Forte 
27564baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
275782527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
27584baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
27594baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
27604baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
27614baa2c25SSukumar Swaminathan 
27624baa2c25SSukumar Swaminathan 		rval = 1;
27634baa2c25SSukumar Swaminathan 
27644baa2c25SSukumar Swaminathan 		goto EXIT_REL_DOWNLOAD;
27654baa2c25SSukumar Swaminathan 	}
27664baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
27674baa2c25SSukumar Swaminathan 
27686a573d82SSukumar Swaminathan 	/* Update wakeup parameters */
2769fcf3ce44SJohn Forte 	switch (ImageHdr->Id.Type) {
2770fcf3ce44SJohn Forte 	case TEST_PROGRAM:
2771fcf3ce44SJohn Forte 		break;
2772fcf3ce44SJohn Forte 
2773fcf3ce44SJohn Forte 	case FUNC_FIRMWARE:
27746a573d82SSukumar Swaminathan 		if (!dwc_flag) {
27756a573d82SSukumar Swaminathan 			rval = emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
27766a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
27776a573d82SSukumar Swaminathan 		} else {
27786a573d82SSukumar Swaminathan 			WakeUpParms->prog_id = ImageHdr->Id;
27796a573d82SSukumar Swaminathan 		}
2780fcf3ce44SJohn Forte 		break;
2781fcf3ce44SJohn Forte 
2782fcf3ce44SJohn Forte 	case BOOT_BIOS:
27836a573d82SSukumar Swaminathan 		if (!dwc_flag) {
27846a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
27856a573d82SSukumar Swaminathan 			    "BOOT: Updating parms...");
27866a573d82SSukumar Swaminathan 
27876a573d82SSukumar Swaminathan 			rval = emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
27886a573d82SSukumar Swaminathan 			    &ImageHdr->Id, 1);
27896a573d82SSukumar Swaminathan 		} else {
27906a573d82SSukumar Swaminathan 			if (hba->wakeup_parms.u0.boot_bios_wd[0]) {
27916a573d82SSukumar Swaminathan 				WakeUpParms->u0.boot_bios_id = ImageHdr->Id;
27926a573d82SSukumar Swaminathan 			}
27936a573d82SSukumar Swaminathan 
27946a573d82SSukumar Swaminathan 			if (!(hba->model_info.chip &
27956a573d82SSukumar Swaminathan 			    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
27966a573d82SSukumar Swaminathan 				WakeUpParms->u1.EROM_prog_id = ImageHdr->Id;
27976a573d82SSukumar Swaminathan 			}
27986a573d82SSukumar Swaminathan 		}
2799fcf3ce44SJohn Forte 		break;
2800fcf3ce44SJohn Forte 
2801fcf3ce44SJohn Forte 	case SLI1_OVERLAY:
28026a573d82SSukumar Swaminathan 		if (!dwc_flag) {
28036a573d82SSukumar Swaminathan 			rval = emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
28046a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
28056a573d82SSukumar Swaminathan 		} else {
28066a573d82SSukumar Swaminathan 			WakeUpParms->sli1_prog_id = ImageHdr->Id;
28076a573d82SSukumar Swaminathan 		}
2808fcf3ce44SJohn Forte 		break;
2809fcf3ce44SJohn Forte 
2810fcf3ce44SJohn Forte 	case SLI2_OVERLAY:
28116a573d82SSukumar Swaminathan 		if (!dwc_flag) {
28126a573d82SSukumar Swaminathan 			rval = emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
28136a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
28146a573d82SSukumar Swaminathan 		} else {
28156a573d82SSukumar Swaminathan 			WakeUpParms->sli2_prog_id = ImageHdr->Id;
28166a573d82SSukumar Swaminathan 		}
2817fcf3ce44SJohn Forte 		break;
2818fcf3ce44SJohn Forte 
2819fcf3ce44SJohn Forte 	case SLI3_OVERLAY:
28206a573d82SSukumar Swaminathan 		if (!dwc_flag) {
28216a573d82SSukumar Swaminathan 			rval = emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
28226a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
28236a573d82SSukumar Swaminathan 		} else {
28246a573d82SSukumar Swaminathan 			WakeUpParms->sli3_prog_id = ImageHdr->Id;
28256a573d82SSukumar Swaminathan 		}
2826fcf3ce44SJohn Forte 		break;
2827fcf3ce44SJohn Forte 
2828fcf3ce44SJohn Forte 	case SLI4_OVERLAY:
28296a573d82SSukumar Swaminathan 		if (!dwc_flag) {
28306a573d82SSukumar Swaminathan 			rval = emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
28316a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
28326a573d82SSukumar Swaminathan 		} else {
28336a573d82SSukumar Swaminathan 			WakeUpParms->sli4_prog_id = ImageHdr->Id;
28346a573d82SSukumar Swaminathan 		}
2835fcf3ce44SJohn Forte 		break;
2836fcf3ce44SJohn Forte 
2837fcf3ce44SJohn Forte 	default:
2838fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2839291a2b48SSukumar Swaminathan 		    "Image type not supported. Type=%x", ImageHdr->Id.Type);
2840fcf3ce44SJohn Forte 
2841fcf3ce44SJohn Forte 		break;
2842fcf3ce44SJohn Forte 	}
2843fcf3ce44SJohn Forte 
2844fcf3ce44SJohn Forte EXIT_REL_DOWNLOAD:
2845fcf3ce44SJohn Forte 	if (DataBuffer) {
2846fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2847fcf3ce44SJohn Forte 	}
2848291a2b48SSukumar Swaminathan 
2849fcf3ce44SJohn Forte 	if (mbox) {
2850fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2851fcf3ce44SJohn Forte 	}
2852291a2b48SSukumar Swaminathan 
2853fcf3ce44SJohn Forte 	return (rval);
2854fcf3ce44SJohn Forte 
285582527734SSukumar Swaminathan } /* emlxs_start_rel_download() */
2856fcf3ce44SJohn Forte 
2857fcf3ce44SJohn Forte 
28586a573d82SSukumar Swaminathan static uint32_t
28596a573d82SSukumar Swaminathan emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer, emlxs_fw_image_t *fw_image)
2860291a2b48SSukumar Swaminathan {
28616a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
28626a573d82SSukumar Swaminathan 	uint32_t rval = 0;
28636a573d82SSukumar Swaminathan 	WAKE_UP_PARMS RelWakeUpParms;
28646a573d82SSukumar Swaminathan 	WAKE_UP_PARMS WakeUpParms;
28656a573d82SSukumar Swaminathan 	uint32_t i;
28666a573d82SSukumar Swaminathan 	IMAGE_HDR ImageHdr;
28676a573d82SSukumar Swaminathan 	caddr_t bptr;
28686a573d82SSukumar Swaminathan 	uint32_t flash_cleaned = 0;
28696a573d82SSukumar Swaminathan 
28706a573d82SSukumar Swaminathan 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 0)) {
28716a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
28726a573d82SSukumar Swaminathan 		    "Unable to get wakeup parameters.");
28736a573d82SSukumar Swaminathan 
28746a573d82SSukumar Swaminathan 		return (EMLXS_IMAGE_FAILED);
28756a573d82SSukumar Swaminathan 	}
28766a573d82SSukumar Swaminathan 
28776a573d82SSukumar Swaminathan download:
28786a573d82SSukumar Swaminathan 
28796a573d82SSukumar Swaminathan 	bcopy(&WakeUpParms, &RelWakeUpParms, sizeof (WAKE_UP_PARMS));
28806a573d82SSukumar Swaminathan 
28816a573d82SSukumar Swaminathan 	for (i = 0; i < MAX_PROG_TYPES; i++) {
28826a573d82SSukumar Swaminathan 		if (!fw_image->prog[i].version) {
28836a573d82SSukumar Swaminathan 			continue;
28846a573d82SSukumar Swaminathan 		}
28856a573d82SSukumar Swaminathan 
28866a573d82SSukumar Swaminathan 		bptr = buffer + fw_image->prog[i].offset;
28876a573d82SSukumar Swaminathan 
28886a573d82SSukumar Swaminathan 		bcopy(bptr, &ImageHdr, sizeof (IMAGE_HDR));
28896a573d82SSukumar Swaminathan 
28906a573d82SSukumar Swaminathan 		rval = emlxs_start_rel_download(hba, &ImageHdr, bptr,
28916a573d82SSukumar Swaminathan 		    &RelWakeUpParms, 1);
28926a573d82SSukumar Swaminathan 
28936a573d82SSukumar Swaminathan 		if (rval) {
28946a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
28956a573d82SSukumar Swaminathan 			    &emlxs_download_failed_msg,
28966a573d82SSukumar Swaminathan 			    "Failed to program flash.");
28976a573d82SSukumar Swaminathan 
28986a573d82SSukumar Swaminathan 			if ((rval == NO_FLASH_MEM_AVAIL) && !flash_cleaned) {
28996a573d82SSukumar Swaminathan 				/* Cleanup using current load list */
29006a573d82SSukumar Swaminathan 				(void) emlxs_clean_flash(hba, 0, &WakeUpParms);
29016a573d82SSukumar Swaminathan 
29026a573d82SSukumar Swaminathan 				flash_cleaned = 1;
29036a573d82SSukumar Swaminathan 				goto download;
29046a573d82SSukumar Swaminathan 			}
29056a573d82SSukumar Swaminathan 
29066a573d82SSukumar Swaminathan 			return (EMLXS_IMAGE_FAILED);
29076a573d82SSukumar Swaminathan 		}
29086a573d82SSukumar Swaminathan 	}
29096a573d82SSukumar Swaminathan 
29106a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
29116a573d82SSukumar Swaminathan 	    "Updating wakeup parameters.");
29126a573d82SSukumar Swaminathan 
29136a573d82SSukumar Swaminathan 	if (emlxs_update_wakeup_parms(hba, &RelWakeUpParms,
29146a573d82SSukumar Swaminathan 	    &RelWakeUpParms)) {
29156a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
29166a573d82SSukumar Swaminathan 		    "Unable to update parameters.");
29176a573d82SSukumar Swaminathan 
29186a573d82SSukumar Swaminathan 		return (EMLXS_IMAGE_FAILED);
29196a573d82SSukumar Swaminathan 	}
29206a573d82SSukumar Swaminathan 
2921*a9800bebSGarrett D'Amore 	/* Cleanup using old wakeup paramters */
2922*a9800bebSGarrett D'Amore 	(void) emlxs_clean_flash(hba, &WakeUpParms, &RelWakeUpParms);
2923*a9800bebSGarrett D'Amore 
29246a573d82SSukumar Swaminathan 	return (0);
29256a573d82SSukumar Swaminathan 
29266a573d82SSukumar Swaminathan } /* emlxs_proc_rel_2mb() */
29276a573d82SSukumar Swaminathan 
29286a573d82SSukumar Swaminathan 
29296a573d82SSukumar Swaminathan #define	FLASH_POLLING_BIT	0x80
29306a573d82SSukumar Swaminathan #define	FLASH_ERROR_BIT		0x20
29316a573d82SSukumar Swaminathan 
29326a573d82SSukumar Swaminathan typedef struct _flash_t
29336a573d82SSukumar Swaminathan {
29346a573d82SSukumar Swaminathan 	uint32_t	offset;
29356a573d82SSukumar Swaminathan 	uint8_t		val;
29366a573d82SSukumar Swaminathan } flash_t;
29376a573d82SSukumar Swaminathan 
29386a573d82SSukumar Swaminathan 
2939fcf3ce44SJohn Forte 
2940fcf3ce44SJohn Forte static uint32_t
2941291a2b48SSukumar Swaminathan emlxs_write_fcode_flash(emlxs_hba_t *hba,
2942291a2b48SSukumar Swaminathan     PIMAGE_HDR ImageHdr, caddr_t Buffer)
2943fcf3ce44SJohn Forte {
2944fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2945fcf3ce44SJohn Forte 	uint8_t bb;
2946fcf3ce44SJohn Forte 	uint8_t cc;
2947fcf3ce44SJohn Forte 	uint8_t *src;
2948fcf3ce44SJohn Forte 	uint32_t DlByteCount = ImageHdr->BlockSize;
2949fcf3ce44SJohn Forte 	uint32_t i;
2950fcf3ce44SJohn Forte 	uint32_t j;
2951fcf3ce44SJohn Forte 	uint32_t k;
2952fcf3ce44SJohn Forte 
2953291a2b48SSukumar Swaminathan 	flash_t wr[3] = {
2954fcf3ce44SJohn Forte 		{0x555, 0xaa},
2955fcf3ce44SJohn Forte 		{0x2aa, 0x55},
2956fcf3ce44SJohn Forte 		{0x555, 0xa0}
2957fcf3ce44SJohn Forte 	};
2958fcf3ce44SJohn Forte 
2959fcf3ce44SJohn Forte 	/* Load Fcode */
2960fcf3ce44SJohn Forte 	src = (uint8_t *)Buffer + sizeof (IMAGE_HDR);
2961fcf3ce44SJohn Forte 	for (i = 0; i < DlByteCount; i++) {
2962fcf3ce44SJohn Forte 		for (k = 0; k < 3; k++) {
2963fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
2964fcf3ce44SJohn Forte 		}
2965fcf3ce44SJohn Forte 
2966fcf3ce44SJohn Forte 		/* Reverse Endian word alignment */
2967fcf3ce44SJohn Forte 		j = (i & 3) ^ 3;
2968fcf3ce44SJohn Forte 
2969fcf3ce44SJohn Forte 		bb = src[j];
2970fcf3ce44SJohn Forte 
2971fcf3ce44SJohn Forte 		if (j == 0) {
2972fcf3ce44SJohn Forte 			src += 4;
2973fcf3ce44SJohn Forte 		}
2974291a2b48SSukumar Swaminathan 
2975fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
2976fcf3ce44SJohn Forte 
2977fcf3ce44SJohn Forte 		/* check for complete */
2978fcf3ce44SJohn Forte 		for (;;) {
2979fcf3ce44SJohn Forte 			DELAYUS(20);
2980fcf3ce44SJohn Forte 
2981fcf3ce44SJohn Forte 			cc = SBUS_READ_FLASH_COPY(hba, i);
2982fcf3ce44SJohn Forte 
2983fcf3ce44SJohn Forte 			/* If data matches then continue */
2984fcf3ce44SJohn Forte 			if (cc == bb) {
2985fcf3ce44SJohn Forte 				break;
2986fcf3ce44SJohn Forte 			}
2987291a2b48SSukumar Swaminathan 
2988291a2b48SSukumar Swaminathan 			/* Polling bit will be inverse final value */
2989291a2b48SSukumar Swaminathan 			/* while active */
2990fcf3ce44SJohn Forte 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
2991fcf3ce44SJohn Forte 				/* Still busy */
2992fcf3ce44SJohn Forte 
2993fcf3ce44SJohn Forte 				/* Check for error bit */
2994fcf3ce44SJohn Forte 				if (cc & FLASH_ERROR_BIT) {
2995fcf3ce44SJohn Forte 					/* Read data one more time */
2996fcf3ce44SJohn Forte 					cc = SBUS_READ_FLASH_COPY(hba, i);
2997fcf3ce44SJohn Forte 
2998fcf3ce44SJohn Forte 					/* Check if data matches */
2999fcf3ce44SJohn Forte 					if (cc == bb) {
3000fcf3ce44SJohn Forte 						break;
3001fcf3ce44SJohn Forte 					}
3002291a2b48SSukumar Swaminathan 
3003fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
3004fcf3ce44SJohn Forte 					    &emlxs_download_failed_msg,
3005fcf3ce44SJohn Forte 					    "FCode write error: offset:%x "
3006291a2b48SSukumar Swaminathan 					    "wrote:%x read:%x\n", i, bb, cc);
3007fcf3ce44SJohn Forte 
3008fcf3ce44SJohn Forte 					return (1);
3009fcf3ce44SJohn Forte 				}
3010fcf3ce44SJohn Forte 			}
3011fcf3ce44SJohn Forte 		}
3012fcf3ce44SJohn Forte 	}
3013fcf3ce44SJohn Forte 
3014fcf3ce44SJohn Forte 	/* Load Header */
3015fcf3ce44SJohn Forte 	src = (uint8_t *)ImageHdr;
3016fcf3ce44SJohn Forte 
3017fcf3ce44SJohn Forte 	for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) {
3018fcf3ce44SJohn Forte 		for (k = 0; k < 3; k++) {
3019fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
3020fcf3ce44SJohn Forte 		}
3021fcf3ce44SJohn Forte 
3022fcf3ce44SJohn Forte 		/* Reverse Endian word alignment */
3023fcf3ce44SJohn Forte 		j = (i & 3) ^ 3;
3024fcf3ce44SJohn Forte 
3025fcf3ce44SJohn Forte 		bb = src[j];
3026fcf3ce44SJohn Forte 
3027fcf3ce44SJohn Forte 		if (j == 0) {
3028fcf3ce44SJohn Forte 			src += 4;
3029fcf3ce44SJohn Forte 		}
3030291a2b48SSukumar Swaminathan 
3031fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
3032fcf3ce44SJohn Forte 
3033fcf3ce44SJohn Forte 		/* check for complete */
3034fcf3ce44SJohn Forte 		for (;;) {
3035fcf3ce44SJohn Forte 			DELAYUS(20);
3036fcf3ce44SJohn Forte 
3037fcf3ce44SJohn Forte 			cc = SBUS_READ_FLASH_COPY(hba, i);
3038fcf3ce44SJohn Forte 
3039fcf3ce44SJohn Forte 			/* If data matches then continue */
3040fcf3ce44SJohn Forte 			if (cc == bb) {
3041fcf3ce44SJohn Forte 				break;
3042fcf3ce44SJohn Forte 			}
3043291a2b48SSukumar Swaminathan 
3044291a2b48SSukumar Swaminathan 			/* Polling bit will be inverse final value */
3045291a2b48SSukumar Swaminathan 			/* while active */
3046fcf3ce44SJohn Forte 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
3047fcf3ce44SJohn Forte 				/* Still busy */
3048fcf3ce44SJohn Forte 
3049fcf3ce44SJohn Forte 				/* Check for error bit */
3050fcf3ce44SJohn Forte 				if (cc & FLASH_ERROR_BIT) {
3051fcf3ce44SJohn Forte 					/* Read data one more time */
3052fcf3ce44SJohn Forte 					cc = SBUS_READ_FLASH_COPY(hba, i);
3053fcf3ce44SJohn Forte 
3054fcf3ce44SJohn Forte 					/* Check if data matches */
3055fcf3ce44SJohn Forte 					if (cc == bb) {
3056fcf3ce44SJohn Forte 						break;
3057fcf3ce44SJohn Forte 					}
3058291a2b48SSukumar Swaminathan 
3059fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
3060fcf3ce44SJohn Forte 					    &emlxs_download_failed_msg,
3061fcf3ce44SJohn Forte 					    "FCode write error: offset:%x "
3062291a2b48SSukumar Swaminathan 					    "wrote:%x read:%x\n", i, bb, cc);
3063fcf3ce44SJohn Forte 
3064fcf3ce44SJohn Forte 					return (1);
3065fcf3ce44SJohn Forte 				}
3066fcf3ce44SJohn Forte 			}
3067fcf3ce44SJohn Forte 		}
3068fcf3ce44SJohn Forte 	}
3069fcf3ce44SJohn Forte 
30704baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
307182527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
30724baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
30734baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
30744baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
30754baa2c25SSukumar Swaminathan 		return (1);
30764baa2c25SSukumar Swaminathan 	}
30774baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
3078291a2b48SSukumar Swaminathan 
3079fcf3ce44SJohn Forte 	return (0);
3080fcf3ce44SJohn Forte 
308182527734SSukumar Swaminathan } /* emlxs_write_fcode_flash() */
3082fcf3ce44SJohn Forte 
3083fcf3ce44SJohn Forte 
3084fcf3ce44SJohn Forte 
3085fcf3ce44SJohn Forte static uint32_t
3086fcf3ce44SJohn Forte emlxs_erase_fcode_flash(emlxs_hba_t *hba)
3087fcf3ce44SJohn Forte {
3088fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3089fcf3ce44SJohn Forte 	int32_t i, j;
3090fcf3ce44SJohn Forte 	uint8_t cc;
3091fcf3ce44SJohn Forte 	uint32_t offset;
3092fcf3ce44SJohn Forte 
3093291a2b48SSukumar Swaminathan 	flash_t ef[6] = {
3094fcf3ce44SJohn Forte 		{0x555, 0xaa},
3095fcf3ce44SJohn Forte 		{0x2aa, 0x55},
3096fcf3ce44SJohn Forte 		{0x555, 0x80},
3097fcf3ce44SJohn Forte 		{0x555, 0xaa},
3098fcf3ce44SJohn Forte 		{0x2aa, 0x55},
3099fcf3ce44SJohn Forte 		{0x555, 0x10}
3100fcf3ce44SJohn Forte 	};
3101fcf3ce44SJohn Forte 
3102fcf3ce44SJohn Forte 	/* Auto select */
3103291a2b48SSukumar Swaminathan 	flash_t as[3] = {
3104fcf3ce44SJohn Forte 		{0x555, 0xaa},
3105fcf3ce44SJohn Forte 		{0x2aa, 0x55},
3106fcf3ce44SJohn Forte 		{0x555, 0x90}
3107fcf3ce44SJohn Forte 	};
3108fcf3ce44SJohn Forte 
3109fcf3ce44SJohn Forte 
3110fcf3ce44SJohn Forte 	/* Check Manufacturers Code */
3111fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++) {
3112fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3113fcf3ce44SJohn Forte 	}
3114fcf3ce44SJohn Forte 
3115fcf3ce44SJohn Forte 	cc = SBUS_READ_FLASH_COPY(hba, 0);
3116fcf3ce44SJohn Forte 
3117fcf3ce44SJohn Forte 	/* Check Device Code */
3118fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++) {
3119fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3120fcf3ce44SJohn Forte 	}
3121fcf3ce44SJohn Forte 
3122fcf3ce44SJohn Forte 	cc = SBUS_READ_FLASH_COPY(hba, 1);
3123fcf3ce44SJohn Forte 
3124fcf3ce44SJohn Forte 
3125fcf3ce44SJohn Forte 	/* Check block protections (up to 4 16K blocks = 64K) */
3126fcf3ce44SJohn Forte 	for (j = 0; j < 4; j++) {
3127fcf3ce44SJohn Forte 		for (i = 0; i < 3; i++) {
3128fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3129fcf3ce44SJohn Forte 		}
3130fcf3ce44SJohn Forte 
3131fcf3ce44SJohn Forte 		offset = (j << 14) | 0x2;
3132fcf3ce44SJohn Forte 
3133fcf3ce44SJohn Forte 		cc = SBUS_READ_FLASH_COPY(hba, offset);
3134fcf3ce44SJohn Forte 
3135fcf3ce44SJohn Forte 		if (cc == 0x01) {
3136fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3137fcf3ce44SJohn Forte 			    "Block %d is protected and can't be erased.", j);
3138fcf3ce44SJohn Forte 		}
3139fcf3ce44SJohn Forte 	}
3140fcf3ce44SJohn Forte 
3141fcf3ce44SJohn Forte 	/* Write erase flash sequence */
3142fcf3ce44SJohn Forte 	for (i = 0; i < 6; i++) {
3143fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val);
3144fcf3ce44SJohn Forte 	}
3145fcf3ce44SJohn Forte 
3146fcf3ce44SJohn Forte 	/* check for complete */
3147fcf3ce44SJohn Forte 	for (;;) {
3148fcf3ce44SJohn Forte 		/* Delay 3 seconds */
3149fcf3ce44SJohn Forte 		DELAYMS(3000);
3150fcf3ce44SJohn Forte 
3151fcf3ce44SJohn Forte 		cc = SBUS_READ_FLASH_COPY(hba, 0);
3152fcf3ce44SJohn Forte 
3153fcf3ce44SJohn Forte 
3154fcf3ce44SJohn Forte 		/* If data matches then continue; */
3155fcf3ce44SJohn Forte 		if (cc == 0xff) {
3156fcf3ce44SJohn Forte 			break;
3157fcf3ce44SJohn Forte 		}
3158291a2b48SSukumar Swaminathan 
3159fcf3ce44SJohn Forte 		/* Polling bit will be inverse final value while active */
3160fcf3ce44SJohn Forte 		if ((cc ^ 0xff) & FLASH_POLLING_BIT) {
3161fcf3ce44SJohn Forte 			/* Still busy */
3162fcf3ce44SJohn Forte 
3163fcf3ce44SJohn Forte 			/* Check for error bit */
3164fcf3ce44SJohn Forte 			if (cc & FLASH_ERROR_BIT) {
3165fcf3ce44SJohn Forte 				/* Read data one more time */
3166fcf3ce44SJohn Forte 				cc = SBUS_READ_FLASH_COPY(hba, 0);
3167fcf3ce44SJohn Forte 
3168fcf3ce44SJohn Forte 				/* Check if data matches */
3169fcf3ce44SJohn Forte 				if (cc == 0xff) {
3170fcf3ce44SJohn Forte 					break;
3171fcf3ce44SJohn Forte 				}
3172291a2b48SSukumar Swaminathan 
3173fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
3174fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
3175291a2b48SSukumar Swaminathan 				    "FCode write error: offset:%x wrote:%x "
3176291a2b48SSukumar Swaminathan 				    "read:%x\n", i, 0xff, cc);
3177fcf3ce44SJohn Forte 
3178fcf3ce44SJohn Forte 				return (1);
3179fcf3ce44SJohn Forte 			}
3180fcf3ce44SJohn Forte 		}
3181fcf3ce44SJohn Forte 	}
3182fcf3ce44SJohn Forte 
31834baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
318482527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
31854baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
31864baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
31874baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
31884baa2c25SSukumar Swaminathan 		return (1);
31894baa2c25SSukumar Swaminathan 	}
31904baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
31914baa2c25SSukumar Swaminathan 
3192fcf3ce44SJohn Forte 	return (0);
3193fcf3ce44SJohn Forte 
319482527734SSukumar Swaminathan } /* emlxs_erase_fcode_flash() */
3195fcf3ce44SJohn Forte 
3196fcf3ce44SJohn Forte 
31976a573d82SSukumar Swaminathan static uint32_t
31986a573d82SSukumar Swaminathan emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId)
31996a573d82SSukumar Swaminathan {
32006a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
32016a573d82SSukumar Swaminathan 	MAILBOXQ *mbox = NULL;
32026a573d82SSukumar Swaminathan 	MAILBOX *mb;
32036a573d82SSukumar Swaminathan 	uint32_t rval = 0;
32046a573d82SSukumar Swaminathan 
32056a573d82SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
32066a573d82SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
32076a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
32086a573d82SSukumar Swaminathan 		    "Unable to allocate mailbox buffer.");
32096a573d82SSukumar Swaminathan 
32106a573d82SSukumar Swaminathan 		return (1);
32116a573d82SSukumar Swaminathan 	}
32126a573d82SSukumar Swaminathan 
32136a573d82SSukumar Swaminathan 	mb = (MAILBOX *)mbox;
32146a573d82SSukumar Swaminathan 	mb->mbxCommand = MBX_DEL_LD_ENTRY;
32156a573d82SSukumar Swaminathan 	mb->un.varDelLdEntry.list_req = FLASH_LOAD_LIST;
32166a573d82SSukumar Swaminathan 	mb->un.varDelLdEntry.prog_id = *progId;
32176a573d82SSukumar Swaminathan 
32186a573d82SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
32196a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
32206a573d82SSukumar Swaminathan 		    "Unable to delete load entry: Mailbox cmd=%x status=%x",
32216a573d82SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
32226a573d82SSukumar Swaminathan 
32236a573d82SSukumar Swaminathan 		rval = 1;
32246a573d82SSukumar Swaminathan 	}
32256a573d82SSukumar Swaminathan 
32266a573d82SSukumar Swaminathan done:
32276a573d82SSukumar Swaminathan 
32286a573d82SSukumar Swaminathan 	if (mbox) {
32296a573d82SSukumar Swaminathan 		kmem_free(mbox, sizeof (MAILBOXQ));
32306a573d82SSukumar Swaminathan 	}
32316a573d82SSukumar Swaminathan 
32326a573d82SSukumar Swaminathan 	return (rval);
32336a573d82SSukumar Swaminathan 
32346a573d82SSukumar Swaminathan } /* emlxs_delete_load_entry() */
32356a573d82SSukumar Swaminathan 
32366a573d82SSukumar Swaminathan 
3237fcf3ce44SJohn Forte extern uint32_t
3238fcf3ce44SJohn Forte emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
3239fcf3ce44SJohn Forte {
3240fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3241fcf3ce44SJohn Forte 	LOAD_ENTRY *LoadEntry;
3242fcf3ce44SJohn Forte 	LOAD_LIST *LoadList = NULL;
3243fcf3ce44SJohn Forte 	uint32_t i;
32446a573d82SSukumar Swaminathan 	uint32_t count = 0;
3245fcf3ce44SJohn Forte 
3246fcf3ce44SJohn Forte 	bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
3247fcf3ce44SJohn Forte 
3248291a2b48SSukumar Swaminathan 	if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST),
3249291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3250fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3251fcf3ce44SJohn Forte 		    "Unable to allocate LOADLIST buffer.");
3252fcf3ce44SJohn Forte 
3253fcf3ce44SJohn Forte 		goto done;
3254fcf3ce44SJohn Forte 	}
3255291a2b48SSukumar Swaminathan 
3256fcf3ce44SJohn Forte 	if (emlxs_read_load_list(hba, LoadList)) {
3257fcf3ce44SJohn Forte 		goto done;
3258fcf3ce44SJohn Forte 	}
3259291a2b48SSukumar Swaminathan 
3260fcf3ce44SJohn Forte 	for (i = 0; i < LoadList->entry_cnt; i++) {
3261fcf3ce44SJohn Forte 		LoadEntry = &LoadList->load_entry[i];
3262fcf3ce44SJohn Forte 		if ((LoadEntry->un.wd[0] != 0) &&
3263fcf3ce44SJohn Forte 		    (LoadEntry->un.wd[0] != 0xffffffff)) {
3264fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
32656a573d82SSukumar Swaminathan 			    "Load List[%d]: %08x %08x", count,
3266291a2b48SSukumar Swaminathan 			    LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
32676a573d82SSukumar Swaminathan 
32686a573d82SSukumar Swaminathan 			load_list[count++] = LoadEntry->un.id;
3269fcf3ce44SJohn Forte 		}
3270fcf3ce44SJohn Forte 	}
3271fcf3ce44SJohn Forte 
3272fcf3ce44SJohn Forte done:
3273fcf3ce44SJohn Forte 
3274fcf3ce44SJohn Forte 	if (LoadList) {
3275fcf3ce44SJohn Forte 		kmem_free(LoadList, sizeof (LOAD_LIST));
3276fcf3ce44SJohn Forte 	}
3277291a2b48SSukumar Swaminathan 
32786a573d82SSukumar Swaminathan 	return (count);
3279fcf3ce44SJohn Forte 
328082527734SSukumar Swaminathan } /* emlxs_get_load_list() */
3281fcf3ce44SJohn Forte 
3282fcf3ce44SJohn Forte 
3283fcf3ce44SJohn Forte extern uint32_t
3284fcf3ce44SJohn Forte emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
3285fcf3ce44SJohn Forte     uint32_t verbose)
3286fcf3ce44SJohn Forte {
3287fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3288fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
3289fcf3ce44SJohn Forte 	MAILBOX *mb;
3290fcf3ce44SJohn Forte 	uint32_t rval = 0;
3291fcf3ce44SJohn Forte 	uint32_t *wd;
3292fcf3ce44SJohn Forte 
3293fcf3ce44SJohn Forte 	bzero(WakeUpParms, sizeof (WAKE_UP_PARMS));
3294fcf3ce44SJohn Forte 
3295291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3296291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3297fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3298fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3299fcf3ce44SJohn Forte 
3300fcf3ce44SJohn Forte 		return (1);
3301fcf3ce44SJohn Forte 	}
3302291a2b48SSukumar Swaminathan 
3303fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3304fcf3ce44SJohn Forte 
330582527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox,
3306291a2b48SSukumar Swaminathan 	    DMP_NV_PARAMS,
3307291a2b48SSukumar Swaminathan 	    WAKE_UP_PARMS_REGION_ID,
3308fcf3ce44SJohn Forte 	    sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
3309fcf3ce44SJohn Forte 
331082527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3311fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3312fcf3ce44SJohn Forte 		    "Unable to get parameters: Mailbox cmd=%x status=%x",
3313fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
3314fcf3ce44SJohn Forte 
3315fcf3ce44SJohn Forte 		if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) {
3316fcf3ce44SJohn Forte 			rval = (uint32_t)CFG_DATA_NO_REGION;
3317fcf3ce44SJohn Forte 		} else {
3318fcf3ce44SJohn Forte 			rval = 1;
3319fcf3ce44SJohn Forte 		}
3320fcf3ce44SJohn Forte 	} else {
332182527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
332282527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
332382527734SSukumar Swaminathan 			    0, hba->sli.sli4.dump_region.size,
332482527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
332582527734SSukumar Swaminathan 
332682527734SSukumar Swaminathan 			bcopy((caddr_t)hba->sli.sli4.dump_region.virt,
332782527734SSukumar Swaminathan 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
332882527734SSukumar Swaminathan 		} else {
332982527734SSukumar Swaminathan 			bcopy((caddr_t)&mb->un.varDmp.resp_offset,
333082527734SSukumar Swaminathan 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
333182527734SSukumar Swaminathan 		}
3332fcf3ce44SJohn Forte 
3333fcf3ce44SJohn Forte 		if (verbose) {
3334fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->prog_id;
3335fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3336291a2b48SSukumar Swaminathan 			    "Wakeup:      prog_id=%08x %08x", wd[0], wd[1]);
3337fcf3ce44SJohn Forte 
3338fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id;
3339fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3340291a2b48SSukumar Swaminathan 			    "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]);
3341fcf3ce44SJohn Forte 
3342fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli1_prog_id;
3343fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3344291a2b48SSukumar Swaminathan 			    "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]);
3345fcf3ce44SJohn Forte 
3346fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli2_prog_id;
3347fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3348291a2b48SSukumar Swaminathan 			    "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]);
3349fcf3ce44SJohn Forte 
3350fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli3_prog_id;
3351fcf3ce44SJohn Forte 			if (wd[0] || wd[1]) {
3352291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3353291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
3354291a2b48SSukumar Swaminathan 				    "Wakeup: sli3_prog_id=%08x %08x", wd[0],
3355291a2b48SSukumar Swaminathan 				    wd[1]);
3356fcf3ce44SJohn Forte 			}
3357291a2b48SSukumar Swaminathan 
3358fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli4_prog_id;
3359fcf3ce44SJohn Forte 			if (wd[0] || wd[1]) {
3360291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3361291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
3362291a2b48SSukumar Swaminathan 				    "Wakeup: sli4_prog_id=%08x %08x", wd[0],
3363291a2b48SSukumar Swaminathan 				    wd[1]);
3364fcf3ce44SJohn Forte 			}
3365291a2b48SSukumar Swaminathan 
3366fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id;
3367fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3368291a2b48SSukumar Swaminathan 			    "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]);
3369fcf3ce44SJohn Forte 
3370fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3371fcf3ce44SJohn Forte 			    "Wakeup: pci_cfg_rsvd=%x",
3372fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_rsvd);
3373fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3374fcf3ce44SJohn Forte 			    "Wakeup:  use_hdw_def=%x",
3375fcf3ce44SJohn Forte 			    WakeUpParms->use_hdw_def);
3376fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3377fcf3ce44SJohn Forte 			    "Wakeup:  pci_cfg_sel=%x",
3378fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_sel);
3379fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3380fcf3ce44SJohn Forte 			    "Wakeup:   cfg_lookup=%x",
3381fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_lookup_sel);
3382fcf3ce44SJohn Forte 		}
3383fcf3ce44SJohn Forte 	}
3384fcf3ce44SJohn Forte 
3385fcf3ce44SJohn Forte done:
3386fcf3ce44SJohn Forte 
3387fcf3ce44SJohn Forte 	if (mbox) {
3388fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3389fcf3ce44SJohn Forte 	}
3390291a2b48SSukumar Swaminathan 
3391b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3392b3660a96SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3393b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
3394b3660a96SSukumar Swaminathan 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3395b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3396b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3397b3660a96SSukumar Swaminathan 			    "emlxs_read_wakeup_parms: hdl=%p",
3398b3660a96SSukumar Swaminathan 			    hba->sli.sli4.dump_region.dma_handle);
3399b3660a96SSukumar Swaminathan 			rval = 1;
3400b3660a96SSukumar Swaminathan 		}
3401b3660a96SSukumar Swaminathan 	}
3402b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
3403b3660a96SSukumar Swaminathan 
3404fcf3ce44SJohn Forte 	return (rval);
3405fcf3ce44SJohn Forte 
340682527734SSukumar Swaminathan } /* emlxs_read_wakeup_parms() */
3407fcf3ce44SJohn Forte 
3408fcf3ce44SJohn Forte 
3409fcf3ce44SJohn Forte static uint32_t
3410291a2b48SSukumar Swaminathan emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
3411fcf3ce44SJohn Forte {
3412fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3413fcf3ce44SJohn Forte 	LOAD_ENTRY *LoadEntry;
3414fcf3ce44SJohn Forte 	uint32_t *Uptr;
3415fcf3ce44SJohn Forte 	uint32_t CurEntryAddr;
3416fcf3ce44SJohn Forte 	MAILBOXQ *mbox = NULL;
3417fcf3ce44SJohn Forte 	MAILBOX *mb;
3418fcf3ce44SJohn Forte 
3419fcf3ce44SJohn Forte 	bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
3420fcf3ce44SJohn Forte 
3421291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3422291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3423fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3424fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3425fcf3ce44SJohn Forte 
3426fcf3ce44SJohn Forte 		return (1);
3427fcf3ce44SJohn Forte 	}
3428291a2b48SSukumar Swaminathan 
3429fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3430fcf3ce44SJohn Forte 
343182527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
3432fcf3ce44SJohn Forte 
343382527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3434fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3435fcf3ce44SJohn Forte 		    "Unable to get load list: Mailbox cmd=%x status=%x",
3436fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
3437fcf3ce44SJohn Forte 
3438fcf3ce44SJohn Forte 		goto done;
3439fcf3ce44SJohn Forte 	}
3440291a2b48SSukumar Swaminathan 
344182527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
344282527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
344382527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
344482527734SSukumar Swaminathan 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
344582527734SSukumar Swaminathan 	} else {
344682527734SSukumar Swaminathan 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
344782527734SSukumar Swaminathan 	}
3448fcf3ce44SJohn Forte 
3449fcf3ce44SJohn Forte 	LoadList->head = Uptr[0];
3450fcf3ce44SJohn Forte 	LoadList->tail = Uptr[1];
3451fcf3ce44SJohn Forte 
3452fcf3ce44SJohn Forte 	CurEntryAddr = LoadList->head;
3453fcf3ce44SJohn Forte 
3454fcf3ce44SJohn Forte 	while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
3455fcf3ce44SJohn Forte 	    (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
3456fcf3ce44SJohn Forte 		LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
3457fcf3ce44SJohn Forte 		LoadList->entry_cnt++;
3458fcf3ce44SJohn Forte 
345982527734SSukumar Swaminathan 		emlxs_format_dump(hba, mbox,
3460291a2b48SSukumar Swaminathan 		    DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
3461fcf3ce44SJohn Forte 
346282527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3463291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
3464fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3465291a2b48SSukumar Swaminathan 			    "Unable to get load list (%d): Mailbox cmd=%x "
3466291a2b48SSukumar Swaminathan 			    "status=%x", LoadList->entry_cnt, mb->mbxCommand,
3467291a2b48SSukumar Swaminathan 			    mb->mbxStatus);
3468fcf3ce44SJohn Forte 
3469fcf3ce44SJohn Forte 			goto done;
3470fcf3ce44SJohn Forte 		}
3471291a2b48SSukumar Swaminathan 
347282527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
347382527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
347482527734SSukumar Swaminathan 			    0, hba->sli.sli4.dump_region.size,
347582527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
347682527734SSukumar Swaminathan 			Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
347782527734SSukumar Swaminathan 		} else {
347882527734SSukumar Swaminathan 			Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
347982527734SSukumar Swaminathan 		}
3480fcf3ce44SJohn Forte 
3481fcf3ce44SJohn Forte 		LoadEntry->next = Uptr[0];
3482fcf3ce44SJohn Forte 		LoadEntry->prev = Uptr[1];
3483fcf3ce44SJohn Forte 		LoadEntry->start_adr = Uptr[2];
3484fcf3ce44SJohn Forte 		LoadEntry->len = Uptr[3];
3485fcf3ce44SJohn Forte 		LoadEntry->un.wd[0] = Uptr[4];
3486fcf3ce44SJohn Forte 		LoadEntry->un.wd[1] = Uptr[5];
3487fcf3ce44SJohn Forte 
3488fcf3ce44SJohn Forte 		/* update next current load entry address */
3489fcf3ce44SJohn Forte 		CurEntryAddr = LoadEntry->next;
3490fcf3ce44SJohn Forte 
3491fcf3ce44SJohn Forte 	}	/* end of while (not end of list) */
3492fcf3ce44SJohn Forte 
3493fcf3ce44SJohn Forte done:
3494fcf3ce44SJohn Forte 
3495fcf3ce44SJohn Forte 	if (mbox) {
3496fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3497fcf3ce44SJohn Forte 	}
3498291a2b48SSukumar Swaminathan 
3499b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3500b3660a96SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3501b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
3502b3660a96SSukumar Swaminathan 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3503b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3504b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3505b3660a96SSukumar Swaminathan 			    "emlxs_read_load_list: hdl=%p",
3506b3660a96SSukumar Swaminathan 			    hba->sli.sli4.dump_region.dma_handle);
3507b3660a96SSukumar Swaminathan 			return (1);
3508b3660a96SSukumar Swaminathan 		}
3509b3660a96SSukumar Swaminathan 	}
3510b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
3511b3660a96SSukumar Swaminathan 
3512fcf3ce44SJohn Forte 	return (0);
3513fcf3ce44SJohn Forte 
351482527734SSukumar Swaminathan } /* emlxs_read_load_list() */
3515fcf3ce44SJohn Forte 
3516fcf3ce44SJohn Forte 
3517fcf3ce44SJohn Forte 
3518*a9800bebSGarrett D'Amore 
3519fcf3ce44SJohn Forte static int
3520291a2b48SSukumar Swaminathan emlxs_build_parms(caddr_t Buffer,
3521291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS AbsWakeUpParms,
35226a573d82SSukumar Swaminathan     uint32_t BufferSize, PAIF_HDR AifHeader)
3523fcf3ce44SJohn Forte {
3524fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
3525fcf3ce44SJohn Forte 	uint32_t NextImage;
3526fcf3ce44SJohn Forte 	uint32_t i;
3527fcf3ce44SJohn Forte 	int32_t ChangeParams = FALSE;
3528fcf3ce44SJohn Forte 	caddr_t Sptr;
3529fcf3ce44SJohn Forte 	caddr_t Dptr;
3530fcf3ce44SJohn Forte 
3531fcf3ce44SJohn Forte 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
3532fcf3ce44SJohn Forte 
35336a573d82SSukumar Swaminathan 	if ((AifHeader->ImageBase != 0x20000) &&
35346a573d82SSukumar Swaminathan 	    ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
3535fcf3ce44SJohn Forte 		return (FALSE);
3536fcf3ce44SJohn Forte 	}
3537291a2b48SSukumar Swaminathan 
3538fcf3ce44SJohn Forte 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
3539fcf3ce44SJohn Forte 
3540fcf3ce44SJohn Forte 	while (BufferSize > NextImage) {
3541fcf3ce44SJohn Forte 		Sptr = &Buffer[NextImage];
3542fcf3ce44SJohn Forte 		Dptr = (caddr_t)&ImageHdr;
3543fcf3ce44SJohn Forte 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
3544fcf3ce44SJohn Forte 			Dptr[i] = Sptr[i];
3545fcf3ce44SJohn Forte 		}
3546fcf3ce44SJohn Forte 
3547fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff)
3548fcf3ce44SJohn Forte 			break;
3549fcf3ce44SJohn Forte 
3550fcf3ce44SJohn Forte 		switch (ImageHdr.Id.Type) {
3551fcf3ce44SJohn Forte 		case TEST_PROGRAM:
3552fcf3ce44SJohn Forte 			break;
3553fcf3ce44SJohn Forte 		case FUNC_FIRMWARE:
3554fcf3ce44SJohn Forte 			AbsWakeUpParms->prog_id = ImageHdr.Id;
3555fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3556fcf3ce44SJohn Forte 			break;
3557fcf3ce44SJohn Forte 		case BOOT_BIOS:
3558fcf3ce44SJohn Forte 			AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
3559fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3560fcf3ce44SJohn Forte 			break;
3561fcf3ce44SJohn Forte 		case SLI1_OVERLAY:
3562fcf3ce44SJohn Forte 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
3563fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3564fcf3ce44SJohn Forte 			break;
3565fcf3ce44SJohn Forte 		case SLI2_OVERLAY:
3566fcf3ce44SJohn Forte 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
3567fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3568fcf3ce44SJohn Forte 			break;
3569fcf3ce44SJohn Forte 		case SLI3_OVERLAY:
3570fcf3ce44SJohn Forte 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
3571fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3572fcf3ce44SJohn Forte 			break;
3573fcf3ce44SJohn Forte 		case SLI4_OVERLAY:
3574fcf3ce44SJohn Forte 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
3575fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3576fcf3ce44SJohn Forte 			break;
3577fcf3ce44SJohn Forte 		default:
3578fcf3ce44SJohn Forte 			break;
3579fcf3ce44SJohn Forte 		}
3580fcf3ce44SJohn Forte 
3581fcf3ce44SJohn Forte 		NextImage += ImageHdr.BlockSize;
3582fcf3ce44SJohn Forte 	}
3583fcf3ce44SJohn Forte 
3584fcf3ce44SJohn Forte 	return (ChangeParams);
3585fcf3ce44SJohn Forte 
358682527734SSukumar Swaminathan } /* emlxs_build_parms() */
3587fcf3ce44SJohn Forte 
3588fcf3ce44SJohn Forte 
3589fcf3ce44SJohn Forte static uint32_t
3590fcf3ce44SJohn Forte emlxs_update_wakeup_parms(emlxs_hba_t *hba,
3591fcf3ce44SJohn Forte     PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
3592fcf3ce44SJohn Forte {
3593fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3594fcf3ce44SJohn Forte 	MAILBOX *mb;
3595fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
3596fcf3ce44SJohn Forte 	uint32_t rval = 0;
3597fcf3ce44SJohn Forte 
3598291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3599291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3600fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3601fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3602fcf3ce44SJohn Forte 
3603fcf3ce44SJohn Forte 		return (1);
3604fcf3ce44SJohn Forte 	}
3605291a2b48SSukumar Swaminathan 
3606fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3607fcf3ce44SJohn Forte 
3608fcf3ce44SJohn Forte 	WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
3609fcf3ce44SJohn Forte 	WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
3610fcf3ce44SJohn Forte 	WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
3611fcf3ce44SJohn Forte 	WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
3612fcf3ce44SJohn Forte 	WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
3613fcf3ce44SJohn Forte 	WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
3614fcf3ce44SJohn Forte 
361582527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
3616fcf3ce44SJohn Forte 
361782527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3618fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3619291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
3620291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
3621fcf3ce44SJohn Forte 
3622fcf3ce44SJohn Forte 		rval = 1;
3623fcf3ce44SJohn Forte 	}
3624291a2b48SSukumar Swaminathan 
3625fcf3ce44SJohn Forte 	if (mbox) {
3626fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3627fcf3ce44SJohn Forte 	}
3628291a2b48SSukumar Swaminathan 
3629fcf3ce44SJohn Forte 	return (rval);
3630fcf3ce44SJohn Forte 
363182527734SSukumar Swaminathan } /* emlxs_update_wakeup_parms() */
3632fcf3ce44SJohn Forte 
3633fcf3ce44SJohn Forte 
3634fcf3ce44SJohn Forte static uint32_t
3635291a2b48SSukumar Swaminathan emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
3636291a2b48SSukumar Swaminathan     uint32_t type, char *file_type)
3637fcf3ce44SJohn Forte {
3638fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3639fcf3ce44SJohn Forte 
3640fcf3ce44SJohn Forte 	/* Create the version label */
3641fcf3ce44SJohn Forte 	emlxs_decode_version(file->version, file->label);
3642fcf3ce44SJohn Forte 
3643fcf3ce44SJohn Forte 	/* Process the DWC type */
3644fcf3ce44SJohn Forte 	switch (type) {
3645fcf3ce44SJohn Forte 	case TEST_PROGRAM:
3646fcf3ce44SJohn Forte 
3647fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3648291a2b48SSukumar Swaminathan 		    "%s: TEST: offset=%08x  version=%08x, %s", file_type,
3649291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3650fcf3ce44SJohn Forte 
3651fcf3ce44SJohn Forte 		break;
3652fcf3ce44SJohn Forte 
3653fcf3ce44SJohn Forte 	case BOOT_BIOS:
3654fcf3ce44SJohn Forte 
3655fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3656291a2b48SSukumar Swaminathan 		    "%s: BOOT: offset=%08x  version=%08x, %s", file_type,
3657291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3658fcf3ce44SJohn Forte 
3659fcf3ce44SJohn Forte 		if (!emlxs_bios_check(hba, id)) {
3660fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3661fcf3ce44SJohn Forte 			    "BOOT Check: Image not compatible with %s. id=%02x",
3662fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3663fcf3ce44SJohn Forte 
3664fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3665fcf3ce44SJohn Forte 		}
3666291a2b48SSukumar Swaminathan 
3667fcf3ce44SJohn Forte 		break;
3668fcf3ce44SJohn Forte 
3669fcf3ce44SJohn Forte 	case FUNC_FIRMWARE:	/* Stub */
3670fcf3ce44SJohn Forte 
3671fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3672291a2b48SSukumar Swaminathan 		    "%s: STUB: offset=%08x  version=%08x, %s", file_type,
3673291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3674fcf3ce44SJohn Forte 
3675fcf3ce44SJohn Forte 		if (!emlxs_stub_check(hba, id)) {
3676fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3677fcf3ce44SJohn Forte 			    "STUB Check: Image not compatible with %s. id=%02x",
3678fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3679fcf3ce44SJohn Forte 
3680fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3681fcf3ce44SJohn Forte 		}
3682291a2b48SSukumar Swaminathan 
3683fcf3ce44SJohn Forte 		break;
3684fcf3ce44SJohn Forte 
3685fcf3ce44SJohn Forte 	case SLI1_OVERLAY:
3686fcf3ce44SJohn Forte 
3687fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3688291a2b48SSukumar Swaminathan 		    "%s: SLI1: offset=%08x  version=%08x, %s", file_type,
3689291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3690fcf3ce44SJohn Forte 
3691fcf3ce44SJohn Forte 		if (!emlxs_sli1_check(hba, id)) {
3692fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3693fcf3ce44SJohn Forte 			    "SLI1 Check: Image not compatible with %s. id=%02x",
3694fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3695fcf3ce44SJohn Forte 
3696fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3697fcf3ce44SJohn Forte 		}
3698291a2b48SSukumar Swaminathan 
3699fcf3ce44SJohn Forte 		break;
3700fcf3ce44SJohn Forte 
3701fcf3ce44SJohn Forte 	case SLI2_OVERLAY:
3702fcf3ce44SJohn Forte 
3703fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3704291a2b48SSukumar Swaminathan 		    "%s: SLI2: offset=%08x  version=%08x, %s", file_type,
3705291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3706fcf3ce44SJohn Forte 
3707fcf3ce44SJohn Forte 		if (!emlxs_sli2_check(hba, id)) {
3708fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3709fcf3ce44SJohn Forte 			    "SLI2 Check: Image not compatible with %s. id=%02x",
3710fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3711fcf3ce44SJohn Forte 
3712fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3713fcf3ce44SJohn Forte 		}
3714291a2b48SSukumar Swaminathan 
3715fcf3ce44SJohn Forte 		break;
3716fcf3ce44SJohn Forte 
3717fcf3ce44SJohn Forte 	case SLI3_OVERLAY:
3718fcf3ce44SJohn Forte 
3719fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3720291a2b48SSukumar Swaminathan 		    "%s: SLI3: offset=%08x  version=%08x, %s", file_type,
3721291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3722fcf3ce44SJohn Forte 
3723fcf3ce44SJohn Forte 		if (!emlxs_sli3_check(hba, id)) {
3724fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3725fcf3ce44SJohn Forte 			    "SLI3 Check: Image not compatible with %s. id=%02x",
3726fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3727fcf3ce44SJohn Forte 
3728fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3729fcf3ce44SJohn Forte 		}
3730291a2b48SSukumar Swaminathan 
3731fcf3ce44SJohn Forte 		break;
3732fcf3ce44SJohn Forte 
3733fcf3ce44SJohn Forte 	case SLI4_OVERLAY:
3734fcf3ce44SJohn Forte 
3735fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3736291a2b48SSukumar Swaminathan 		    "%s: SLI4: offset=%08x  version=%08x, %s", file_type,
3737291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3738fcf3ce44SJohn Forte 
3739fcf3ce44SJohn Forte 		if (!emlxs_sli4_check(hba, id)) {
3740fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3741fcf3ce44SJohn Forte 			    "SLI4 Check: Image not compatible with %s. id=%02x",
3742fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3743fcf3ce44SJohn Forte 
3744fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3745fcf3ce44SJohn Forte 		}
3746291a2b48SSukumar Swaminathan 
3747fcf3ce44SJohn Forte 		break;
3748fcf3ce44SJohn Forte 
3749fcf3ce44SJohn Forte 	case SBUS_FCODE:
3750fcf3ce44SJohn Forte 
3751fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3752fcf3ce44SJohn Forte 		    "%s: SBUS FCODE: offset=%08x  version=%08x, %s",
3753291a2b48SSukumar Swaminathan 		    file_type, file->offset, file->version, file->label);
3754fcf3ce44SJohn Forte 
3755fcf3ce44SJohn Forte 		if (!emlxs_sbus_fcode_check(hba, id)) {
3756fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3757fcf3ce44SJohn Forte 			    "SBUS FCODE Check: Image not compatible with %s. "
3758291a2b48SSukumar Swaminathan 			    "id=%02x", hba->model_info.model, id);
3759fcf3ce44SJohn Forte 
3760fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3761fcf3ce44SJohn Forte 		}
3762291a2b48SSukumar Swaminathan 
3763fcf3ce44SJohn Forte 		break;
3764fcf3ce44SJohn Forte 
3765fcf3ce44SJohn Forte 	case KERNEL_CODE:
3766fcf3ce44SJohn Forte 
3767fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3768291a2b48SSukumar Swaminathan 		    "%s: KERN: offset=%08x  version=%08x, %s", file_type,
3769291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3770fcf3ce44SJohn Forte 
3771fcf3ce44SJohn Forte 		if (!emlxs_kern_check(hba, id)) {
3772fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3773fcf3ce44SJohn Forte 			    "KERN Check: Image not compatible with %s. id=%02x",
3774fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3775fcf3ce44SJohn Forte 
3776fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3777fcf3ce44SJohn Forte 		}
3778291a2b48SSukumar Swaminathan 
3779fcf3ce44SJohn Forte 		break;
3780fcf3ce44SJohn Forte 
3781fcf3ce44SJohn Forte 	default:
3782fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3783291a2b48SSukumar Swaminathan 		    "%s: Image type not supported. type=%x", file_type, type);
3784fcf3ce44SJohn Forte 
3785fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
3786fcf3ce44SJohn Forte 	}
3787fcf3ce44SJohn Forte 
3788fcf3ce44SJohn Forte 	return (0);
3789fcf3ce44SJohn Forte 
379082527734SSukumar Swaminathan } /* emlxs_validate_version() */
3791fcf3ce44SJohn Forte 
3792fcf3ce44SJohn Forte 
37936a573d82SSukumar Swaminathan static void
37946a573d82SSukumar Swaminathan emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *fw_image)
37956a573d82SSukumar Swaminathan {
37966a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
37976a573d82SSukumar Swaminathan 	emlxs_vpd_t *vpd = &VPD;
37986a573d82SSukumar Swaminathan 	uint32_t i;
37996a573d82SSukumar Swaminathan 	uint32_t count;
38006a573d82SSukumar Swaminathan 
38016a573d82SSukumar Swaminathan 	/* Check for AWC file */
38026a573d82SSukumar Swaminathan 	if (fw_image->awc.version) {
38036a573d82SSukumar Swaminathan 		if (fw_image->awc.version == vpd->postKernRev) {
38046a573d82SSukumar Swaminathan 			fw_image->awc.version = 0;
38056a573d82SSukumar Swaminathan 		}
38066a573d82SSukumar Swaminathan 
38076a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
38086a573d82SSukumar Swaminathan 		    "AWC file: KERN: old=%s  new=%s  %s.",
38096a573d82SSukumar Swaminathan 		    vpd->postKernName,
38106a573d82SSukumar Swaminathan 		    fw_image->awc.label,
38116a573d82SSukumar Swaminathan 		    (fw_image->awc.version)? "Update":"Skip");
38126a573d82SSukumar Swaminathan 	}
38136a573d82SSukumar Swaminathan 
38146a573d82SSukumar Swaminathan 	/* Check for BWC file */
38156a573d82SSukumar Swaminathan 	if (fw_image->bwc.version) {
38166a573d82SSukumar Swaminathan 		if (strcmp(vpd->fcode_version, fw_image->bwc.label) == 0) {
38176a573d82SSukumar Swaminathan 			fw_image->bwc.version = 0;
38186a573d82SSukumar Swaminathan 		}
38196a573d82SSukumar Swaminathan 
38206a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
38216a573d82SSukumar Swaminathan 		    "BWC file: BOOT: old=%s  new=%s  %s.",
38226a573d82SSukumar Swaminathan 		    vpd->fcode_version,
38236a573d82SSukumar Swaminathan 		    fw_image->bwc.label,
38246a573d82SSukumar Swaminathan 		    (fw_image->bwc.version)? "Update":"Skip");
38256a573d82SSukumar Swaminathan 	}
38266a573d82SSukumar Swaminathan 
38276a573d82SSukumar Swaminathan 	/* Check for DWC file */
38286a573d82SSukumar Swaminathan 	if (fw_image->dwc.version) {
38296a573d82SSukumar Swaminathan 		/* Check for program files */
38306a573d82SSukumar Swaminathan 		count = 0;
38316a573d82SSukumar Swaminathan 		for (i = 0; i < MAX_PROG_TYPES; i++) {
38326a573d82SSukumar Swaminathan 			if (!fw_image->prog[i].version) {
38336a573d82SSukumar Swaminathan 				continue;
38346a573d82SSukumar Swaminathan 			}
38356a573d82SSukumar Swaminathan 
38366a573d82SSukumar Swaminathan 			/* Skip components that don't need updating */
38376a573d82SSukumar Swaminathan 			switch (i) {
38386a573d82SSukumar Swaminathan 			case TEST_PROGRAM:
38396a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
38406a573d82SSukumar Swaminathan 				    "DWC file: TEST:             new=%s  "
38416a573d82SSukumar Swaminathan 				    "Update.",
38426a573d82SSukumar Swaminathan 				    fw_image->prog[i].label);
38436a573d82SSukumar Swaminathan 				break;
38446a573d82SSukumar Swaminathan 
38456a573d82SSukumar Swaminathan 			case BOOT_BIOS:
38466a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
38476a573d82SSukumar Swaminathan 				    "DWC file: BOOT:             new=%s  "
38486a573d82SSukumar Swaminathan 				    "Update.",
38496a573d82SSukumar Swaminathan 				    fw_image->prog[i].label);
38506a573d82SSukumar Swaminathan 				break;
38516a573d82SSukumar Swaminathan 
38526a573d82SSukumar Swaminathan 			case FUNC_FIRMWARE:
38536a573d82SSukumar Swaminathan 				if (vpd->opFwRev &&
38546a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
38556a573d82SSukumar Swaminathan 				    vpd->opFwRev)) {
38566a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
38576a573d82SSukumar Swaminathan 				}
38586a573d82SSukumar Swaminathan 
38596a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
38606a573d82SSukumar Swaminathan 				    "DWC file: STUB: old=%s  new=%s  %s.",
38616a573d82SSukumar Swaminathan 				    vpd->opFwName,
38626a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
38636a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
38646a573d82SSukumar Swaminathan 				    "Update":"Skip");
38656a573d82SSukumar Swaminathan 				break;
38666a573d82SSukumar Swaminathan 
38676a573d82SSukumar Swaminathan 			case SLI1_OVERLAY:
38686a573d82SSukumar Swaminathan 				if (vpd->sli1FwRev &&
38696a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
38706a573d82SSukumar Swaminathan 				    vpd->sli1FwRev)) {
38716a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
38726a573d82SSukumar Swaminathan 				}
38736a573d82SSukumar Swaminathan 
38746a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
38756a573d82SSukumar Swaminathan 				    "DWC file: SLI1: old=%s  new=%s  %s.",
38766a573d82SSukumar Swaminathan 				    vpd->sli1FwName,
38776a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
38786a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
38796a573d82SSukumar Swaminathan 				    "Update":"Skip");
38806a573d82SSukumar Swaminathan 				break;
38816a573d82SSukumar Swaminathan 
38826a573d82SSukumar Swaminathan 			case SLI2_OVERLAY:
38836a573d82SSukumar Swaminathan 				if (vpd->sli2FwRev &&
38846a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
38856a573d82SSukumar Swaminathan 				    vpd->sli2FwRev)) {
38866a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
38876a573d82SSukumar Swaminathan 				}
38886a573d82SSukumar Swaminathan 
38896a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
38906a573d82SSukumar Swaminathan 				    "DWC file: SLI2: old=%s  new=%s  %s.",
38916a573d82SSukumar Swaminathan 				    vpd->sli2FwName,
38926a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
38936a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
38946a573d82SSukumar Swaminathan 				    "Update":"Skip");
38956a573d82SSukumar Swaminathan 				break;
38966a573d82SSukumar Swaminathan 
38976a573d82SSukumar Swaminathan 			case SLI3_OVERLAY:
38986a573d82SSukumar Swaminathan 				if (vpd->sli3FwRev &&
38996a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
39006a573d82SSukumar Swaminathan 				    vpd->sli3FwRev)) {
39016a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
39026a573d82SSukumar Swaminathan 				}
39036a573d82SSukumar Swaminathan 
39046a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
39056a573d82SSukumar Swaminathan 				    "DWC file: SLI3: old=%s  new=%s  %s.",
39066a573d82SSukumar Swaminathan 				    vpd->sli3FwName,
39076a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
39086a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
39096a573d82SSukumar Swaminathan 				    "Update":"Skip");
39106a573d82SSukumar Swaminathan 				break;
39116a573d82SSukumar Swaminathan 
39126a573d82SSukumar Swaminathan 			case SLI4_OVERLAY:
39136a573d82SSukumar Swaminathan 				if (vpd->sli4FwRev &&
39146a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
39156a573d82SSukumar Swaminathan 				    vpd->sli4FwRev)) {
39166a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
39176a573d82SSukumar Swaminathan 				}
39186a573d82SSukumar Swaminathan 
39196a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
39206a573d82SSukumar Swaminathan 				    "DWC file: SLI4: old=%s  new=%s  %s.",
39216a573d82SSukumar Swaminathan 				    vpd->sli4FwRev,
39226a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
39236a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
39246a573d82SSukumar Swaminathan 				    "Update":"Skip");
39256a573d82SSukumar Swaminathan 				break;
39266a573d82SSukumar Swaminathan 
39276a573d82SSukumar Swaminathan 			default:
39286a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
39296a573d82SSukumar Swaminathan 				    "DWC file: type=%x version=%x label=%s  "
39306a573d82SSukumar Swaminathan 				    "Update.",
39316a573d82SSukumar Swaminathan 				    i,
39326a573d82SSukumar Swaminathan 				    fw_image->prog[i].version,
39336a573d82SSukumar Swaminathan 				    fw_image->prog[i].label);
39346a573d82SSukumar Swaminathan 			}
39356a573d82SSukumar Swaminathan 
39366a573d82SSukumar Swaminathan 			if (fw_image->prog[i].version) {
39376a573d82SSukumar Swaminathan 				count++;
39386a573d82SSukumar Swaminathan 			}
39396a573d82SSukumar Swaminathan 		}
39406a573d82SSukumar Swaminathan 
39416a573d82SSukumar Swaminathan 		if (!count) {
39426a573d82SSukumar Swaminathan 			fw_image->dwc.version = 0;
39436a573d82SSukumar Swaminathan 		}
39446a573d82SSukumar Swaminathan 	}
39456a573d82SSukumar Swaminathan 
39466a573d82SSukumar Swaminathan 	return;
39476a573d82SSukumar Swaminathan 
39486a573d82SSukumar Swaminathan } /* emlxs_verify_image() */
39496a573d82SSukumar Swaminathan 
39506a573d82SSukumar Swaminathan 
3951fcf3ce44SJohn Forte static uint32_t
3952fcf3ce44SJohn Forte emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
3953fcf3ce44SJohn Forte     emlxs_fw_image_t *image)
3954fcf3ce44SJohn Forte {
3955fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3956fcf3ce44SJohn Forte 	uint32_t ImageType;
3957fcf3ce44SJohn Forte 	AIF_HDR AifHdr;
3958fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
3959fcf3ce44SJohn Forte 	uint32_t NextImage;
39606a573d82SSukumar Swaminathan 	uint32_t count;
3961fcf3ce44SJohn Forte 	uint32_t FileType;
3962fcf3ce44SJohn Forte 	uint32_t FileLen = 0;
3963fcf3ce44SJohn Forte 	uint32_t TotalLen = 0;
3964fcf3ce44SJohn Forte 	uint32_t *CkSumEnd;
3965fcf3ce44SJohn Forte 	uint32_t id;
3966fcf3ce44SJohn Forte 	uint32_t type;
3967fcf3ce44SJohn Forte 	uint32_t ver;
3968fcf3ce44SJohn Forte 	uint32_t ImageLength;
3969fcf3ce44SJohn Forte 	uint32_t BufferSize;
3970fcf3ce44SJohn Forte 	uint32_t rval = 0;
3971fcf3ce44SJohn Forte 	caddr_t bptr;
3972fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
3973fcf3ce44SJohn Forte 
3974fcf3ce44SJohn Forte 	vpd = &VPD;
3975fcf3ce44SJohn Forte 
3976fcf3ce44SJohn Forte 	/* Get image type */
3977fcf3ce44SJohn Forte 	ImageType = *((uint32_t *)Buffer);
3978fcf3ce44SJohn Forte 
3979fcf3ce44SJohn Forte 	/* Pegasus and beyond adapters */
3980fcf3ce44SJohn Forte 	if ((ImageType == NOP_IMAGE_TYPE) &&
3981fcf3ce44SJohn Forte 	    !(hba->model_info.chip &
3982fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
3983fcf3ce44SJohn Forte 		bptr = Buffer;
3984fcf3ce44SJohn Forte 		TotalLen = sizeof (uint32_t);
3985fcf3ce44SJohn Forte 
3986fcf3ce44SJohn Forte 		while (TotalLen < Size) {
3987fcf3ce44SJohn Forte 			if (Size < sizeof (AIF_HDR)) {
3988291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3989291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
3990fcf3ce44SJohn Forte 				    "Invalid image header length: 0x%x < 0x%x",
3991fcf3ce44SJohn Forte 				    Size, sizeof (AIF_HDR));
3992fcf3ce44SJohn Forte 
3993fcf3ce44SJohn Forte 				return (EMLXS_IMAGE_BAD);
3994fcf3ce44SJohn Forte 			}
3995291a2b48SSukumar Swaminathan 
3996fcf3ce44SJohn Forte 			bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
3997fcf3ce44SJohn Forte 			emlxs_disp_aif_header(hba, &AifHdr);
3998fcf3ce44SJohn Forte 
3999fcf3ce44SJohn Forte 			ImageLength = AifHdr.RoSize;
4000fcf3ce44SJohn Forte 
4001fcf3ce44SJohn Forte 			/* Validate checksum */
4002291a2b48SSukumar Swaminathan 			CkSumEnd =
4003291a2b48SSukumar Swaminathan 			    (uint32_t *)(bptr + ImageLength +
4004291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR));
4005fcf3ce44SJohn Forte 			if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
4006291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
4007291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
4008fcf3ce44SJohn Forte 				    "Invalid checksum found.");
4009fcf3ce44SJohn Forte 
4010fcf3ce44SJohn Forte 				return (EMLXS_IMAGE_BAD);
4011fcf3ce44SJohn Forte 			}
4012291a2b48SSukumar Swaminathan 
4013fcf3ce44SJohn Forte 			FileType = AifHdr.ZinitBr;
4014fcf3ce44SJohn Forte 			switch (FileType) {
4015fcf3ce44SJohn Forte 			case FILE_TYPE_AWC:
4016291a2b48SSukumar Swaminathan 				image->awc.offset =
4017291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
4018291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
4019fcf3ce44SJohn Forte 				image->awc.version = AifHdr.AVersion;
4020fcf3ce44SJohn Forte 				image->awc.revcomp = 0;
4021fcf3ce44SJohn Forte 
4022fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4023fcf3ce44SJohn Forte 				type = emlxs_type_check(
4024fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
4025fcf3ce44SJohn Forte 
4026fcf3ce44SJohn Forte 				/* Validate the file version */
4027fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
4028fcf3ce44SJohn Forte 				    &image->awc, id, type, "AWC file"))) {
4029fcf3ce44SJohn Forte 					return (rval);
4030fcf3ce44SJohn Forte 				}
4031291a2b48SSukumar Swaminathan 
4032fcf3ce44SJohn Forte 				break;
4033fcf3ce44SJohn Forte 
4034fcf3ce44SJohn Forte 			case FILE_TYPE_BWC:
4035291a2b48SSukumar Swaminathan 				image->bwc.offset =
4036291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
4037291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
4038fcf3ce44SJohn Forte 				image->bwc.version = AifHdr.AVersion;
4039fcf3ce44SJohn Forte 				image->bwc.revcomp = 0;
4040fcf3ce44SJohn Forte 
4041fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4042fcf3ce44SJohn Forte 				type = emlxs_type_check(
4043fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
4044fcf3ce44SJohn Forte 
4045fcf3ce44SJohn Forte 				/* Validate the file version */
4046fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
4047fcf3ce44SJohn Forte 				    &image->bwc, id, type, "BWC file"))) {
4048fcf3ce44SJohn Forte 					return (rval);
4049fcf3ce44SJohn Forte 				}
4050291a2b48SSukumar Swaminathan 
4051fcf3ce44SJohn Forte 				break;
4052fcf3ce44SJohn Forte 
4053fcf3ce44SJohn Forte 			case FILE_TYPE_DWC:
4054291a2b48SSukumar Swaminathan 				image->dwc.offset =
4055291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
4056291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
4057fcf3ce44SJohn Forte 				image->dwc.version = AifHdr.AVersion;
4058fcf3ce44SJohn Forte 				image->dwc.revcomp = 0;
4059fcf3ce44SJohn Forte 
4060fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4061fcf3ce44SJohn Forte 				type = emlxs_type_check(
4062fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
4063fcf3ce44SJohn Forte 
4064fcf3ce44SJohn Forte 				/* Validate the file version */
4065fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
4066fcf3ce44SJohn Forte 				    &image->dwc, id, type, "DWC file"))) {
4067fcf3ce44SJohn Forte 					return (rval);
4068fcf3ce44SJohn Forte 				}
4069291a2b48SSukumar Swaminathan 
4070fcf3ce44SJohn Forte 				/* Scan for program types */
4071fcf3ce44SJohn Forte 				NextImage = sizeof (AIF_HDR) + 4;
4072fcf3ce44SJohn Forte 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
4073fcf3ce44SJohn Forte 
40746a573d82SSukumar Swaminathan 				count = 0;
4075fcf3ce44SJohn Forte 				while (BufferSize > NextImage) {
4076fcf3ce44SJohn Forte 					bcopy(&bptr[NextImage], &ImageHdr,
4077fcf3ce44SJohn Forte 					    sizeof (IMAGE_HDR));
4078291a2b48SSukumar Swaminathan 					emlxs_dump_image_header(hba,
4079291a2b48SSukumar Swaminathan 					    &ImageHdr);
4080fcf3ce44SJohn Forte 
4081fcf3ce44SJohn Forte 					/* Validate block size */
4082fcf3ce44SJohn Forte 					if (ImageHdr.BlockSize == 0xffffffff) {
4083fcf3ce44SJohn Forte 						break;
4084fcf3ce44SJohn Forte 					}
4085291a2b48SSukumar Swaminathan 
4086fcf3ce44SJohn Forte 					type = emlxs_type_check(
4087fcf3ce44SJohn Forte 					    ImageHdr.Id.Type);
4088fcf3ce44SJohn Forte 
4089fcf3ce44SJohn Forte 					/* Calculate the program offset */
4090291a2b48SSukumar Swaminathan 					image->prog[type].offset =
4091291a2b48SSukumar Swaminathan 					    (uint32_t)((uintptr_t)
4092291a2b48SSukumar Swaminathan 					    &bptr[NextImage] -
4093fcf3ce44SJohn Forte 					    (uintptr_t)Buffer);
4094fcf3ce44SJohn Forte 
4095fcf3ce44SJohn Forte 					/* Acquire the versions */
4096fcf3ce44SJohn Forte 					image->prog[type].version =
4097fcf3ce44SJohn Forte 					    (ImageHdr.Id.Type << 24) |
4098fcf3ce44SJohn Forte 					    (ImageHdr.Id.Id << 16) |
4099fcf3ce44SJohn Forte 					    (ImageHdr.Id.Ver << 8) |
4100fcf3ce44SJohn Forte 					    ImageHdr.Id.Rev;
4101fcf3ce44SJohn Forte 
4102fcf3ce44SJohn Forte 					image->prog[type].revcomp =
4103fcf3ce44SJohn Forte 					    ImageHdr.Id.un.revcomp;
4104fcf3ce44SJohn Forte 
4105fcf3ce44SJohn Forte 					/* Validate the file version */
4106fcf3ce44SJohn Forte 					if ((rval = emlxs_validate_version(hba,
4107fcf3ce44SJohn Forte 					    &image->prog[type], ImageHdr.Id.Id,
4108fcf3ce44SJohn Forte 					    type, "DWC prog"))) {
4109fcf3ce44SJohn Forte 						return (rval);
4110fcf3ce44SJohn Forte 					}
4111291a2b48SSukumar Swaminathan 
41126a573d82SSukumar Swaminathan 					count++;
4113fcf3ce44SJohn Forte 					NextImage += ImageHdr.BlockSize;
4114fcf3ce44SJohn Forte 
411582527734SSukumar Swaminathan 				}	/* while () */
4116fcf3ce44SJohn Forte 
41176a573d82SSukumar Swaminathan 				if (count == 0) {
41186a573d82SSukumar Swaminathan 					EMLXS_MSGF(EMLXS_CONTEXT,
41196a573d82SSukumar Swaminathan 					    &emlxs_image_bad_msg,
41206a573d82SSukumar Swaminathan 					    "DWC file has no PRG images.");
41216a573d82SSukumar Swaminathan 
41226a573d82SSukumar Swaminathan 					return (EMLXS_IMAGE_BAD);
41236a573d82SSukumar Swaminathan 				}
41246a573d82SSukumar Swaminathan 
4125fcf3ce44SJohn Forte 				break;
4126fcf3ce44SJohn Forte 			}
4127fcf3ce44SJohn Forte 
4128291a2b48SSukumar Swaminathan 			FileLen =
4129291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR) + ImageLength +
4130fcf3ce44SJohn Forte 			    sizeof (uint32_t);
4131fcf3ce44SJohn Forte 			TotalLen += FileLen;
4132fcf3ce44SJohn Forte 			bptr += FileLen;
4133fcf3ce44SJohn Forte 		}
4134fcf3ce44SJohn Forte 	}
4135291a2b48SSukumar Swaminathan 
4136fcf3ce44SJohn Forte 	/* Pre-pegasus adapters */
4137fcf3ce44SJohn Forte 
4138fcf3ce44SJohn Forte 	else if (ImageType == NOP_IMAGE_TYPE) {
4139fcf3ce44SJohn Forte 		if (Size < sizeof (AIF_HDR)) {
4140fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4141291a2b48SSukumar Swaminathan 			    "Invalid image header length: 0x%x < 0x%x", Size,
4142291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR));
4143fcf3ce44SJohn Forte 
4144fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4145fcf3ce44SJohn Forte 		}
4146291a2b48SSukumar Swaminathan 
4147fcf3ce44SJohn Forte 		bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
4148fcf3ce44SJohn Forte 		emlxs_disp_aif_header(hba, &AifHdr);
4149fcf3ce44SJohn Forte 
4150fcf3ce44SJohn Forte 		ImageLength = AifHdr.RoSize + AifHdr.RwSize;
4151fcf3ce44SJohn Forte 
4152fcf3ce44SJohn Forte 		if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
4153fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4154291a2b48SSukumar Swaminathan 			    "Image length incorrect: 0x%x != 0x%x", Size,
4155291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR) + ImageLength +
4156291a2b48SSukumar Swaminathan 			    sizeof (uint32_t));
4157fcf3ce44SJohn Forte 
4158fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4159fcf3ce44SJohn Forte 		}
4160291a2b48SSukumar Swaminathan 
4161fcf3ce44SJohn Forte 		if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
4162fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4163fcf3ce44SJohn Forte 			    "Invalid imageBase value %x != 0x20000",
4164fcf3ce44SJohn Forte 			    AifHdr.ImageBase);
4165fcf3ce44SJohn Forte 
4166fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4167fcf3ce44SJohn Forte 		}
4168291a2b48SSukumar Swaminathan 
4169291a2b48SSukumar Swaminathan 		CkSumEnd =
4170291a2b48SSukumar Swaminathan 		    (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
4171fcf3ce44SJohn Forte 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4172fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4173fcf3ce44SJohn Forte 			    "Invalid checksum found.");
4174fcf3ce44SJohn Forte 
4175fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4176fcf3ce44SJohn Forte 		}
4177291a2b48SSukumar Swaminathan 
4178fcf3ce44SJohn Forte 		image->dwc.offset = 0;
4179fcf3ce44SJohn Forte 		image->dwc.version = AifHdr.AVersion;
4180fcf3ce44SJohn Forte 		image->dwc.revcomp = 0;
4181fcf3ce44SJohn Forte 
4182fcf3ce44SJohn Forte 		id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4183fcf3ce44SJohn Forte 		type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
4184fcf3ce44SJohn Forte 
4185fcf3ce44SJohn Forte 		/* Validate the file version */
4186291a2b48SSukumar Swaminathan 		if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
4187291a2b48SSukumar Swaminathan 		    "DWC file"))) {
4188fcf3ce44SJohn Forte 			return (rval);
4189fcf3ce44SJohn Forte 		}
4190291a2b48SSukumar Swaminathan 
4191fcf3ce44SJohn Forte 		NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
4192fcf3ce44SJohn Forte 		while (Size > NextImage) {
4193fcf3ce44SJohn Forte 			bcopy(&Buffer[NextImage], &ImageHdr,
4194fcf3ce44SJohn Forte 			    sizeof (IMAGE_HDR));
4195fcf3ce44SJohn Forte 			emlxs_dump_image_header(hba, &ImageHdr);
4196fcf3ce44SJohn Forte 
4197fcf3ce44SJohn Forte 			/* Validate block size */
4198fcf3ce44SJohn Forte 			if (ImageHdr.BlockSize == 0xffffffff) {
4199fcf3ce44SJohn Forte 				break;
4200fcf3ce44SJohn Forte 			}
4201291a2b48SSukumar Swaminathan 
4202fcf3ce44SJohn Forte 			type = emlxs_type_check(ImageHdr.Id.Type);
4203fcf3ce44SJohn Forte 
4204fcf3ce44SJohn Forte 			/* Calculate the program offset */
4205fcf3ce44SJohn Forte 			image->prog[type].offset = NextImage;
4206fcf3ce44SJohn Forte 
4207fcf3ce44SJohn Forte 			/* Acquire the versions */
4208291a2b48SSukumar Swaminathan 			image->prog[type].version =
4209291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Type << 24) |
4210291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Id << 16) |
4211291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Ver << 8) |
4212fcf3ce44SJohn Forte 			    ImageHdr.Id.Rev;
4213fcf3ce44SJohn Forte 
4214fcf3ce44SJohn Forte 			image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4215fcf3ce44SJohn Forte 
4216fcf3ce44SJohn Forte 			/* Validate the file version */
4217fcf3ce44SJohn Forte 			if ((rval = emlxs_validate_version(hba,
4218291a2b48SSukumar Swaminathan 			    &image->prog[type], ImageHdr.Id.Id, type,
4219291a2b48SSukumar Swaminathan 			    "DWC prog"))) {
4220fcf3ce44SJohn Forte 				return (rval);
4221fcf3ce44SJohn Forte 			}
4222291a2b48SSukumar Swaminathan 
4223fcf3ce44SJohn Forte 			NextImage += ImageHdr.BlockSize;
4224fcf3ce44SJohn Forte 		}
42256a573d82SSukumar Swaminathan 
42266a573d82SSukumar Swaminathan 	} else { /* PRG File */
42276a573d82SSukumar Swaminathan 
4228fcf3ce44SJohn Forte 		/* Precheck image size */
4229fcf3ce44SJohn Forte 		if (Size < sizeof (IMAGE_HDR)) {
4230fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4231291a2b48SSukumar Swaminathan 			    "Invalid image header length: 0x%x < 0x%x", Size,
4232291a2b48SSukumar Swaminathan 			    sizeof (IMAGE_HDR));
4233fcf3ce44SJohn Forte 
4234fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4235fcf3ce44SJohn Forte 		}
4236291a2b48SSukumar Swaminathan 
4237fcf3ce44SJohn Forte 		bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
4238fcf3ce44SJohn Forte 		emlxs_dump_image_header(hba, &ImageHdr);
4239fcf3ce44SJohn Forte 
4240fcf3ce44SJohn Forte 		/* Validate block size */
4241fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff) {
4242fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4243fcf3ce44SJohn Forte 			    "Invalid block size.");
4244fcf3ce44SJohn Forte 
4245fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4246fcf3ce44SJohn Forte 		}
4247291a2b48SSukumar Swaminathan 
4248fcf3ce44SJohn Forte 		ImageLength = ImageHdr.BlockSize;
4249fcf3ce44SJohn Forte 
4250fcf3ce44SJohn Forte 		/* Validate image length */
4251fcf3ce44SJohn Forte 		if (Size != ImageLength) {
4252fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4253291a2b48SSukumar Swaminathan 			    "Invalid image length: 0x%x != 0x%x", Size,
4254291a2b48SSukumar Swaminathan 			    ImageLength);
4255fcf3ce44SJohn Forte 
4256fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4257fcf3ce44SJohn Forte 		}
4258291a2b48SSukumar Swaminathan 
4259fcf3ce44SJohn Forte 		/* Validate Checksum */
4260291a2b48SSukumar Swaminathan 		CkSumEnd =
4261291a2b48SSukumar Swaminathan 		    (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
4262291a2b48SSukumar Swaminathan 		    1;
4263fcf3ce44SJohn Forte 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4264fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4265fcf3ce44SJohn Forte 			    "Invalid checksum found.");
4266fcf3ce44SJohn Forte 
4267fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4268fcf3ce44SJohn Forte 		}
4269291a2b48SSukumar Swaminathan 
4270fcf3ce44SJohn Forte 		type = emlxs_type_check(ImageHdr.Id.Type);
4271fcf3ce44SJohn Forte 
4272fcf3ce44SJohn Forte 		/* Calculate the program offset */
4273fcf3ce44SJohn Forte 		image->prog[type].offset = 0;
4274fcf3ce44SJohn Forte 
4275fcf3ce44SJohn Forte 		/* Acquire the versions */
4276291a2b48SSukumar Swaminathan 		image->prog[type].version =
42776a573d82SSukumar Swaminathan 		    (ImageHdr.Id.Type << 24) |
42786a573d82SSukumar Swaminathan 		    (ImageHdr.Id.Id << 16) |
42796a573d82SSukumar Swaminathan 		    (ImageHdr.Id.Ver << 8) |
42806a573d82SSukumar Swaminathan 		    ImageHdr.Id.Rev;
4281fcf3ce44SJohn Forte 
4282fcf3ce44SJohn Forte 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4283fcf3ce44SJohn Forte 
4284fcf3ce44SJohn Forte 		/* Validate the file version */
4285fcf3ce44SJohn Forte 		if ((rval = emlxs_validate_version(hba, &image->prog[type],
4286fcf3ce44SJohn Forte 		    ImageHdr.Id.Id, type, "DWC file"))) {
4287fcf3ce44SJohn Forte 			return (rval);
4288fcf3ce44SJohn Forte 		}
4289fcf3ce44SJohn Forte 	}
4290fcf3ce44SJohn Forte 
4291fcf3ce44SJohn Forte 	/*
4292291a2b48SSukumar Swaminathan 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
42936a573d82SSukumar Swaminathan 	 * image file is < version 3.8
4294fcf3ce44SJohn Forte 	 */
4295fcf3ce44SJohn Forte 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
42966a573d82SSukumar Swaminathan 		ver = (image->prog[SLI2_OVERLAY].version &
42976a573d82SSukumar Swaminathan 		    0x0000ff00) >> 8;
4298fcf3ce44SJohn Forte 
42996a573d82SSukumar Swaminathan 		if (ver >= 0x38) {
43006a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
43016a573d82SSukumar Swaminathan 			    &emlxs_image_incompat_msg,
43026a573d82SSukumar Swaminathan 			    "ASIC Check: Image requires DragonFly "
43036a573d82SSukumar Swaminathan 			    "V2 ASIC");
4304fcf3ce44SJohn Forte 
43056a573d82SSukumar Swaminathan 			return (EMLXS_IMAGE_INCOMPATIBLE);
4306fcf3ce44SJohn Forte 		}
4307fcf3ce44SJohn Forte 	}
4308291a2b48SSukumar Swaminathan 
4309fcf3ce44SJohn Forte 	return (0);
4310fcf3ce44SJohn Forte 
431182527734SSukumar Swaminathan } /* emlxs_validate_image() */
4312fcf3ce44SJohn Forte 
4313fcf3ce44SJohn Forte 
4314fcf3ce44SJohn Forte static uint32_t
4315fcf3ce44SJohn Forte emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
4316fcf3ce44SJohn Forte {
4317fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4318fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
4319fcf3ce44SJohn Forte 	MAILBOX *mb;
4320fcf3ce44SJohn Forte 	uint32_t next_address;
4321fcf3ce44SJohn Forte 	uint32_t rval = 0;
4322fcf3ce44SJohn Forte 
4323fcf3ce44SJohn Forte 	if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
4324fcf3ce44SJohn Forte 		return (1);
4325fcf3ce44SJohn Forte 	}
4326291a2b48SSukumar Swaminathan 
4327291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4328291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
4329fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4330fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
4331fcf3ce44SJohn Forte 
4332fcf3ce44SJohn Forte 		return (1);
4333fcf3ce44SJohn Forte 	}
4334291a2b48SSukumar Swaminathan 
4335fcf3ce44SJohn Forte 	bzero(mbox, sizeof (MAILBOXQ));
4336fcf3ce44SJohn Forte 
4337fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
4338fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_LOAD_EXP_ROM;
4339fcf3ce44SJohn Forte 	mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
4340fcf3ce44SJohn Forte 	mb->un.varLdExpRom.progress = 0;
4341fcf3ce44SJohn Forte 	mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
434282527734SSukumar Swaminathan 	mbox->mbox_cmpl = NULL;
4343fcf3ce44SJohn Forte 
434482527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4345fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4346fcf3ce44SJohn Forte 		    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4347fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
4348fcf3ce44SJohn Forte 
4349fcf3ce44SJohn Forte 		rval = 1;
4350fcf3ce44SJohn Forte 
4351fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
4352fcf3ce44SJohn Forte 	}
4353291a2b48SSukumar Swaminathan 
4354fcf3ce44SJohn Forte 	if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
4355fcf3ce44SJohn Forte 		(void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4356fcf3ce44SJohn Forte 
4357fcf3ce44SJohn Forte 		rval = 1;
4358fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
4359fcf3ce44SJohn Forte 	}
4360291a2b48SSukumar Swaminathan 
4361fcf3ce44SJohn Forte 	if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
4362fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4363fcf3ce44SJohn Forte 		    "Invalid exp ROM progress. progress=%x",
4364fcf3ce44SJohn Forte 		    mb->un.varLdExpRom.progress);
4365fcf3ce44SJohn Forte 
4366fcf3ce44SJohn Forte 		rval = 1;
4367fcf3ce44SJohn Forte 
4368fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
4369fcf3ce44SJohn Forte 	}
4370291a2b48SSukumar Swaminathan 
4371fcf3ce44SJohn Forte 	/*
4372fcf3ce44SJohn Forte 	 * continue Erase
4373fcf3ce44SJohn Forte 	 */
4374fcf3ce44SJohn Forte 	while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
4375fcf3ce44SJohn Forte 
4376fcf3ce44SJohn Forte 		next_address = mb->un.varLdExpRom.dl_to_adr;
4377fcf3ce44SJohn Forte 
4378fcf3ce44SJohn Forte 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
4379fcf3ce44SJohn Forte 
4380fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
4381fcf3ce44SJohn Forte 		mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
4382fcf3ce44SJohn Forte 		mb->un.varLdExpRom.dl_to_adr = next_address;
4383fcf3ce44SJohn Forte 		mb->un.varLdExpRom.progress = 0;
4384fcf3ce44SJohn Forte 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
438582527734SSukumar Swaminathan 		mbox->mbox_cmpl = NULL;
4386fcf3ce44SJohn Forte 
438782527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4388291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
4389fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4390fcf3ce44SJohn Forte 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4391fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
4392fcf3ce44SJohn Forte 
4393fcf3ce44SJohn Forte 			rval = 1;
4394fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
4395fcf3ce44SJohn Forte 		}
4396291a2b48SSukumar Swaminathan 
4397fcf3ce44SJohn Forte 	}
4398fcf3ce44SJohn Forte 
4399fcf3ce44SJohn Forte 	while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
4400fcf3ce44SJohn Forte 		next_address = mb->un.varLdExpRom.dl_to_adr;
4401fcf3ce44SJohn Forte 
4402fcf3ce44SJohn Forte 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
4403fcf3ce44SJohn Forte 
4404fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
4405fcf3ce44SJohn Forte 		mb->un.varLdExpRom.step = EROM_CMD_COPY;
4406fcf3ce44SJohn Forte 		mb->un.varLdExpRom.dl_to_adr = next_address;
4407fcf3ce44SJohn Forte 		mb->un.varLdExpRom.progress = 0;
4408fcf3ce44SJohn Forte 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
440982527734SSukumar Swaminathan 		mbox->mbox_cmpl = NULL;
4410fcf3ce44SJohn Forte 
441182527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4412291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
4413fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4414fcf3ce44SJohn Forte 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4415fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
4416fcf3ce44SJohn Forte 
4417fcf3ce44SJohn Forte 			rval = 1;
4418fcf3ce44SJohn Forte 
4419fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
4420fcf3ce44SJohn Forte 		}
4421fcf3ce44SJohn Forte 	}
4422fcf3ce44SJohn Forte 
4423fcf3ce44SJohn Forte 	rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4424fcf3ce44SJohn Forte 
4425fcf3ce44SJohn Forte SLI_DOWNLOAD_EXIT:
4426fcf3ce44SJohn Forte 
4427fcf3ce44SJohn Forte 	if (mbox) {
4428fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
4429fcf3ce44SJohn Forte 	}
4430291a2b48SSukumar Swaminathan 
4431fcf3ce44SJohn Forte 	return (rval);
4432fcf3ce44SJohn Forte 
443382527734SSukumar Swaminathan } /* emlxs_update_exp_rom() */
4434fcf3ce44SJohn Forte 
4435fcf3ce44SJohn Forte 
4436fcf3ce44SJohn Forte /*
4437fcf3ce44SJohn Forte  *
4438fcf3ce44SJohn Forte  * FUNCTION NAME: emlxs_start_abs_download_2mb
4439fcf3ce44SJohn Forte  *
4440fcf3ce44SJohn Forte  * DESCRIPTION: Perform absolute download for 2 MB flash.  A incoming
4441fcf3ce44SJohn Forte  *              buffer may consist of more than 1 file.  This function
4442fcf3ce44SJohn Forte  *              will parse the buffer to find all the files.
4443fcf3ce44SJohn Forte  *
4444fcf3ce44SJohn Forte  *
4445fcf3ce44SJohn Forte  * PARAMETERS:
4446fcf3ce44SJohn Forte  *
4447fcf3ce44SJohn Forte  *
4448fcf3ce44SJohn Forte  * RETURNS:
4449fcf3ce44SJohn Forte  *
4450fcf3ce44SJohn Forte  */
4451fcf3ce44SJohn Forte /* ARGSUSED */
4452fcf3ce44SJohn Forte static uint32_t
4453fcf3ce44SJohn Forte emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
4454fcf3ce44SJohn Forte     uint32_t offline, emlxs_fw_image_t *fw_image)
4455fcf3ce44SJohn Forte {
4456fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4457fcf3ce44SJohn Forte 	uint32_t rval = 0;
4458fcf3ce44SJohn Forte 
4459fcf3ce44SJohn Forte 	/* If nothing to download then quit now */
44606a573d82SSukumar Swaminathan 	if (!fw_image->awc.version &&
44616a573d82SSukumar Swaminathan 	    !fw_image->dwc.version &&
44626a573d82SSukumar Swaminathan 	    !fw_image->bwc.version) {
44636a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
44646a573d82SSukumar Swaminathan 		    "Nothing new to update.  Exiting.");
4465fcf3ce44SJohn Forte 		return (0);
4466fcf3ce44SJohn Forte 	}
4467291a2b48SSukumar Swaminathan 
4468fcf3ce44SJohn Forte 	/*
4469fcf3ce44SJohn Forte 	 * Everything checks out, now to just do it
4470fcf3ce44SJohn Forte 	 */
4471fcf3ce44SJohn Forte 	if (offline) {
4472fcf3ce44SJohn Forte 		if (emlxs_offline(hba) != FC_SUCCESS) {
4473fcf3ce44SJohn Forte 			return (EMLXS_OFFLINE_FAILED);
4474fcf3ce44SJohn Forte 		}
4475291a2b48SSukumar Swaminathan 
447682527734SSukumar Swaminathan 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
4477fcf3ce44SJohn Forte 			return (EMLXS_OFFLINE_FAILED);
4478fcf3ce44SJohn Forte 		}
4479fcf3ce44SJohn Forte 	}
4480291a2b48SSukumar Swaminathan 
44816a573d82SSukumar Swaminathan 	if (fw_image->awc.version) {
4482291a2b48SSukumar Swaminathan 		rval = emlxs_proc_abs_2mb(hba,
44836a573d82SSukumar Swaminathan 		    (buffer + fw_image->awc.offset),
44846a573d82SSukumar Swaminathan 		    FILE_TYPE_AWC, 0);
4485fcf3ce44SJohn Forte 
4486fcf3ce44SJohn Forte 		if (rval) {
4487fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_2MB_EXIT;
4488fcf3ce44SJohn Forte 		}
4489fcf3ce44SJohn Forte 	}
4490291a2b48SSukumar Swaminathan 
44916a573d82SSukumar Swaminathan 	if (fw_image->bwc.version) {
4492291a2b48SSukumar Swaminathan 		rval = emlxs_proc_abs_2mb(hba,
44936a573d82SSukumar Swaminathan 		    (buffer + fw_image->bwc.offset),
44946a573d82SSukumar Swaminathan 		    FILE_TYPE_BWC,
44956a573d82SSukumar Swaminathan 		    (fw_image->dwc.version)? ALLext:BWCext);
4496fcf3ce44SJohn Forte 
4497fcf3ce44SJohn Forte 		if (rval) {
4498fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_2MB_EXIT;
4499fcf3ce44SJohn Forte 		}
4500fcf3ce44SJohn Forte 	}
4501291a2b48SSukumar Swaminathan 
45026a573d82SSukumar Swaminathan 	if (fw_image->dwc.version) {
45036a573d82SSukumar Swaminathan 		rval = emlxs_proc_rel_2mb(hba, buffer, fw_image);
4504fcf3ce44SJohn Forte 
45056a573d82SSukumar Swaminathan 		if (rval) {
45066a573d82SSukumar Swaminathan 			goto SLI_DOWNLOAD_2MB_EXIT;
45076a573d82SSukumar Swaminathan 		}
4508fcf3ce44SJohn Forte 	}
4509291a2b48SSukumar Swaminathan 
4510fcf3ce44SJohn Forte SLI_DOWNLOAD_2MB_EXIT:
4511fcf3ce44SJohn Forte 
4512fcf3ce44SJohn Forte 	if (offline) {
4513fcf3ce44SJohn Forte 		(void) emlxs_online(hba);
4514fcf3ce44SJohn Forte 	}
4515291a2b48SSukumar Swaminathan 
4516fcf3ce44SJohn Forte 	return (rval);
4517fcf3ce44SJohn Forte 
451882527734SSukumar Swaminathan } /* emlxs_start_abs_download_2mb() */
4519fcf3ce44SJohn Forte 
4520fcf3ce44SJohn Forte 
4521fcf3ce44SJohn Forte /*
4522fcf3ce44SJohn Forte  *
4523fcf3ce44SJohn Forte  * FUNCTION NAME: emlxs_proc_abs_2mb
4524fcf3ce44SJohn Forte  *
4525fcf3ce44SJohn Forte  * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
4526fcf3ce44SJohn Forte  *              the port and download the file with sliIssueMbCommand()
4527fcf3ce44SJohn Forte  *
4528fcf3ce44SJohn Forte  *
4529fcf3ce44SJohn Forte  * PARAMETERS:
4530fcf3ce44SJohn Forte  *
4531fcf3ce44SJohn Forte  *
4532fcf3ce44SJohn Forte  * RETURNS:
4533fcf3ce44SJohn Forte  *
4534fcf3ce44SJohn Forte  */
4535fcf3ce44SJohn Forte static uint32_t
45366a573d82SSukumar Swaminathan emlxs_proc_abs_2mb(emlxs_hba_t *hba, caddr_t EntireBuffer,
45376a573d82SSukumar Swaminathan     uint32_t FileType, uint32_t extType)
4538fcf3ce44SJohn Forte {
4539fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
45406a573d82SSukumar Swaminathan 	PAIF_HDR AifHdr;
4541fcf3ce44SJohn Forte 	caddr_t Buffer = NULL;
4542fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
4543fcf3ce44SJohn Forte 	uint32_t *Src;
4544fcf3ce44SJohn Forte 	uint32_t *Dst;
4545fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
4546fcf3ce44SJohn Forte 	MAILBOX *mb;
45476a573d82SSukumar Swaminathan 	uint32_t DlByteCount;
4548fcf3ce44SJohn Forte 	uint32_t rval = 0;
4549fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
45506a573d82SSukumar Swaminathan 	uint32_t DlToAddr;
4551fcf3ce44SJohn Forte 	uint32_t DlCount;
4552fcf3ce44SJohn Forte 	WAKE_UP_PARMS AbsWakeUpParms;
4553fcf3ce44SJohn Forte 	uint32_t i;
4554fcf3ce44SJohn Forte 	uint32_t NextAddr;
4555fcf3ce44SJohn Forte 	uint32_t EraseByteCount;
4556fcf3ce44SJohn Forte 	uint32_t AreaId;
4557fcf3ce44SJohn Forte 	uint32_t RspProgress = 0;
45586a573d82SSukumar Swaminathan 	uint32_t ParamsChg;
45596a573d82SSukumar Swaminathan 
45606a573d82SSukumar Swaminathan 	AifHdr = (PAIF_HDR)EntireBuffer;
45616a573d82SSukumar Swaminathan 	DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
45626a573d82SSukumar Swaminathan 	DlToAddr = AifHdr->ImageBase;
4563fcf3ce44SJohn Forte 
4564291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
4565291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
4566fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4567fcf3ce44SJohn Forte 		    "%x: Unable to allocate data buffer.", FileType);
4568fcf3ce44SJohn Forte 
4569fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_FAILED);
4570fcf3ce44SJohn Forte 	}
4571291a2b48SSukumar Swaminathan 
4572291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4573291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
4574fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4575fcf3ce44SJohn Forte 		    "%x: Unable to allocate mailbox buffer.", FileType);
4576fcf3ce44SJohn Forte 
4577fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4578fcf3ce44SJohn Forte 
4579fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_FAILED);
4580fcf3ce44SJohn Forte 	}
4581291a2b48SSukumar Swaminathan 
4582fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
4583fcf3ce44SJohn Forte 
4584fcf3ce44SJohn Forte 	Buffer = EntireBuffer + sizeof (AIF_HDR);
4585fcf3ce44SJohn Forte 
4586fcf3ce44SJohn Forte 	switch (FileType) {
4587fcf3ce44SJohn Forte 	case FILE_TYPE_AWC:
45886a573d82SSukumar Swaminathan 		ParamsChg = 0;
4589fcf3ce44SJohn Forte 		break;
4590fcf3ce44SJohn Forte 
4591fcf3ce44SJohn Forte 	case FILE_TYPE_BWC:
45926a573d82SSukumar Swaminathan 		rval = emlxs_build_parms_2mb_bwc(hba,
4593291a2b48SSukumar Swaminathan 		    AifHdr, extType, &AbsWakeUpParms);
4594fcf3ce44SJohn Forte 
45956a573d82SSukumar Swaminathan 		if (rval == FALSE) {
4596fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4597fcf3ce44SJohn Forte 			    "BWC build parms failed.");
4598fcf3ce44SJohn Forte 
4599fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
4600fcf3ce44SJohn Forte 
4601fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
4602fcf3ce44SJohn Forte 		}
46036a573d82SSukumar Swaminathan 		ParamsChg = 1;
4604fcf3ce44SJohn Forte 		break;
4605fcf3ce44SJohn Forte 
4606fcf3ce44SJohn Forte 	default:
4607fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4608fcf3ce44SJohn Forte 		    "Invalid file type: %x", FileType);
4609fcf3ce44SJohn Forte 
4610fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_BAD;
4611fcf3ce44SJohn Forte 
4612fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
4613fcf3ce44SJohn Forte 	}
4614fcf3ce44SJohn Forte 
4615fcf3ce44SJohn Forte 	EraseByteCount = AifHdr->Area_Size;
4616fcf3ce44SJohn Forte 	AreaId = AifHdr->Area_ID;
4617fcf3ce44SJohn Forte 
461882527734SSukumar Swaminathan 	emlxs_format_load_area_cmd(mbox,
4619291a2b48SSukumar Swaminathan 	    DlToAddr,
4620291a2b48SSukumar Swaminathan 	    EraseByteCount,
4621291a2b48SSukumar Swaminathan 	    ERASE_FLASH,
4622fcf3ce44SJohn Forte 	    0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
4623fcf3ce44SJohn Forte 
462482527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4625fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4626fcf3ce44SJohn Forte 		    "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
4627fcf3ce44SJohn Forte 		    FileType, mb->mbxCommand, mb->mbxStatus);
4628fcf3ce44SJohn Forte 
4629fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_FAILED;
4630fcf3ce44SJohn Forte 
4631fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
4632fcf3ce44SJohn Forte 	}
4633291a2b48SSukumar Swaminathan 
4634fcf3ce44SJohn Forte 	while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
4635fcf3ce44SJohn Forte 		NextAddr = mb->un.varLdArea.dl_to_adr;
4636fcf3ce44SJohn Forte 
463782527734SSukumar Swaminathan 		emlxs_format_load_area_cmd(mbox,
4638291a2b48SSukumar Swaminathan 		    NextAddr,
4639291a2b48SSukumar Swaminathan 		    EraseByteCount,
4640291a2b48SSukumar Swaminathan 		    ERASE_FLASH,
4641291a2b48SSukumar Swaminathan 		    0,
4642291a2b48SSukumar Swaminathan 		    DL_FROM_SLIM_OFFSET,
4643291a2b48SSukumar Swaminathan 		    AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
4644fcf3ce44SJohn Forte 
464582527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4646291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
4647fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4648291a2b48SSukumar Swaminathan 			    "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
4649291a2b48SSukumar Swaminathan 			    "status=%x", FileType, mb->mbxCommand,
4650291a2b48SSukumar Swaminathan 			    mb->mbxStatus);
4651fcf3ce44SJohn Forte 
4652fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
4653fcf3ce44SJohn Forte 
4654fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
4655fcf3ce44SJohn Forte 		}
4656fcf3ce44SJohn Forte 	}
4657fcf3ce44SJohn Forte 
4658fcf3ce44SJohn Forte 	while (DlByteCount) {
4659fcf3ce44SJohn Forte 		if (DlByteCount >= SegSize)
4660fcf3ce44SJohn Forte 			DlCount = SegSize;
4661fcf3ce44SJohn Forte 		else
4662fcf3ce44SJohn Forte 			DlCount = DlByteCount;
4663fcf3ce44SJohn Forte 
4664fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
4665fcf3ce44SJohn Forte 
4666fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
4667fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
4668fcf3ce44SJohn Forte 
4669fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
4670fcf3ce44SJohn Forte 			*Dst = *Src;
4671fcf3ce44SJohn Forte 			Dst++;
4672fcf3ce44SJohn Forte 			Src++;
4673fcf3ce44SJohn Forte 		}
4674fcf3ce44SJohn Forte 
4675fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
467682527734SSukumar Swaminathan 		    (volatile uint32_t *)((volatile char *)
467782527734SSukumar Swaminathan 		    hba->sli.sli3.slim_addr + sizeof (MAILBOX)),
467882527734SSukumar Swaminathan 		    (DlCount / sizeof (uint32_t)));
4679fcf3ce44SJohn Forte 
4680fcf3ce44SJohn Forte 		if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
468182527734SSukumar Swaminathan 			emlxs_format_load_area_cmd(mbox,
4682291a2b48SSukumar Swaminathan 			    DlToAddr,
4683291a2b48SSukumar Swaminathan 			    DlCount,
4684291a2b48SSukumar Swaminathan 			    PROGRAM_FLASH,
4685291a2b48SSukumar Swaminathan 			    (DlByteCount) ? 0 : 1,
4686291a2b48SSukumar Swaminathan 			    DL_FROM_SLIM_OFFSET,
4687291a2b48SSukumar Swaminathan 			    AreaId,
4688291a2b48SSukumar Swaminathan 			    MBX_LOAD_AREA,
4689fcf3ce44SJohn Forte 			    (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
4690fcf3ce44SJohn Forte 
469182527734SSukumar Swaminathan 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4692fcf3ce44SJohn Forte 			    MBX_SUCCESS) {
4693fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
4694fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
4695291a2b48SSukumar Swaminathan 				    "%x: Could not program 2MB Flash: Mailbox "
4696291a2b48SSukumar Swaminathan 				    "cmd=%x status=%x", FileType,
4697291a2b48SSukumar Swaminathan 				    mb->mbxCommand, mb->mbxStatus);
4698fcf3ce44SJohn Forte 
4699fcf3ce44SJohn Forte 				rval = EMLXS_IMAGE_FAILED;
4700fcf3ce44SJohn Forte 
4701fcf3ce44SJohn Forte 				goto EXIT_ABS_DOWNLOAD;
4702fcf3ce44SJohn Forte 			}
4703fcf3ce44SJohn Forte 		}
4704291a2b48SSukumar Swaminathan 
4705fcf3ce44SJohn Forte 		RspProgress = mb->un.varLdArea.progress;
4706fcf3ce44SJohn Forte 
4707fcf3ce44SJohn Forte 		Buffer += DlCount;
4708fcf3ce44SJohn Forte 		DlToAddr += DlCount;
4709fcf3ce44SJohn Forte 	}
4710fcf3ce44SJohn Forte 
47114baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
471282527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
47134baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
47144baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
47154baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
47164baa2c25SSukumar Swaminathan 
47174baa2c25SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
47184baa2c25SSukumar Swaminathan 
47194baa2c25SSukumar Swaminathan 		goto EXIT_ABS_DOWNLOAD;
47204baa2c25SSukumar Swaminathan 	}
47214baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
47224baa2c25SSukumar Swaminathan 
4723fcf3ce44SJohn Forte 	if (RspProgress != RSP_DOWNLOAD_DONE) {
4724fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4725291a2b48SSukumar Swaminathan 		    "%x: Failed download response received. %x", FileType,
4726291a2b48SSukumar Swaminathan 		    RspProgress);
4727fcf3ce44SJohn Forte 
4728fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_FAILED;
4729fcf3ce44SJohn Forte 
4730fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
4731fcf3ce44SJohn Forte 	}
4732291a2b48SSukumar Swaminathan 
4733fcf3ce44SJohn Forte 	if (ParamsChg) {
4734fcf3ce44SJohn Forte 		if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
4735fcf3ce44SJohn Forte 		    &AbsWakeUpParms)) {
4736fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4737fcf3ce44SJohn Forte 			    "%x: Unable to update parms.", FileType);
4738fcf3ce44SJohn Forte 
4739fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
4740fcf3ce44SJohn Forte 		}
4741fcf3ce44SJohn Forte 	}
4742291a2b48SSukumar Swaminathan 
4743fcf3ce44SJohn Forte EXIT_ABS_DOWNLOAD:
4744fcf3ce44SJohn Forte 
4745fcf3ce44SJohn Forte 	if (DataBuffer) {
4746fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4747fcf3ce44SJohn Forte 	}
4748291a2b48SSukumar Swaminathan 
4749fcf3ce44SJohn Forte 	if (mbox) {
4750fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
4751fcf3ce44SJohn Forte 	}
4752291a2b48SSukumar Swaminathan 
4753fcf3ce44SJohn Forte 	return (rval);
4754fcf3ce44SJohn Forte 
475582527734SSukumar Swaminathan } /* emlxs_proc_abs_2mb() */
4756fcf3ce44SJohn Forte 
4757fcf3ce44SJohn Forte 
4758fcf3ce44SJohn Forte static void
475982527734SSukumar Swaminathan emlxs_format_load_area_cmd(MAILBOXQ * mbq,
4760291a2b48SSukumar Swaminathan     uint32_t Base,
4761291a2b48SSukumar Swaminathan     uint32_t DlByteCount,
4762291a2b48SSukumar Swaminathan     uint32_t Function,
4763291a2b48SSukumar Swaminathan     uint32_t Complete,
4764291a2b48SSukumar Swaminathan     uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
4765fcf3ce44SJohn Forte {
476682527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
476782527734SSukumar Swaminathan 
4768fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
4769fcf3ce44SJohn Forte 
4770fcf3ce44SJohn Forte 	mb->mbxCommand = MbxCmd;
4771fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
4772fcf3ce44SJohn Forte 	mb->un.varLdArea.update_flash = 1;
4773fcf3ce44SJohn Forte 	mb->un.varLdArea.erase_or_prog = Function;
4774fcf3ce44SJohn Forte 	mb->un.varLdArea.dl_to_adr = Base;
4775fcf3ce44SJohn Forte 	mb->un.varLdArea.dl_len = DlByteCount;
4776fcf3ce44SJohn Forte 	mb->un.varLdArea.load_cmplt = Complete;
4777fcf3ce44SJohn Forte 	mb->un.varLdArea.method = DL_FROM_SLIM;
4778fcf3ce44SJohn Forte 	mb->un.varLdArea.area_id = AreaId;
4779fcf3ce44SJohn Forte 	mb->un.varLdArea.step = StepCmd;
4780fcf3ce44SJohn Forte 	mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
478182527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
4782fcf3ce44SJohn Forte 
478382527734SSukumar Swaminathan } /* emlxs_format_load_area_cmd() */
4784fcf3ce44SJohn Forte 
4785fcf3ce44SJohn Forte 
4786291a2b48SSukumar Swaminathan /* ARGSUSED */
4787fcf3ce44SJohn Forte static uint32_t
4788291a2b48SSukumar Swaminathan emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
4789291a2b48SSukumar Swaminathan     PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
4790fcf3ce44SJohn Forte {
4791fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4792fcf3ce44SJohn Forte 	uint32_t pId[2];
4793fcf3ce44SJohn Forte 	uint32_t returnStat;
4794fcf3ce44SJohn Forte 
4795fcf3ce44SJohn Forte 	/* Read wakeup paramters */
4796fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
47976a573d82SSukumar Swaminathan 	    (uint32_t)CFG_DATA_NO_REGION) {
4798fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4799fcf3ce44SJohn Forte 		    "Unable to get BWC parameters.");
4800fcf3ce44SJohn Forte 		return (FALSE);
4801fcf3ce44SJohn Forte 	}
4802291a2b48SSukumar Swaminathan 
4803fcf3ce44SJohn Forte 	pId[0] = AifHdr->AVersion;
4804fcf3ce44SJohn Forte 	pId[1] = 0;
4805fcf3ce44SJohn Forte 
4806fcf3ce44SJohn Forte 	if (extType == BWCext) {
4807fcf3ce44SJohn Forte 		AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4808fcf3ce44SJohn Forte 		AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4809fcf3ce44SJohn Forte 		AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4810fcf3ce44SJohn Forte 		AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4811291a2b48SSukumar Swaminathan 	}
4812291a2b48SSukumar Swaminathan 
4813291a2b48SSukumar Swaminathan 	else if (extType == ALLext) {
4814fcf3ce44SJohn Forte 		if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
4815fcf3ce44SJohn Forte 			/* case of EROM inactive */
4816fcf3ce44SJohn Forte 			AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4817fcf3ce44SJohn Forte 			AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4818fcf3ce44SJohn Forte 		} else {
4819fcf3ce44SJohn Forte 			/* case of EROM active */
4820fcf3ce44SJohn Forte 			if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
4821fcf3ce44SJohn Forte 				/* same ID */
4822fcf3ce44SJohn Forte 				AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4823fcf3ce44SJohn Forte 				AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4824fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4825fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4826fcf3ce44SJohn Forte 			} else {
4827fcf3ce44SJohn Forte 				/* different ID */
4828fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4829fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4830fcf3ce44SJohn Forte 
4831291a2b48SSukumar Swaminathan 				returnStat =
4832291a2b48SSukumar Swaminathan 				    emlxs_update_exp_rom(hba, AbsWakeUpParms);
4833fcf3ce44SJohn Forte 
4834fcf3ce44SJohn Forte 				if (returnStat) {
4835fcf3ce44SJohn Forte 					AbsWakeUpParms->u0.boot_bios_wd[0] =
4836fcf3ce44SJohn Forte 					    pId[0];
4837fcf3ce44SJohn Forte 					AbsWakeUpParms->u0.boot_bios_wd[1] =
4838fcf3ce44SJohn Forte 					    pId[1];
4839fcf3ce44SJohn Forte 				}
4840fcf3ce44SJohn Forte 			}
4841fcf3ce44SJohn Forte 		}
4842fcf3ce44SJohn Forte 	}
4843291a2b48SSukumar Swaminathan 
4844fcf3ce44SJohn Forte 	return (TRUE);
4845fcf3ce44SJohn Forte 
484682527734SSukumar Swaminathan } /* emlxs_build_parms_2mb_bwc() */
4847fcf3ce44SJohn Forte 
4848fcf3ce44SJohn Forte 
4849fcf3ce44SJohn Forte extern uint32_t
4850fcf3ce44SJohn Forte emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
4851fcf3ce44SJohn Forte     uint32_t *MaxIbusSize)
4852fcf3ce44SJohn Forte {
4853fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4854fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
4855fcf3ce44SJohn Forte 	MAILBOX *mb;
4856fcf3ce44SJohn Forte 	uint32_t *Uptr;
4857fcf3ce44SJohn Forte 	uint32_t rval = 0;
4858fcf3ce44SJohn Forte 
48596a573d82SSukumar Swaminathan 	if (MaxRbusSize) {
48606a573d82SSukumar Swaminathan 		*MaxRbusSize = 0;
48616a573d82SSukumar Swaminathan 	}
48626a573d82SSukumar Swaminathan 
48636a573d82SSukumar Swaminathan 	if (MaxIbusSize) {
48646a573d82SSukumar Swaminathan 		*MaxIbusSize = 0;
48656a573d82SSukumar Swaminathan 	}
48666a573d82SSukumar Swaminathan 
4867291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4868291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
4869fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4870fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
4871fcf3ce44SJohn Forte 
4872fcf3ce44SJohn Forte 		return (1);
4873fcf3ce44SJohn Forte 	}
4874291a2b48SSukumar Swaminathan 
4875fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
4876fcf3ce44SJohn Forte 
487782527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
4878fcf3ce44SJohn Forte 
487982527734SSukumar Swaminathan 	if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) !=
4880291a2b48SSukumar Swaminathan 	    MBX_SUCCESS) {
4881fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4882fcf3ce44SJohn Forte 		    "Unable to get SRAM size: Mailbox cmd=%x status=%x",
4883fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
4884fcf3ce44SJohn Forte 
4885fcf3ce44SJohn Forte 		rval = 1;
4886fcf3ce44SJohn Forte 
4887fcf3ce44SJohn Forte 		goto Exit_Function;
4888fcf3ce44SJohn Forte 	}
4889291a2b48SSukumar Swaminathan 
489082527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
489182527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
489282527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
489382527734SSukumar Swaminathan 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
489482527734SSukumar Swaminathan 	} else {
489582527734SSukumar Swaminathan 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
489682527734SSukumar Swaminathan 	}
4897fcf3ce44SJohn Forte 
48986a573d82SSukumar Swaminathan 	if (MaxRbusSize) {
48996a573d82SSukumar Swaminathan 		*MaxRbusSize = Uptr[0];
49006a573d82SSukumar Swaminathan 	}
49016a573d82SSukumar Swaminathan 
49026a573d82SSukumar Swaminathan 	if (MaxIbusSize) {
49036a573d82SSukumar Swaminathan 		*MaxIbusSize = Uptr[1];
49046a573d82SSukumar Swaminathan 	}
4905fcf3ce44SJohn Forte 
4906fcf3ce44SJohn Forte Exit_Function:
4907fcf3ce44SJohn Forte 
4908fcf3ce44SJohn Forte 	if (mbox) {
4909fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
4910fcf3ce44SJohn Forte 	}
4911291a2b48SSukumar Swaminathan 
4912b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
4913b3660a96SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4914b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
4915b3660a96SSukumar Swaminathan 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
4916b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
4917b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
4918b3660a96SSukumar Swaminathan 			    "emlxs_get_max_sram: hdl=%p",
4919b3660a96SSukumar Swaminathan 			    hba->sli.sli4.dump_region.dma_handle);
4920b3660a96SSukumar Swaminathan 			rval = 1;
4921b3660a96SSukumar Swaminathan 		}
4922b3660a96SSukumar Swaminathan 	}
4923b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4924b3660a96SSukumar Swaminathan 
4925fcf3ce44SJohn Forte 	return (rval);
4926fcf3ce44SJohn Forte 
492782527734SSukumar Swaminathan } /* emlxs_get_max_sram() */
4928fcf3ce44SJohn Forte 
4929fcf3ce44SJohn Forte 
4930fcf3ce44SJohn Forte static uint32_t
4931fcf3ce44SJohn Forte emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
4932fcf3ce44SJohn Forte {
4933fcf3ce44SJohn Forte 	uint8_t *ptr;
4934fcf3ce44SJohn Forte 	uint8_t ver;
4935fcf3ce44SJohn Forte 
4936fcf3ce44SJohn Forte 	ver = version & 0xff;
4937fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_FF;
4938fcf3ce44SJohn Forte 
4939fcf3ce44SJohn Forte 	while (*ptr) {
4940fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4941fcf3ce44SJohn Forte 			return (1);
4942fcf3ce44SJohn Forte 		}
4943fcf3ce44SJohn Forte 	}
4944fcf3ce44SJohn Forte 
4945fcf3ce44SJohn Forte 	return (0);
4946fcf3ce44SJohn Forte 
494782527734SSukumar Swaminathan } /* emlxs_kern_check() */
4948fcf3ce44SJohn Forte 
4949fcf3ce44SJohn Forte static uint32_t
4950fcf3ce44SJohn Forte emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
4951fcf3ce44SJohn Forte {
4952fcf3ce44SJohn Forte 	uint8_t *ptr;
4953fcf3ce44SJohn Forte 	uint8_t ver;
4954fcf3ce44SJohn Forte 
4955fcf3ce44SJohn Forte 	ver = version & 0xff;
4956fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_2;
4957fcf3ce44SJohn Forte 
4958fcf3ce44SJohn Forte 	while (*ptr) {
4959fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4960fcf3ce44SJohn Forte 			return (1);
4961fcf3ce44SJohn Forte 		}
4962fcf3ce44SJohn Forte 	}
4963fcf3ce44SJohn Forte 
4964fcf3ce44SJohn Forte 	return (0);
4965fcf3ce44SJohn Forte 
496682527734SSukumar Swaminathan } /* emlxs_stub_check() */
4967fcf3ce44SJohn Forte 
4968fcf3ce44SJohn Forte static uint32_t
4969fcf3ce44SJohn Forte emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
4970fcf3ce44SJohn Forte {
4971fcf3ce44SJohn Forte 	uint8_t *ptr;
4972fcf3ce44SJohn Forte 	uint8_t ver;
4973fcf3ce44SJohn Forte 
4974fcf3ce44SJohn Forte 	ver = version & 0xff;
4975fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_3;
4976fcf3ce44SJohn Forte 
4977fcf3ce44SJohn Forte 	while (*ptr) {
4978fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4979fcf3ce44SJohn Forte 			return (1);
4980fcf3ce44SJohn Forte 		}
4981fcf3ce44SJohn Forte 	}
4982fcf3ce44SJohn Forte 
4983fcf3ce44SJohn Forte 	return (0);
4984fcf3ce44SJohn Forte 
498582527734SSukumar Swaminathan } /* emlxs_bios_check() */
4986fcf3ce44SJohn Forte 
4987fcf3ce44SJohn Forte static uint32_t
4988fcf3ce44SJohn Forte emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
4989fcf3ce44SJohn Forte {
4990fcf3ce44SJohn Forte 	uint8_t *ptr;
4991fcf3ce44SJohn Forte 	uint8_t ver;
4992fcf3ce44SJohn Forte 
4993fcf3ce44SJohn Forte 	ver = version & 0xff;
4994fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_6;
4995fcf3ce44SJohn Forte 
4996fcf3ce44SJohn Forte 	while (*ptr) {
4997fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4998fcf3ce44SJohn Forte 			return (1);
4999fcf3ce44SJohn Forte 		}
5000fcf3ce44SJohn Forte 	}
5001fcf3ce44SJohn Forte 
5002fcf3ce44SJohn Forte 	return (0);
5003fcf3ce44SJohn Forte 
500482527734SSukumar Swaminathan } /* emlxs_sli1_check() */
5005fcf3ce44SJohn Forte 
5006fcf3ce44SJohn Forte static uint32_t
5007fcf3ce44SJohn Forte emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version)
5008fcf3ce44SJohn Forte {
5009fcf3ce44SJohn Forte 	uint8_t *ptr;
5010fcf3ce44SJohn Forte 	uint8_t ver;
5011fcf3ce44SJohn Forte 
5012fcf3ce44SJohn Forte 	ver = version & 0xff;
5013fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_7;
5014fcf3ce44SJohn Forte 
5015fcf3ce44SJohn Forte 	while (*ptr) {
5016fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5017fcf3ce44SJohn Forte 			return (1);
5018fcf3ce44SJohn Forte 		}
5019fcf3ce44SJohn Forte 	}
5020fcf3ce44SJohn Forte 
5021fcf3ce44SJohn Forte 	return (0);
5022fcf3ce44SJohn Forte 
502382527734SSukumar Swaminathan } /* emlxs_sli2_check() */
5024fcf3ce44SJohn Forte 
5025fcf3ce44SJohn Forte static uint32_t
5026fcf3ce44SJohn Forte emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
5027fcf3ce44SJohn Forte {
5028fcf3ce44SJohn Forte 	uint8_t *ptr;
5029fcf3ce44SJohn Forte 	uint8_t ver;
5030fcf3ce44SJohn Forte 
5031fcf3ce44SJohn Forte 	ver = version & 0xff;
5032fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_B;
5033fcf3ce44SJohn Forte 
5034fcf3ce44SJohn Forte 	while (*ptr) {
5035fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5036fcf3ce44SJohn Forte 			return (1);
5037fcf3ce44SJohn Forte 		}
5038fcf3ce44SJohn Forte 	}
5039fcf3ce44SJohn Forte 
5040fcf3ce44SJohn Forte 	return (0);
5041fcf3ce44SJohn Forte 
504282527734SSukumar Swaminathan } /* emlxs_sli3_check() */
5043fcf3ce44SJohn Forte 
5044fcf3ce44SJohn Forte 
5045fcf3ce44SJohn Forte static uint32_t
5046fcf3ce44SJohn Forte emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
5047fcf3ce44SJohn Forte {
5048fcf3ce44SJohn Forte 	uint8_t *ptr;
5049fcf3ce44SJohn Forte 	uint8_t ver;
5050fcf3ce44SJohn Forte 
5051fcf3ce44SJohn Forte 	ver = version & 0xff;
5052fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_E;
5053fcf3ce44SJohn Forte 
5054fcf3ce44SJohn Forte 	while (*ptr) {
5055fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5056fcf3ce44SJohn Forte 			return (1);
5057fcf3ce44SJohn Forte 		}
5058fcf3ce44SJohn Forte 	}
5059fcf3ce44SJohn Forte 
5060fcf3ce44SJohn Forte 	return (0);
5061fcf3ce44SJohn Forte 
506282527734SSukumar Swaminathan } /* emlxs_sli4_check() */
5063fcf3ce44SJohn Forte 
5064fcf3ce44SJohn Forte 
5065fcf3ce44SJohn Forte static uint32_t
5066fcf3ce44SJohn Forte emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
5067fcf3ce44SJohn Forte {
5068fcf3ce44SJohn Forte 	uint8_t *ptr;
5069fcf3ce44SJohn Forte 	uint8_t ver;
5070fcf3ce44SJohn Forte 
5071fcf3ce44SJohn Forte 	ver = version & 0xff;
5072fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_A;
5073fcf3ce44SJohn Forte 
5074fcf3ce44SJohn Forte 	while (*ptr) {
5075fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5076fcf3ce44SJohn Forte 			return (1);
5077fcf3ce44SJohn Forte 		}
5078fcf3ce44SJohn Forte 	}
5079fcf3ce44SJohn Forte 
5080fcf3ce44SJohn Forte 	return (0);
5081fcf3ce44SJohn Forte 
508282527734SSukumar Swaminathan } /* emlxs_sbus_fcode_check() */
5083fcf3ce44SJohn Forte 
5084*a9800bebSGarrett D'Amore 
5085fcf3ce44SJohn Forte static uint32_t
5086fcf3ce44SJohn Forte emlxs_type_check(uint32_t type)
5087fcf3ce44SJohn Forte {
5088fcf3ce44SJohn Forte 	if (type == 0xff) {
5089fcf3ce44SJohn Forte 		return (KERNEL_CODE);
5090fcf3ce44SJohn Forte 	}
5091291a2b48SSukumar Swaminathan 
5092fcf3ce44SJohn Forte 	if (type >= MAX_PROG_TYPES) {
5093fcf3ce44SJohn Forte 		return (RESERVED_D);
5094fcf3ce44SJohn Forte 	}
5095291a2b48SSukumar Swaminathan 
5096fcf3ce44SJohn Forte 	return (type);
5097fcf3ce44SJohn Forte 
509882527734SSukumar Swaminathan } /* emlxs_type_check() */
5099fcf3ce44SJohn Forte 
5100fcf3ce44SJohn Forte 
5101291a2b48SSukumar Swaminathan extern int32_t
5102fcf3ce44SJohn Forte emlxs_boot_code_disable(emlxs_hba_t *hba)
5103fcf3ce44SJohn Forte {
5104fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5105fcf3ce44SJohn Forte 	PROG_ID Id;
5106fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
5107fcf3ce44SJohn Forte 
5108fcf3ce44SJohn Forte 	vpd = &VPD;
5109fcf3ce44SJohn Forte 
5110*a9800bebSGarrett D'Amore 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5111*a9800bebSGarrett D'Amore 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5112fe199829SSukumar Swaminathan 		return (EMLXS_OP_NOT_SUP);
5113fe199829SSukumar Swaminathan 	}
5114fe199829SSukumar Swaminathan 
5115fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5116fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5117fcf3ce44SJohn Forte 		    "emlxs_boot_code_disable: Unable to read wake up parms.");
5118fcf3ce44SJohn Forte 
5119291a2b48SSukumar Swaminathan 		return (FC_FAILURE);
5120fcf3ce44SJohn Forte 	}
5121291a2b48SSukumar Swaminathan 
5122fcf3ce44SJohn Forte 	/* Check if boot code is already disabled */
5123fcf3ce44SJohn Forte 	if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
5124fcf3ce44SJohn Forte 		return (FC_SUCCESS);
5125fcf3ce44SJohn Forte 	}
5126291a2b48SSukumar Swaminathan 
5127fcf3ce44SJohn Forte 	/* Make sure EROM entry has copy of boot bios entry */
5128fcf3ce44SJohn Forte 	if (!(hba->model_info.chip &
5129fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
5130fcf3ce44SJohn Forte 	    (hba->wakeup_parms.u0.boot_bios_wd[0] !=
5131fcf3ce44SJohn Forte 	    hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
5132fcf3ce44SJohn Forte 	    (hba->wakeup_parms.u0.boot_bios_wd[1] !=
5133fcf3ce44SJohn Forte 	    hba->wakeup_parms.u1.EROM_prog_wd[1])) {
5134fcf3ce44SJohn Forte 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
5135fcf3ce44SJohn Forte 		    &hba->wakeup_parms.u0.boot_bios_id, 1);
5136fcf3ce44SJohn Forte 	}
5137291a2b48SSukumar Swaminathan 
5138fcf3ce44SJohn Forte 	/* Update the bios id with a zero id */
5139fcf3ce44SJohn Forte 	/* Don't load the EROM this time */
5140fcf3ce44SJohn Forte 	bzero(&Id, sizeof (PROG_ID));
5141fcf3ce44SJohn Forte 	(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0);
5142fcf3ce44SJohn Forte 
5143fcf3ce44SJohn Forte 	/* Now read the parms again to verify */
5144fcf3ce44SJohn Forte 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5145fcf3ce44SJohn Forte 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5146fcf3ce44SJohn Forte 	    vpd->boot_version);
5147fcf3ce44SJohn Forte 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5148fcf3ce44SJohn Forte 
5149fcf3ce44SJohn Forte 	/* Return the result */
5150291a2b48SSukumar Swaminathan 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
5151291a2b48SSukumar Swaminathan 	    FC_SUCCESS : FC_FAILURE);
5152fcf3ce44SJohn Forte 
515382527734SSukumar Swaminathan } /* emlxs_boot_code_disable() */
5154fcf3ce44SJohn Forte 
5155fcf3ce44SJohn Forte 
5156291a2b48SSukumar Swaminathan extern int32_t
5157fcf3ce44SJohn Forte emlxs_boot_code_enable(emlxs_hba_t *hba)
5158fcf3ce44SJohn Forte {
5159fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5160fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
5161fcf3ce44SJohn Forte 	PROG_ID load_list[MAX_LOAD_ENTRY];
5162fcf3ce44SJohn Forte 	uint32_t i;
51636a573d82SSukumar Swaminathan 	uint32_t count;
5164fcf3ce44SJohn Forte 
5165fcf3ce44SJohn Forte 	vpd = &VPD;
5166fcf3ce44SJohn Forte 
5167*a9800bebSGarrett D'Amore 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5168*a9800bebSGarrett D'Amore 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5169fe199829SSukumar Swaminathan 		return (FC_SUCCESS);
5170fe199829SSukumar Swaminathan 	}
5171fe199829SSukumar Swaminathan 
5172fcf3ce44SJohn Forte 	/* Read the wakeup parms */
5173fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5174fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5175fcf3ce44SJohn Forte 		    "emlxs_boot_code_enable: Unable to read wake up parms.");
5176fcf3ce44SJohn Forte 
5177291a2b48SSukumar Swaminathan 		return (FC_FAILURE);
5178fcf3ce44SJohn Forte 	}
5179291a2b48SSukumar Swaminathan 
5180fcf3ce44SJohn Forte 	/* Check if boot code is already enabled */
5181fcf3ce44SJohn Forte 	if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
5182fcf3ce44SJohn Forte 		return (FC_SUCCESS);
5183fcf3ce44SJohn Forte 	}
5184291a2b48SSukumar Swaminathan 
5185fcf3ce44SJohn Forte 	if (!(hba->model_info.chip &
5186fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
5187fcf3ce44SJohn Forte 		if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) {
5188fcf3ce44SJohn Forte 			return (EMLXS_NO_BOOT_CODE);
5189fcf3ce44SJohn Forte 		}
5190291a2b48SSukumar Swaminathan 
5191fcf3ce44SJohn Forte 		/* Update the parms with the boot image id */
5192fcf3ce44SJohn Forte 		/* Don't load the EROM this time */
5193fcf3ce44SJohn Forte 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
5194fcf3ce44SJohn Forte 		    &hba->wakeup_parms.u1.EROM_prog_id, 0);
5195fcf3ce44SJohn Forte 	} else {	/* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
5196291a2b48SSukumar Swaminathan 
51976a573d82SSukumar Swaminathan 		count = emlxs_get_load_list(hba, load_list);
51986a573d82SSukumar Swaminathan 
51996a573d82SSukumar Swaminathan 		if (!count) {
5200291a2b48SSukumar Swaminathan 			return (FC_FAILURE);
5201fcf3ce44SJohn Forte 		}
5202291a2b48SSukumar Swaminathan 
5203fcf3ce44SJohn Forte 		/* Scan load list for a boot image */
52046a573d82SSukumar Swaminathan 		for (i = 0; i < count; i++) {
5205fcf3ce44SJohn Forte 			if (load_list[i].Type == BOOT_BIOS) {
5206fcf3ce44SJohn Forte 				/* Update the parms with the boot image id */
5207fcf3ce44SJohn Forte 				/* Don't load the EROM this time */
5208fcf3ce44SJohn Forte 				(void) emlxs_update_boot_wakeup_parms(hba,
5209fcf3ce44SJohn Forte 				    &hba->wakeup_parms, &load_list[i], 0);
5210fcf3ce44SJohn Forte 
5211fcf3ce44SJohn Forte 				break;
5212fcf3ce44SJohn Forte 			}
5213fcf3ce44SJohn Forte 		}
5214fcf3ce44SJohn Forte 
52156a573d82SSukumar Swaminathan 		if (i == count) {
5216fcf3ce44SJohn Forte 			return (EMLXS_NO_BOOT_CODE);
5217fcf3ce44SJohn Forte 		}
5218fcf3ce44SJohn Forte 	}
5219fcf3ce44SJohn Forte 
5220fcf3ce44SJohn Forte 	/* Now read the parms again to verify */
5221fcf3ce44SJohn Forte 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5222fcf3ce44SJohn Forte 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5223fcf3ce44SJohn Forte 	    vpd->boot_version);
5224291a2b48SSukumar Swaminathan 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5225fcf3ce44SJohn Forte 
5226fcf3ce44SJohn Forte 	/* return the result */
5227291a2b48SSukumar Swaminathan 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5228291a2b48SSukumar Swaminathan 	    FC_SUCCESS : FC_FAILURE);
5229fcf3ce44SJohn Forte 
523082527734SSukumar Swaminathan } /* emlxs_boot_code_enable() */
5231fcf3ce44SJohn Forte 
5232fcf3ce44SJohn Forte 
5233fcf3ce44SJohn Forte 
5234291a2b48SSukumar Swaminathan extern int32_t
5235fcf3ce44SJohn Forte emlxs_boot_code_state(emlxs_hba_t *hba)
5236fcf3ce44SJohn Forte {
5237fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5238fcf3ce44SJohn Forte 
5239*a9800bebSGarrett D'Amore 	if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5240*a9800bebSGarrett D'Amore 	    (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5241fe199829SSukumar Swaminathan 		return (FC_SUCCESS);
5242fe199829SSukumar Swaminathan 	}
5243fe199829SSukumar Swaminathan 
5244fcf3ce44SJohn Forte 	/* Read the wakeup parms */
5245fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
5246fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5247fcf3ce44SJohn Forte 		    "emlxs_boot_code_state: Unable to read wake up parms.");
5248fcf3ce44SJohn Forte 
5249291a2b48SSukumar Swaminathan 		return (FC_FAILURE);
5250fcf3ce44SJohn Forte 	}
5251291a2b48SSukumar Swaminathan 
5252fcf3ce44SJohn Forte 	/* return the result */
5253291a2b48SSukumar Swaminathan 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5254291a2b48SSukumar Swaminathan 	    FC_SUCCESS : FC_FAILURE);
5255fcf3ce44SJohn Forte 
525682527734SSukumar Swaminathan } /* emlxs_boot_code_state() */
5257