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