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 /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24*82527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27*82527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C);
32fcf3ce44SJohn Forte 
33fcf3ce44SJohn Forte #define	MAX_BOOTID	10
34fcf3ce44SJohn Forte 
35291a2b48SSukumar Swaminathan static uint32_t	emlxs_erase_fcode_flash(emlxs_hba_t *hba);
36*82527734SSukumar Swaminathan 
37291a2b48SSukumar Swaminathan static uint32_t	emlxs_write_fcode_flash(emlxs_hba_t *hba,
38291a2b48SSukumar Swaminathan 			PIMAGE_HDR ImageHdr, caddr_t Buffer);
39fcf3ce44SJohn Forte 
40291a2b48SSukumar Swaminathan static int32_t	emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
41291a2b48SSukumar Swaminathan 			uint32_t BufferSize, PAIF_HDR AifHeader,
42291a2b48SSukumar Swaminathan 			int32_t DwcFile);
43291a2b48SSukumar Swaminathan static uint32_t	emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
44291a2b48SSukumar Swaminathan 			uint32_t Size, emlxs_fw_image_t *fw_image);
45*82527734SSukumar Swaminathan static void	emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq,
46*82527734SSukumar Swaminathan 			uint32_t Type, uint32_t RegionId, uint32_t WordCnt,
47*82527734SSukumar Swaminathan 			uint32_t BaseAddr);
48291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
49291a2b48SSukumar Swaminathan 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
50291a2b48SSukumar Swaminathan 			uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize,
51291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile);
52291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
53291a2b48SSukumar Swaminathan 			uint32_t len, uint32_t offline,
54291a2b48SSukumar Swaminathan 			emlxs_fw_image_t *fw_image);
55291a2b48SSukumar Swaminathan static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba, PAIF_HDR AifHdr,
56291a2b48SSukumar Swaminathan 			caddr_t EntireBuffer, uint32_t FileType,
57291a2b48SSukumar Swaminathan 			uint32_t BWCflag, uint32_t extType);
58*82527734SSukumar Swaminathan static void	emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base,
59291a2b48SSukumar Swaminathan 			uint32_t DlByteCount, uint32_t Function,
60291a2b48SSukumar Swaminathan 			uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
61291a2b48SSukumar Swaminathan 			uint8_t MbxCmd, uint32_t StepCmd);
62291a2b48SSukumar Swaminathan static uint32_t	emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
63291a2b48SSukumar Swaminathan 			uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
64291a2b48SSukumar Swaminathan static uint32_t	emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba, caddr_t Buffer,
65291a2b48SSukumar Swaminathan 			uint32_t BufferSize, PAIF_HDR AifHeader,
66291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS AbsWakeUpParms, uint32_t BWCflag,
67291a2b48SSukumar Swaminathan 			uint32_t extType, uint32_t *numBootImage);
68291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_exp_rom(emlxs_hba_t *hba,
69291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
70291a2b48SSukumar Swaminathan extern uint32_t	emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
71291a2b48SSukumar Swaminathan 			uint32_t *MaxIbusSize);
72*82527734SSukumar Swaminathan static void	emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base,
73291a2b48SSukumar Swaminathan 			uint32_t DlByteCount, uint32_t Function,
74291a2b48SSukumar Swaminathan 			uint32_t Complete, uint32_t BdeAddress,
75291a2b48SSukumar Swaminathan 			uint32_t BdeSize, PROG_ID *ProgId);
76*82527734SSukumar Swaminathan static void	emlxs_format_update_parms(MAILBOXQ *mbq,
77291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
78*82527734SSukumar Swaminathan static void	emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
79291a2b48SSukumar Swaminathan 			uint32_t region_id, uint32_t size);
80291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_wakeup_parms(emlxs_hba_t *hba,
81291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS AbsWakeUpParms,
82291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
83291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba,
84291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id,
85291a2b48SSukumar Swaminathan 			uint32_t proc_erom);
86291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba,
87291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
88291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba,
89291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
90291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba,
91291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
92291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba,
93291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
94291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba,
95291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
96291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
97291a2b48SSukumar Swaminathan 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
98291a2b48SSukumar Swaminathan 			uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize);
99291a2b48SSukumar Swaminathan static uint32_t	emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
100fcf3ce44SJohn Forte 
101291a2b48SSukumar Swaminathan static uint32_t	emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
102*82527734SSukumar Swaminathan 
103291a2b48SSukumar Swaminathan static void	emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr);
104*82527734SSukumar Swaminathan 
105291a2b48SSukumar Swaminathan static void	emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
106*82527734SSukumar Swaminathan 
107291a2b48SSukumar Swaminathan static uint32_t	emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize);
108fcf3ce44SJohn Forte 
109291a2b48SSukumar Swaminathan static uint32_t	emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer,
110291a2b48SSukumar Swaminathan 			uint32_t BufferSize, PAIF_HDR AifHeader);
111291a2b48SSukumar Swaminathan static uint32_t	emlxs_type_check(uint32_t type);
112*82527734SSukumar Swaminathan 
113291a2b48SSukumar Swaminathan static uint32_t	emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
114*82527734SSukumar Swaminathan 
115291a2b48SSukumar Swaminathan static uint32_t	emlxs_stub_check(emlxs_hba_t *hba, uint32_t version);
116*82527734SSukumar Swaminathan 
117291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version);
118*82527734SSukumar Swaminathan 
119291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version);
120*82527734SSukumar Swaminathan 
121291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version);
122*82527734SSukumar Swaminathan 
123291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version);
124*82527734SSukumar Swaminathan 
125291a2b48SSukumar Swaminathan static uint32_t	emlxs_bios_check(emlxs_hba_t *hba, uint32_t version);
126*82527734SSukumar Swaminathan 
127291a2b48SSukumar Swaminathan static uint32_t	emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version);
128*82527734SSukumar Swaminathan 
129291a2b48SSukumar Swaminathan static uint32_t	emlxs_validate_version(emlxs_hba_t *hba,
130291a2b48SSukumar Swaminathan 			emlxs_fw_file_t *file, uint32_t id, uint32_t type,
131291a2b48SSukumar Swaminathan 			char *file_type);
132*82527734SSukumar Swaminathan static uint32_t emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer,
133*82527734SSukumar Swaminathan 			uint32_t len, emlxs_be_fw_image_t *fw_image);
134*82527734SSukumar Swaminathan static int32_t emlxs_sli4_verify_image(emlxs_hba_t *hba, caddr_t buffer,
135*82527734SSukumar Swaminathan 			emlxs_be_fw_file_t *file,
136*82527734SSukumar Swaminathan 			MAILBOXQ *mbq, MATCHMAP *mp);
137*82527734SSukumar Swaminathan static int32_t emlxs_sli4_verify_crc(emlxs_hba_t *hba,
138*82527734SSukumar Swaminathan 			emlxs_be_fw_file_t *file,
139*82527734SSukumar Swaminathan 			MAILBOXQ *mbq, MATCHMAP *mp);
140*82527734SSukumar Swaminathan static int32_t emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
141*82527734SSukumar Swaminathan 			emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp);
142*82527734SSukumar Swaminathan static int32_t emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer,
143*82527734SSukumar Swaminathan 			uint32_t len, uint32_t offline);
144fcf3ce44SJohn Forte 
145291a2b48SSukumar Swaminathan /* ************************************************************************* */
146fcf3ce44SJohn Forte 
147fcf3ce44SJohn Forte extern int32_t
148fcf3ce44SJohn Forte emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
149fcf3ce44SJohn Forte     uint32_t offline)
150fcf3ce44SJohn Forte {
151fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
152fcf3ce44SJohn Forte 	uint32_t *Uptr;
153fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
154fcf3ce44SJohn Forte 	AIF_HDR AifHdr;
155fcf3ce44SJohn Forte 	uint32_t ImageType;
156fcf3ce44SJohn Forte 	WAKE_UP_PARMS WakeUpParms;
157fcf3ce44SJohn Forte 	WAKE_UP_PARMS AbsWakeUpParms;
158fcf3ce44SJohn Forte 	uint32_t MaxRbusSramSize;
159fcf3ce44SJohn Forte 	uint32_t MaxIbusSramSize;
160fcf3ce44SJohn Forte 	int32_t AbsChangeParams = 0;
161fcf3ce44SJohn Forte 	int32_t DwcFile = FALSE;
162fcf3ce44SJohn Forte 	uint32_t rval = 0;
163fcf3ce44SJohn Forte 	emlxs_fw_image_t fw_image;
164fcf3ce44SJohn Forte 	uint32_t i;
165fcf3ce44SJohn Forte 
166*82527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
167fcf3ce44SJohn Forte 	caddr_t local_buffer;
168fcf3ce44SJohn Forte 	uint32_t *bptr1;
169fcf3ce44SJohn Forte 	uint32_t *bptr2;
170*82527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
171*82527734SSukumar Swaminathan 
172*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
173*82527734SSukumar Swaminathan 		rval = emlxs_sli4_fw_download(hba, buffer, len, offline);
174*82527734SSukumar Swaminathan 		return (rval);
175*82527734SSukumar Swaminathan 	}
176fcf3ce44SJohn Forte 
177fcf3ce44SJohn Forte 	if (buffer == NULL || len == 0) {
178fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
179fcf3ce44SJohn Forte 	}
180*82527734SSukumar Swaminathan 
181*82527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
182fcf3ce44SJohn Forte 	/* We need to swap the image buffer before we start */
183fcf3ce44SJohn Forte 
184fcf3ce44SJohn Forte 	/*
185fcf3ce44SJohn Forte 	 * Use KM_SLEEP to allocate a temporary buffer
186fcf3ce44SJohn Forte 	 */
187fcf3ce44SJohn Forte 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
188fcf3ce44SJohn Forte 
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++) {
193*82527734SSukumar Swaminathan 		*bptr1 = LE_SWAP32(*bptr2);
194fcf3ce44SJohn Forte 		bptr1++;
195fcf3ce44SJohn Forte 		bptr2++;
196fcf3ce44SJohn Forte 	}
197fcf3ce44SJohn Forte 
198fcf3ce44SJohn Forte 	/* Replace the original buffer */
199fcf3ce44SJohn Forte 	buffer = local_buffer;
200*82527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
201fcf3ce44SJohn Forte 
202fcf3ce44SJohn Forte 	bzero(&fw_image, sizeof (emlxs_fw_image_t));
203fcf3ce44SJohn Forte 	for (i = 0; i < MAX_PROG_TYPES; i++) {
204fcf3ce44SJohn Forte 		(void) strcpy(fw_image.prog[i].label, "none");
205fcf3ce44SJohn Forte 	}
206fcf3ce44SJohn Forte 
207fcf3ce44SJohn Forte 	/* Validate image */
208fcf3ce44SJohn Forte 	if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) {
209fcf3ce44SJohn Forte 		goto done;
210fcf3ce44SJohn Forte 	}
211291a2b48SSukumar Swaminathan 
212fcf3ce44SJohn Forte 	/* Get image type */
213fcf3ce44SJohn Forte 	Uptr = (uint32_t *)buffer;
214fcf3ce44SJohn Forte 	ImageType = *Uptr;
215fcf3ce44SJohn Forte 
216fcf3ce44SJohn Forte 	/*
217291a2b48SSukumar Swaminathan 	 * Pegasus and beyond FW download is done differently
218291a2b48SSukumar Swaminathan 	 * for absolute download.
219fcf3ce44SJohn Forte 	 */
220fcf3ce44SJohn Forte 
221fcf3ce44SJohn Forte 	/* Check for absolute image */
222fcf3ce44SJohn Forte 	if ((ImageType == NOP_IMAGE_TYPE) &&
223fcf3ce44SJohn Forte 	    !(hba->model_info.chip &
224fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
225fcf3ce44SJohn Forte 		/*
226fcf3ce44SJohn Forte 		 * Because 2Mb flash download file format is different from
227fcf3ce44SJohn Forte 		 * 512k, it needs to be handled differently
228fcf3ce44SJohn Forte 		 */
229fcf3ce44SJohn Forte 		if (rval = emlxs_start_abs_download_2mb(hba, buffer, len,
230fcf3ce44SJohn Forte 		    offline, &fw_image)) {
231fcf3ce44SJohn Forte 			goto done;
232fcf3ce44SJohn Forte 		}
233291a2b48SSukumar Swaminathan 
234fcf3ce44SJohn Forte 		/* Offline already handled */
235fcf3ce44SJohn Forte 		offline = 0;
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
238fcf3ce44SJohn Forte 	}
239291a2b48SSukumar Swaminathan 
240fcf3ce44SJohn Forte 	/* Pre-pegasus adapters only */
241fcf3ce44SJohn Forte 
242fcf3ce44SJohn Forte 	/* Check for absolute image */
243fcf3ce44SJohn Forte 	else if (ImageType == NOP_IMAGE_TYPE) {
244fcf3ce44SJohn Forte 		bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
245fcf3ce44SJohn Forte 		bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
246fcf3ce44SJohn Forte 
247fcf3ce44SJohn Forte 		if (AifHdr.ImageBase && (AifHdr.ImageBase == 0x20000)) {
248fcf3ce44SJohn Forte 			DwcFile = TRUE;
249fcf3ce44SJohn Forte 		}
250291a2b48SSukumar Swaminathan 
251291a2b48SSukumar Swaminathan 		AbsChangeParams = emlxs_build_parms(buffer,
252291a2b48SSukumar Swaminathan 		    &AbsWakeUpParms, len, &AifHdr, DwcFile);
253fcf3ce44SJohn Forte 	} else {	/* (ImageType != NOP_IMAGE_TYPE) Relative image */
254291a2b48SSukumar Swaminathan 
255fcf3ce44SJohn Forte 		bzero((void *)&AifHdr, sizeof (AIF_HDR));
256fcf3ce44SJohn Forte 		bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
257fcf3ce44SJohn Forte 	}
258fcf3ce44SJohn Forte 
259fcf3ce44SJohn Forte 	/*
260fcf3ce44SJohn Forte 	 * Everything checks out, now to just do it
261fcf3ce44SJohn Forte 	 */
262fcf3ce44SJohn Forte 
263fcf3ce44SJohn Forte 	if (offline) {
264fcf3ce44SJohn Forte 		if (emlxs_offline(hba) != FC_SUCCESS) {
265fcf3ce44SJohn Forte 			offline = 0;
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
268fcf3ce44SJohn Forte 			    "Unable to take adapter offline.");
269fcf3ce44SJohn Forte 
270fcf3ce44SJohn Forte 			rval = EMLXS_OFFLINE_FAILED;
271fcf3ce44SJohn Forte 
272fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
273fcf3ce44SJohn Forte 		}
274291a2b48SSukumar Swaminathan 
275*82527734SSukumar Swaminathan 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
276fcf3ce44SJohn Forte 			offline = 0;
277fcf3ce44SJohn Forte 
278fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
279fcf3ce44SJohn Forte 			    "Unable to restart adapter.");
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte 			rval = EMLXS_OFFLINE_FAILED;
282fcf3ce44SJohn Forte 
283fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
284fcf3ce44SJohn Forte 		}
285fcf3ce44SJohn Forte 	}
286291a2b48SSukumar Swaminathan 
287fcf3ce44SJohn Forte 	if (ImageHdr.Id.Type == SBUS_FCODE) {
288fcf3ce44SJohn Forte 		/* Erase Flash */
289fcf3ce44SJohn Forte 		if (emlxs_erase_fcode_flash(hba)) {
290fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
291fcf3ce44SJohn Forte 			    "Unable to erase flash.");
292fcf3ce44SJohn Forte 
293fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
294fcf3ce44SJohn Forte 
295fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
296fcf3ce44SJohn Forte 		}
297291a2b48SSukumar Swaminathan 
298fcf3ce44SJohn Forte 		/* Write FCODE */
299fcf3ce44SJohn Forte 		if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) {
300fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
301fcf3ce44SJohn Forte 			    "Unable to write flash.");
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
304fcf3ce44SJohn Forte 
305fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
306fcf3ce44SJohn Forte 		}
307291a2b48SSukumar Swaminathan 
308fcf3ce44SJohn Forte 	} else {	/* !SBUS_FCODE */
309fcf3ce44SJohn Forte 
310291a2b48SSukumar Swaminathan 
311fcf3ce44SJohn Forte 		if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
312fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
313fcf3ce44SJohn Forte 			    "Unable to get parameters.");
314fcf3ce44SJohn Forte 
315fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
316fcf3ce44SJohn Forte 
317fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
318fcf3ce44SJohn Forte 		}
319291a2b48SSukumar Swaminathan 
320fcf3ce44SJohn Forte 		if (emlxs_get_max_sram(hba, &MaxRbusSramSize,
321fcf3ce44SJohn Forte 		    &MaxIbusSramSize)) {
322fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
323fcf3ce44SJohn Forte 			    "Unable to get RAM size.");
324fcf3ce44SJohn Forte 
325fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
326fcf3ce44SJohn Forte 
327fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
328fcf3ce44SJohn Forte 		}
329291a2b48SSukumar Swaminathan 
330fcf3ce44SJohn Forte 		if (ImageType == NOP_IMAGE_TYPE) {
331fcf3ce44SJohn Forte 			if (emlxs_start_abs_download(hba, &AifHdr, buffer,
332fcf3ce44SJohn Forte 			    &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize,
333fcf3ce44SJohn Forte 			    (AbsChangeParams) ? &AbsWakeUpParms : NULL,
334fcf3ce44SJohn Forte 			    DwcFile)) {
335fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
336fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
337fcf3ce44SJohn Forte 				    "Failed to program flash.");
338fcf3ce44SJohn Forte 
339fcf3ce44SJohn Forte 				rval = EMLXS_IMAGE_FAILED;
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 				goto SLI_DOWNLOAD_EXIT;
342fcf3ce44SJohn Forte 			}
343291a2b48SSukumar Swaminathan 
344fcf3ce44SJohn Forte 		} else {
345fcf3ce44SJohn Forte 
346fcf3ce44SJohn Forte 			if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
347fcf3ce44SJohn Forte 			    &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize)) {
348fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
349fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
350fcf3ce44SJohn Forte 				    "Failed to program flash.");
351fcf3ce44SJohn Forte 
352fcf3ce44SJohn Forte 				rval = EMLXS_IMAGE_FAILED;
353fcf3ce44SJohn Forte 
354fcf3ce44SJohn Forte 				goto SLI_DOWNLOAD_EXIT;
355fcf3ce44SJohn Forte 			}
356fcf3ce44SJohn Forte 		}
357fcf3ce44SJohn Forte 
358fcf3ce44SJohn Forte 	}	/* !SBUS_FCODE */
359fcf3ce44SJohn Forte 
360fcf3ce44SJohn Forte 
361fcf3ce44SJohn Forte SLI_DOWNLOAD_EXIT:
362fcf3ce44SJohn Forte 
363fcf3ce44SJohn Forte 	if (offline) {
364fcf3ce44SJohn Forte 		(void) emlxs_online(hba);
365fcf3ce44SJohn Forte 	}
366291a2b48SSukumar Swaminathan 
367fcf3ce44SJohn Forte 	if (rval == 0) {
368fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
369fcf3ce44SJohn Forte 		    "Status good.");
370fcf3ce44SJohn Forte 	}
371291a2b48SSukumar Swaminathan 
372fcf3ce44SJohn Forte done:
373fcf3ce44SJohn Forte 
374*82527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
375fcf3ce44SJohn Forte 	/* Free the local buffer */
376fcf3ce44SJohn Forte 	kmem_free(local_buffer, len);
377*82527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
378*82527734SSukumar Swaminathan 
379*82527734SSukumar Swaminathan 	return (rval);
380*82527734SSukumar Swaminathan 
381*82527734SSukumar Swaminathan } /* emlxs_fw_download */
382*82527734SSukumar Swaminathan 
383*82527734SSukumar Swaminathan 
384*82527734SSukumar Swaminathan static void
385*82527734SSukumar Swaminathan emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size)
386*82527734SSukumar Swaminathan {
387*82527734SSukumar Swaminathan 	while (size--) {
388*82527734SSukumar Swaminathan 		*buffer++ = value;
389*82527734SSukumar Swaminathan 	}
390*82527734SSukumar Swaminathan 
391*82527734SSukumar Swaminathan } /* emlxs_memset () */
392*82527734SSukumar Swaminathan 
393*82527734SSukumar Swaminathan 
394*82527734SSukumar Swaminathan static int32_t
395*82527734SSukumar Swaminathan emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
396*82527734SSukumar Swaminathan     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
397*82527734SSukumar Swaminathan {
398*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
399*82527734SSukumar Swaminathan 	uint8_t *image_ptr;
400*82527734SSukumar Swaminathan 	uint32_t *wptr;
401*82527734SSukumar Swaminathan 	uint8_t *payload;
402*82527734SSukumar Swaminathan 	MAILBOX4 *mb;
403*82527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
404*82527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
405*82527734SSukumar Swaminathan 	uint32_t	image_size;
406*82527734SSukumar Swaminathan 	uint32_t	block_size;
407*82527734SSukumar Swaminathan 	uint32_t	xfer_size;
408*82527734SSukumar Swaminathan 	uint32_t	block_offset;
409*82527734SSukumar Swaminathan 	uint32_t	count;
410*82527734SSukumar Swaminathan 	uint32_t	rval = 0;
411*82527734SSukumar Swaminathan 
412*82527734SSukumar Swaminathan 	if (file->image_size == 0) {
413*82527734SSukumar Swaminathan 		return (0);
414*82527734SSukumar Swaminathan 	}
415*82527734SSukumar Swaminathan 
416*82527734SSukumar Swaminathan 	image_ptr  = (uint8_t *)buffer + file->image_offset;
417*82527734SSukumar Swaminathan 	image_size = file->image_size;
418*82527734SSukumar Swaminathan 	block_size = file->block_size;
419*82527734SSukumar Swaminathan 	block_offset = 0;
420*82527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
421*82527734SSukumar Swaminathan 
422*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
423*82527734SSukumar Swaminathan 	    "%s: Downloading...", file->label);
424*82527734SSukumar Swaminathan 
425*82527734SSukumar Swaminathan 	while (block_size) {
426*82527734SSukumar Swaminathan 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
427*82527734SSukumar Swaminathan 		bzero((void *) mp->virt, mp->size);
428*82527734SSukumar Swaminathan 
429*82527734SSukumar Swaminathan 		xfer_size = min(BE_MAX_XFER_SIZE, block_size);
430*82527734SSukumar Swaminathan 
431*82527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.embedded = 0;
432*82527734SSukumar Swaminathan 		mbq->nonembed = (uint8_t *)mp;
433*82527734SSukumar Swaminathan 		mbq->mbox_cmpl = NULL;
434*82527734SSukumar Swaminathan 
435*82527734SSukumar Swaminathan 		mb->mbxCommand = MBX_SLI_CONFIG;
436*82527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
437*82527734SSukumar Swaminathan 
438*82527734SSukumar Swaminathan 		hdr_req = (mbox_req_hdr_t *)mp->virt;
439*82527734SSukumar Swaminathan 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
440*82527734SSukumar Swaminathan 		hdr_req->opcode = COMMON_OPCODE_WRITE_FLASHROM;
441*82527734SSukumar Swaminathan 		hdr_req->timeout = 0;
442*82527734SSukumar Swaminathan 		hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
443*82527734SSukumar Swaminathan 		    xfer_size;
444*82527734SSukumar Swaminathan 
445*82527734SSukumar Swaminathan 		flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
446*82527734SSukumar Swaminathan 		flashrom->params.opcode = ((block_size == xfer_size)?
447*82527734SSukumar Swaminathan 		    MGMT_FLASHROM_OPCODE_FLASH:MGMT_FLASHROM_OPCODE_SAVE);
448*82527734SSukumar Swaminathan 		flashrom->params.optype = file->type;
449*82527734SSukumar Swaminathan 		flashrom->params.data_buffer_size = xfer_size;
450*82527734SSukumar Swaminathan 		flashrom->params.offset = block_offset;
451*82527734SSukumar Swaminathan 
452*82527734SSukumar Swaminathan 		/* Build data buffer payload */
453*82527734SSukumar Swaminathan 		payload = (uint8_t *)(&flashrom->params.data_buffer);
454*82527734SSukumar Swaminathan 		emlxs_memset(payload, 0xff, xfer_size);
455*82527734SSukumar Swaminathan 
456*82527734SSukumar Swaminathan 		/* Copy remaining image into payload */
457*82527734SSukumar Swaminathan 		if (image_size) {
458*82527734SSukumar Swaminathan 			count = min(image_size, xfer_size);
459*82527734SSukumar Swaminathan 			BE_SWAP32_BCOPY(image_ptr, payload, count);
460*82527734SSukumar Swaminathan 			image_size -= count;
461*82527734SSukumar Swaminathan 			image_ptr  += count;
462*82527734SSukumar Swaminathan 		}
463*82527734SSukumar Swaminathan 
464*82527734SSukumar Swaminathan 		/* Set last two words of last payload with */
465*82527734SSukumar Swaminathan 		/* image size and block crc */
466*82527734SSukumar Swaminathan 		if (flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) {
467*82527734SSukumar Swaminathan 			wptr = (uint32_t *)&payload[(xfer_size - 8)];
468*82527734SSukumar Swaminathan 			wptr[0] = file->image_size;
469*82527734SSukumar Swaminathan 			wptr[1] = file->block_crc;
470*82527734SSukumar Swaminathan 		}
471*82527734SSukumar Swaminathan 
472*82527734SSukumar Swaminathan 		/* Send write request */
473*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
474*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
475*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
476*82527734SSukumar Swaminathan 			    "%s: Unable to download image. status=%x",
477*82527734SSukumar Swaminathan 			    file->label, mb->mbxStatus);
478*82527734SSukumar Swaminathan 			rval = EMLXS_IMAGE_FAILED;
479*82527734SSukumar Swaminathan 			goto done;
480*82527734SSukumar Swaminathan 		}
481*82527734SSukumar Swaminathan 
482*82527734SSukumar Swaminathan 		block_size -= xfer_size;
483*82527734SSukumar Swaminathan 		block_offset += xfer_size;
484*82527734SSukumar Swaminathan 	}
485*82527734SSukumar Swaminathan 
486*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
487*82527734SSukumar Swaminathan 	    "%s: Download complete.", file->label);
488*82527734SSukumar Swaminathan done:
489*82527734SSukumar Swaminathan 
490*82527734SSukumar Swaminathan 	return (rval);
491*82527734SSukumar Swaminathan 
492*82527734SSukumar Swaminathan } /* emlxs_sli4_flash_image() */
493*82527734SSukumar Swaminathan 
494*82527734SSukumar Swaminathan 
495*82527734SSukumar Swaminathan static int32_t
496*82527734SSukumar Swaminathan emlxs_sli4_verify_image(emlxs_hba_t *hba, caddr_t buffer,
497*82527734SSukumar Swaminathan     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
498*82527734SSukumar Swaminathan {
499*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
500*82527734SSukumar Swaminathan 	uint8_t *image_ptr;
501*82527734SSukumar Swaminathan 	uint32_t *wptr;
502*82527734SSukumar Swaminathan 	uint32_t *wptr1;
503*82527734SSukumar Swaminathan 	uint8_t *payload;
504*82527734SSukumar Swaminathan 	MAILBOX4 *mb;
505*82527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
506*82527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
507*82527734SSukumar Swaminathan 	uint32_t	xfer_size;
508*82527734SSukumar Swaminathan 	uint32_t	block_size;
509*82527734SSukumar Swaminathan 	uint32_t	block_offset;
510*82527734SSukumar Swaminathan 	uint32_t	rval = 0;
511*82527734SSukumar Swaminathan 	uint32_t	i;
512*82527734SSukumar Swaminathan 	char signature[BE_SIGNATURE_SIZE];
513*82527734SSukumar Swaminathan 	uint32_t ufi_plus = 0;
514*82527734SSukumar Swaminathan 
515*82527734SSukumar Swaminathan 	/* Check for special deflated format */
516*82527734SSukumar Swaminathan 	(void) sprintf(signature, "%s+", BE_SIGNATURE);
517*82527734SSukumar Swaminathan 	if (strncmp(signature, buffer,
518*82527734SSukumar Swaminathan 	    sizeof (signature)-1) == 0) {
519*82527734SSukumar Swaminathan 		ufi_plus = 1;
520*82527734SSukumar Swaminathan 	}
521*82527734SSukumar Swaminathan 
522*82527734SSukumar Swaminathan 	image_ptr  = (uint8_t *)buffer + file->image_offset;
523*82527734SSukumar Swaminathan 	block_size = (ufi_plus)? file->image_size: file->block_size;
524*82527734SSukumar Swaminathan 	block_offset = 0;
525*82527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
526*82527734SSukumar Swaminathan 
527*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
528*82527734SSukumar Swaminathan 	    "%s: Verifying image...", file->label);
529*82527734SSukumar Swaminathan 
530*82527734SSukumar Swaminathan 	while (block_size) {
531*82527734SSukumar Swaminathan 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
532*82527734SSukumar Swaminathan 		bzero((void *) mp->virt, mp->size);
533*82527734SSukumar Swaminathan 
534*82527734SSukumar Swaminathan 		xfer_size = min(BE_MAX_XFER_SIZE, block_size);
535*82527734SSukumar Swaminathan 
536*82527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.embedded = 0;
537*82527734SSukumar Swaminathan 		mbq->nonembed = (uint8_t *)mp;
538*82527734SSukumar Swaminathan 		mbq->mbox_cmpl = NULL;
539*82527734SSukumar Swaminathan 
540*82527734SSukumar Swaminathan 		mb->mbxCommand = MBX_SLI_CONFIG;
541*82527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
542*82527734SSukumar Swaminathan 
543*82527734SSukumar Swaminathan 		hdr_req = (mbox_req_hdr_t *)mp->virt;
544*82527734SSukumar Swaminathan 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
545*82527734SSukumar Swaminathan 		hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
546*82527734SSukumar Swaminathan 		hdr_req->timeout = 0;
547*82527734SSukumar Swaminathan 		hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
548*82527734SSukumar Swaminathan 		    xfer_size;
549*82527734SSukumar Swaminathan 
550*82527734SSukumar Swaminathan 		flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
551*82527734SSukumar Swaminathan 		flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
552*82527734SSukumar Swaminathan 		flashrom->params.optype = file->type;
553*82527734SSukumar Swaminathan 		flashrom->params.data_buffer_size = xfer_size;
554*82527734SSukumar Swaminathan 		flashrom->params.offset = block_offset;
555*82527734SSukumar Swaminathan 
556*82527734SSukumar Swaminathan 		/* Send read request */
557*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
558*82527734SSukumar Swaminathan 		    MBX_SUCCESS) {
559*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
560*82527734SSukumar Swaminathan 			    "%s: Unable to read image. status=%x",
561*82527734SSukumar Swaminathan 			    file->label, mb->mbxStatus);
562*82527734SSukumar Swaminathan 
563*82527734SSukumar Swaminathan 			rval = EMLXS_IMAGE_FAILED;
564*82527734SSukumar Swaminathan 			goto done;
565*82527734SSukumar Swaminathan 		}
566*82527734SSukumar Swaminathan 
567*82527734SSukumar Swaminathan 		payload = (uint8_t *)(&flashrom->params.data_buffer);
568*82527734SSukumar Swaminathan 
569*82527734SSukumar Swaminathan 		BE_SWAP32_BUFFER(payload, xfer_size);
570*82527734SSukumar Swaminathan 
571*82527734SSukumar Swaminathan 		wptr = (uint32_t *)image_ptr;
572*82527734SSukumar Swaminathan 		wptr1 = (uint32_t *)payload;
573*82527734SSukumar Swaminathan 		for (i = 0; i < xfer_size; i += 4, wptr++, wptr1++) {
574*82527734SSukumar Swaminathan 			if (*wptr != *wptr1) {
575*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
576*82527734SSukumar Swaminathan 				    "%s: Image mismatch. [%08x] %x, %x",
577*82527734SSukumar Swaminathan 				    file->label, i,
578*82527734SSukumar Swaminathan 				    BE_MAX_XFER_SIZE, xfer_size);
579*82527734SSukumar Swaminathan 
580*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
581*82527734SSukumar Swaminathan 				    "%08x: %08x %08x %08x %08x %08x " \
582*82527734SSukumar Swaminathan 				    "%08x %08x %08x",
583*82527734SSukumar Swaminathan 				    i, wptr[0], wptr[1], wptr[2],
584*82527734SSukumar Swaminathan 				    wptr[3], wptr[4], wptr[5], wptr[6],
585*82527734SSukumar Swaminathan 				    wptr[7]);
586*82527734SSukumar Swaminathan 
587*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
588*82527734SSukumar Swaminathan 				    "%08x: %08x %08x %08x %08x %08x " \
589*82527734SSukumar Swaminathan 				    "%08x %08x %08x",
590*82527734SSukumar Swaminathan 				    i, wptr1[0], wptr1[1], wptr1[2],
591*82527734SSukumar Swaminathan 				    wptr1[3], wptr1[4], wptr1[5], wptr1[6],
592*82527734SSukumar Swaminathan 				    wptr1[7]);
593*82527734SSukumar Swaminathan 
594*82527734SSukumar Swaminathan 				rval = EMLXS_IMAGE_FAILED;
595*82527734SSukumar Swaminathan 				goto done;
596*82527734SSukumar Swaminathan 			}
597*82527734SSukumar Swaminathan 		}
598*82527734SSukumar Swaminathan 
599*82527734SSukumar Swaminathan 		bcopy((uint8_t *)(&flashrom->params.data_buffer), image_ptr,
600*82527734SSukumar Swaminathan 		    xfer_size);
601*82527734SSukumar Swaminathan 
602*82527734SSukumar Swaminathan 		block_size -= xfer_size;
603*82527734SSukumar Swaminathan 		block_offset += xfer_size;
604*82527734SSukumar Swaminathan 		image_ptr += xfer_size;
605*82527734SSukumar Swaminathan 	}
606*82527734SSukumar Swaminathan 
607*82527734SSukumar Swaminathan 	/* Verify CRC */
608*82527734SSukumar Swaminathan 	rval = emlxs_sli4_verify_crc(hba, file, mbq, mp);
609*82527734SSukumar Swaminathan 
610*82527734SSukumar Swaminathan done:
611*82527734SSukumar Swaminathan 
612*82527734SSukumar Swaminathan 	if (rval == 0) {
613*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
614*82527734SSukumar Swaminathan 		    "%s: Image verified.", file->label);
615*82527734SSukumar Swaminathan 	}
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 	return (rval);
618fcf3ce44SJohn Forte 
619*82527734SSukumar Swaminathan } /* emlxs_sli4_verify_image() */
620*82527734SSukumar Swaminathan 
621*82527734SSukumar Swaminathan 
622*82527734SSukumar Swaminathan static int32_t
623*82527734SSukumar Swaminathan emlxs_sli4_verify_crc(emlxs_hba_t *hba,
624*82527734SSukumar Swaminathan     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
625*82527734SSukumar Swaminathan {
626*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
627*82527734SSukumar Swaminathan 	uint32_t *wptr;
628*82527734SSukumar Swaminathan 	uint8_t *payload;
629*82527734SSukumar Swaminathan 	MAILBOX4 *mb;
630*82527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
631*82527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
632*82527734SSukumar Swaminathan 	uint32_t	xfer_size;
633*82527734SSukumar Swaminathan 	uint32_t	block_offset;
634*82527734SSukumar Swaminathan 	uint32_t	rval = 0;
635*82527734SSukumar Swaminathan 	uint32_t	value;
636*82527734SSukumar Swaminathan 
637*82527734SSukumar Swaminathan 	xfer_size = 8;
638*82527734SSukumar Swaminathan 	block_offset = file->block_size - xfer_size;
639*82527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
640*82527734SSukumar Swaminathan 
641*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
642*82527734SSukumar Swaminathan 	    "%s: Verifying CRC...", file->label);
643*82527734SSukumar Swaminathan 
644*82527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
645*82527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
646*82527734SSukumar Swaminathan 
647*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
648*82527734SSukumar Swaminathan 	mbq->nonembed = (uint8_t *)mp;
649*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
650*82527734SSukumar Swaminathan 
651*82527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
652*82527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
653*82527734SSukumar Swaminathan 
654*82527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
655*82527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
656*82527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
657*82527734SSukumar Swaminathan 	hdr_req->timeout = 0;
658*82527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
659*82527734SSukumar Swaminathan 	    xfer_size;
660*82527734SSukumar Swaminathan 
661*82527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
662*82527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
663*82527734SSukumar Swaminathan 	flashrom->params.optype = file->type;
664*82527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
665*82527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
666*82527734SSukumar Swaminathan 
667*82527734SSukumar Swaminathan 	/* Send read request */
668*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
669*82527734SSukumar Swaminathan 	    MBX_SUCCESS) {
670*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
671*82527734SSukumar Swaminathan 		    "%s: Unable to read CRC. status=%x",
672*82527734SSukumar Swaminathan 		    file->label, mb->mbxStatus);
673*82527734SSukumar Swaminathan 
674*82527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
675*82527734SSukumar Swaminathan 		goto done;
676*82527734SSukumar Swaminathan 	}
677*82527734SSukumar Swaminathan 
678*82527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
679*82527734SSukumar Swaminathan 	wptr = (uint32_t *)(payload + xfer_size - 8);
680*82527734SSukumar Swaminathan 
681*82527734SSukumar Swaminathan 	/* Verify image size */
682*82527734SSukumar Swaminathan 	value = *wptr++;
683*82527734SSukumar Swaminathan 	if (value != file->image_size) {
684*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
685*82527734SSukumar Swaminathan 		    "%s: Image size mismatch. %08x != %08x",
686*82527734SSukumar Swaminathan 		    file->label, value, file->image_size);
687*82527734SSukumar Swaminathan 
688*82527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
689*82527734SSukumar Swaminathan 		goto done;
690*82527734SSukumar Swaminathan 	}
691*82527734SSukumar Swaminathan 
692*82527734SSukumar Swaminathan 	/* Verify block crc */
693*82527734SSukumar Swaminathan 	value = *wptr;
694*82527734SSukumar Swaminathan 	if (value != file->block_crc) {
695*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
696*82527734SSukumar Swaminathan 		    "%s: CRC mismatch. %08x != %08x",
697*82527734SSukumar Swaminathan 		    file->label, value, file->block_crc);
698*82527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
699*82527734SSukumar Swaminathan 	}
700*82527734SSukumar Swaminathan 
701*82527734SSukumar Swaminathan done:
702*82527734SSukumar Swaminathan 
703*82527734SSukumar Swaminathan 	if (rval == 0) {
704*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
705*82527734SSukumar Swaminathan 		    "%s: CRC verified.", file->label);
706*82527734SSukumar Swaminathan 	}
707*82527734SSukumar Swaminathan 
708*82527734SSukumar Swaminathan 	return (rval);
709*82527734SSukumar Swaminathan 
710*82527734SSukumar Swaminathan } /* emlxs_sli4_verify_crc() */
711*82527734SSukumar Swaminathan 
712*82527734SSukumar Swaminathan 
713*82527734SSukumar Swaminathan extern int32_t
714*82527734SSukumar Swaminathan emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw)
715*82527734SSukumar Swaminathan {
716*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
717*82527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
718*82527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
719*82527734SSukumar Swaminathan 	MAILBOX4 *mb;
720*82527734SSukumar Swaminathan 	uint32_t *wptr;
721*82527734SSukumar Swaminathan 	uint8_t *payload;
722*82527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
723*82527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
724*82527734SSukumar Swaminathan 	uint32_t	xfer_size;
725*82527734SSukumar Swaminathan 	uint32_t	block_offset;
726*82527734SSukumar Swaminathan 	uint32_t	rval = 0;
727*82527734SSukumar Swaminathan 
728*82527734SSukumar Swaminathan 	bzero((void *) fw, sizeof (emlxs_firmware_t));
729*82527734SSukumar Swaminathan 
730*82527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
731*82527734SSukumar Swaminathan 	    KM_SLEEP)) == NULL) {
732*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
733*82527734SSukumar Swaminathan 		    "read_fw_version: Unable to allocate mailbox buffer.");
734*82527734SSukumar Swaminathan 
735*82527734SSukumar Swaminathan 		rval = 1;
736*82527734SSukumar Swaminathan 		goto done;
737*82527734SSukumar Swaminathan 	}
738*82527734SSukumar Swaminathan 
739*82527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
740*82527734SSukumar Swaminathan 	    sizeof (IOCTL_COMMON_FLASHROM) + 32))) == NULL) {
741*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
742*82527734SSukumar Swaminathan 		    "read_fw_version: Unable to allocate payload buffer.");
743*82527734SSukumar Swaminathan 
744*82527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
745*82527734SSukumar Swaminathan 		goto done;
746*82527734SSukumar Swaminathan 	}
747*82527734SSukumar Swaminathan 
748*82527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
749*82527734SSukumar Swaminathan 
750*82527734SSukumar Swaminathan 	/* Read CRC and size */
751*82527734SSukumar Swaminathan 	xfer_size = 8;
752*82527734SSukumar Swaminathan 	block_offset = 0x140000 - xfer_size;
753*82527734SSukumar Swaminathan 
754*82527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
755*82527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
756*82527734SSukumar Swaminathan 
757*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
758*82527734SSukumar Swaminathan 	mbq->nonembed = (uint8_t *)mp;
759*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
760*82527734SSukumar Swaminathan 
761*82527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
762*82527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
763*82527734SSukumar Swaminathan 
764*82527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
765*82527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
766*82527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
767*82527734SSukumar Swaminathan 	hdr_req->timeout = 0;
768*82527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
769*82527734SSukumar Swaminathan 	    xfer_size;
770*82527734SSukumar Swaminathan 
771*82527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
772*82527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
773*82527734SSukumar Swaminathan 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
774*82527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
775*82527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
776*82527734SSukumar Swaminathan 
777*82527734SSukumar Swaminathan 	/* Send read request */
778*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
779*82527734SSukumar Swaminathan 	    MBX_SUCCESS) {
780*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
781*82527734SSukumar Swaminathan 		    "read_fw_version: Unable to read CRC. status=%x",
782*82527734SSukumar Swaminathan 		    mb->mbxStatus);
783*82527734SSukumar Swaminathan 
784*82527734SSukumar Swaminathan 		rval = 1;
785*82527734SSukumar Swaminathan 		goto done;
786*82527734SSukumar Swaminathan 	}
787*82527734SSukumar Swaminathan 
788*82527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
789*82527734SSukumar Swaminathan 
790*82527734SSukumar Swaminathan 	wptr = (uint32_t *)payload;
791*82527734SSukumar Swaminathan 	fw->size = *wptr++; /* image size */
792*82527734SSukumar Swaminathan 	fw->sli4 = *wptr;   /* block crc */
793*82527734SSukumar Swaminathan 	fw->kern = *wptr;
794*82527734SSukumar Swaminathan 	fw->stub = *wptr;
795*82527734SSukumar Swaminathan 
796*82527734SSukumar Swaminathan 	/* Read version label */
797*82527734SSukumar Swaminathan 	xfer_size = 32;
798*82527734SSukumar Swaminathan 	block_offset = 0x30;
799*82527734SSukumar Swaminathan 
800*82527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
801*82527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
802*82527734SSukumar Swaminathan 
803*82527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
804*82527734SSukumar Swaminathan 	mbq->nonembed = (uint8_t *)mp;
805*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
806*82527734SSukumar Swaminathan 
807*82527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
808*82527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
809*82527734SSukumar Swaminathan 
810*82527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
811*82527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
812*82527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
813*82527734SSukumar Swaminathan 	hdr_req->timeout = 0;
814*82527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
815*82527734SSukumar Swaminathan 	    xfer_size;
816*82527734SSukumar Swaminathan 
817*82527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
818*82527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
819*82527734SSukumar Swaminathan 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
820*82527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
821*82527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
822*82527734SSukumar Swaminathan 
823*82527734SSukumar Swaminathan 	/* Send read request */
824*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
825*82527734SSukumar Swaminathan 	    MBX_SUCCESS) {
826*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
827*82527734SSukumar Swaminathan 		    "read_fw_version: Unable to read version string. status=%x",
828*82527734SSukumar Swaminathan 		    mb->mbxStatus);
829*82527734SSukumar Swaminathan 
830*82527734SSukumar Swaminathan 		rval = 1;
831*82527734SSukumar Swaminathan 		goto done;
832*82527734SSukumar Swaminathan 	}
833*82527734SSukumar Swaminathan 
834*82527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
835*82527734SSukumar Swaminathan 	BE_SWAP32_BCOPY(payload, (uint8_t *)fw->label, 32);
836*82527734SSukumar Swaminathan 
837*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
838*82527734SSukumar Swaminathan 	    "FCOE FIRMWARE: size=%x version=%s (0x%08x)",
839*82527734SSukumar Swaminathan 	    fw->size, fw->label, fw->sli4);
840*82527734SSukumar Swaminathan 
841*82527734SSukumar Swaminathan done:
842*82527734SSukumar Swaminathan 
843*82527734SSukumar Swaminathan 	if (mbq) {
844*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
845*82527734SSukumar Swaminathan 	}
846*82527734SSukumar Swaminathan 
847*82527734SSukumar Swaminathan 	if (mp) {
848*82527734SSukumar Swaminathan 		(void) emlxs_mem_buf_free(hba, mp);
849*82527734SSukumar Swaminathan 	}
850*82527734SSukumar Swaminathan 
851*82527734SSukumar Swaminathan 	return (rval);
852*82527734SSukumar Swaminathan 
853*82527734SSukumar Swaminathan } /* emlxs_sli4_read_fw_version() */
854*82527734SSukumar Swaminathan 
855*82527734SSukumar Swaminathan 
856*82527734SSukumar Swaminathan static uint32_t
857*82527734SSukumar Swaminathan emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer,
858*82527734SSukumar Swaminathan     uint32_t len, emlxs_be_fw_image_t *fw_image)
859*82527734SSukumar Swaminathan {
860*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
861*82527734SSukumar Swaminathan 	emlxs_sli4_ufi_header_t *ufi_hdr;
862*82527734SSukumar Swaminathan 	emlxs_sli4_flash_dir_t *flash_dir;
863*82527734SSukumar Swaminathan 	emlxs_sli4_flash_entry_t *entry;
864*82527734SSukumar Swaminathan 	uint8_t *bptr;
865*82527734SSukumar Swaminathan 	uint32_t *wptr;
866*82527734SSukumar Swaminathan 	uint32_t i;
867*82527734SSukumar Swaminathan 	uint32_t k;
868*82527734SSukumar Swaminathan 	uint32_t mask;
869*82527734SSukumar Swaminathan 	uint32_t value;
870*82527734SSukumar Swaminathan 	uint32_t image_size;
871*82527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file;
872*82527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file2;
873*82527734SSukumar Swaminathan 	char signature[BE_SIGNATURE_SIZE];
874*82527734SSukumar Swaminathan 	uint32_t ufi_plus = 0;
875*82527734SSukumar Swaminathan 
876*82527734SSukumar Swaminathan 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
877*82527734SSukumar Swaminathan 
878*82527734SSukumar Swaminathan 	if (hba->model_info.chip != EMLXS_TIGERSHARK_CHIP) {
879*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
880*82527734SSukumar Swaminathan 		    "Invalid adapter model.");
881*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
882*82527734SSukumar Swaminathan 	}
883*82527734SSukumar Swaminathan 
884*82527734SSukumar Swaminathan 	if (len < (sizeof (emlxs_sli4_ufi_header_t) +
885*82527734SSukumar Swaminathan 	    sizeof (emlxs_sli4_flash_dir_t))) {
886*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
887*82527734SSukumar Swaminathan 		    "Image too small. (%d < %d)",
888*82527734SSukumar Swaminathan 		    len, (sizeof (emlxs_sli4_ufi_header_t) +
889*82527734SSukumar Swaminathan 		    sizeof (emlxs_sli4_flash_dir_t)));
890*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
891*82527734SSukumar Swaminathan 	}
892*82527734SSukumar Swaminathan 	ufi_hdr = (emlxs_sli4_ufi_header_t *)buffer;
893*82527734SSukumar Swaminathan 
894*82527734SSukumar Swaminathan 	/* Check if this is a standard UFI image */
895*82527734SSukumar Swaminathan 	if (strncmp(BE_SIGNATURE, ufi_hdr->signature,
896*82527734SSukumar Swaminathan 	    sizeof (BE_SIGNATURE)-1) != 0) {
897*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
898*82527734SSukumar Swaminathan 		    "Invalid image provided.");
899*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
900*82527734SSukumar Swaminathan 	}
901*82527734SSukumar Swaminathan 
902*82527734SSukumar Swaminathan 	/* Check for special deflated format */
903*82527734SSukumar Swaminathan 	(void) sprintf(signature, "%s+", BE_SIGNATURE);
904*82527734SSukumar Swaminathan 	if (strncmp(signature, ufi_hdr->signature,
905*82527734SSukumar Swaminathan 	    sizeof (signature)-1) == 0) {
906*82527734SSukumar Swaminathan 		ufi_plus = 1;
907*82527734SSukumar Swaminathan 	}
908*82527734SSukumar Swaminathan 
909*82527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
910*82527734SSukumar Swaminathan 	/* Big Endian Swapping */
911*82527734SSukumar Swaminathan 	/* Swap ufi header */
912*82527734SSukumar Swaminathan 	ufi_hdr->checksum =
913*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->checksum);
914*82527734SSukumar Swaminathan 	ufi_hdr->antidote =
915*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->antidote);
916*82527734SSukumar Swaminathan 	ufi_hdr->controller.vendor_id =
917*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.vendor_id);
918*82527734SSukumar Swaminathan 	ufi_hdr->controller.device_id =
919*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.device_id);
920*82527734SSukumar Swaminathan 	ufi_hdr->controller.sub_vendor_id =
921*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.sub_vendor_id);
922*82527734SSukumar Swaminathan 	ufi_hdr->controller.sub_device_id =
923*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.sub_device_id);
924*82527734SSukumar Swaminathan 	ufi_hdr->file_length =
925*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->file_length);
926*82527734SSukumar Swaminathan 	ufi_hdr->chunk_num =
927*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->chunk_num);
928*82527734SSukumar Swaminathan 	ufi_hdr->chunk_cnt =
929*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->chunk_cnt);
930*82527734SSukumar Swaminathan 	ufi_hdr->image_cnt =
931*82527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->image_cnt);
932*82527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
933*82527734SSukumar Swaminathan 
934*82527734SSukumar Swaminathan 	if (len != ufi_hdr->file_length) {
935*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
936*82527734SSukumar Swaminathan 		    "Invalid image size (%d != %d)",
937*82527734SSukumar Swaminathan 		    len, ufi_hdr->file_length);
938*82527734SSukumar Swaminathan 
939*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
940*82527734SSukumar Swaminathan 	}
941*82527734SSukumar Swaminathan 
942*82527734SSukumar Swaminathan 	/* Scan for flash dir signature */
943*82527734SSukumar Swaminathan 	bptr = (uint8_t *)buffer;
944*82527734SSukumar Swaminathan 	flash_dir = NULL;
945*82527734SSukumar Swaminathan 	for (i = 0; i < len; i++, bptr++) {
946*82527734SSukumar Swaminathan 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
947*82527734SSukumar Swaminathan 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
948*82527734SSukumar Swaminathan 			flash_dir = (emlxs_sli4_flash_dir_t *)bptr;
949*82527734SSukumar Swaminathan 			break;
950*82527734SSukumar Swaminathan 		}
951*82527734SSukumar Swaminathan 	}
952*82527734SSukumar Swaminathan 
953*82527734SSukumar Swaminathan 	if (!flash_dir) {
954*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
955*82527734SSukumar Swaminathan 		    "Unable to find flash directory.");
956*82527734SSukumar Swaminathan 
957*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
958*82527734SSukumar Swaminathan 	}
959*82527734SSukumar Swaminathan 
960*82527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
961*82527734SSukumar Swaminathan 	/* Big Endian Swapping */
962*82527734SSukumar Swaminathan 	/* Swap flash dir */
963*82527734SSukumar Swaminathan 	flash_dir->header.format_rev =
964*82527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.format_rev);
965*82527734SSukumar Swaminathan 	flash_dir->header.checksum =
966*82527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.checksum);
967*82527734SSukumar Swaminathan 	flash_dir->header.antidote =
968*82527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.antidote);
969*82527734SSukumar Swaminathan 	flash_dir->header.build_num =
970*82527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.build_num);
971*82527734SSukumar Swaminathan 	flash_dir->header.active_entry_mask =
972*82527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.active_entry_mask);
973*82527734SSukumar Swaminathan 	flash_dir->header.valid_entry_mask =
974*82527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.valid_entry_mask);
975*82527734SSukumar Swaminathan 	flash_dir->header.orig_content_mask =
976*82527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.orig_content_mask);
977*82527734SSukumar Swaminathan 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
978*82527734SSukumar Swaminathan 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
979*82527734SSukumar Swaminathan 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
980*82527734SSukumar Swaminathan 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
981*82527734SSukumar Swaminathan 	flash_dir->header.resv4 = SWAP32(flash_dir->header.resv4);
982*82527734SSukumar Swaminathan 
983*82527734SSukumar Swaminathan 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
984*82527734SSukumar Swaminathan 		flash_dir->header.controller[i].vendor_id =
985*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].vendor_id);
986*82527734SSukumar Swaminathan 		flash_dir->header.controller[i].device_id =
987*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].device_id);
988*82527734SSukumar Swaminathan 		flash_dir->header.controller[i].sub_vendor_id =
989*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
990*82527734SSukumar Swaminathan 		flash_dir->header.controller[i].sub_device_id =
991*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
992*82527734SSukumar Swaminathan 	}
993*82527734SSukumar Swaminathan 
994*82527734SSukumar Swaminathan 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++,  mask <<= 1) {
995*82527734SSukumar Swaminathan 
996*82527734SSukumar Swaminathan 		if (!(flash_dir->header.valid_entry_mask & mask)) {
997*82527734SSukumar Swaminathan 			continue;
998*82527734SSukumar Swaminathan 		}
999*82527734SSukumar Swaminathan 
1000*82527734SSukumar Swaminathan 		entry = &flash_dir->entry[i];
1001*82527734SSukumar Swaminathan 		if (entry->image_size == 0) {
1002*82527734SSukumar Swaminathan 			continue;
1003*82527734SSukumar Swaminathan 		}
1004*82527734SSukumar Swaminathan 
1005*82527734SSukumar Swaminathan 		flash_dir->entry[i].type =
1006*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].type);
1007*82527734SSukumar Swaminathan 		flash_dir->entry[i].offset =
1008*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].offset);
1009*82527734SSukumar Swaminathan 		flash_dir->entry[i].pad_size =
1010*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].pad_size);
1011*82527734SSukumar Swaminathan 		flash_dir->entry[i].image_size =
1012*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].image_size);
1013*82527734SSukumar Swaminathan 		flash_dir->entry[i].checksum =
1014*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].checksum);
1015*82527734SSukumar Swaminathan 		flash_dir->entry[i].entry_point =
1016*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].entry_point);
1017*82527734SSukumar Swaminathan 		flash_dir->entry[i].resv0 =
1018*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].resv0);
1019*82527734SSukumar Swaminathan 		flash_dir->entry[i].resv1 =
1020*82527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].resv1);
1021*82527734SSukumar Swaminathan 	}
1022*82527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
1023*82527734SSukumar Swaminathan 
1024*82527734SSukumar Swaminathan 	/* Build fw_image table */
1025*82527734SSukumar Swaminathan 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) {
1026*82527734SSukumar Swaminathan 
1027*82527734SSukumar Swaminathan 		if (!(flash_dir->header.valid_entry_mask & mask)) {
1028*82527734SSukumar Swaminathan 			continue;
1029*82527734SSukumar Swaminathan 		}
1030*82527734SSukumar Swaminathan 
1031*82527734SSukumar Swaminathan 		entry = &flash_dir->entry[i];
1032*82527734SSukumar Swaminathan 		if (entry->image_size == 0) {
1033*82527734SSukumar Swaminathan 			continue;
1034*82527734SSukumar Swaminathan 		}
1035*82527734SSukumar Swaminathan 
1036*82527734SSukumar Swaminathan 		switch (entry->type) {
1037*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_REDBOOT:
1038*82527734SSukumar Swaminathan 			file = &fw_image->file[REDBOOT_FLASHTYPE];
1039*82527734SSukumar Swaminathan 			(void) strcpy(file->label, "REDBOOT");
1040*82527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
1041*82527734SSukumar Swaminathan 			break;
1042*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_BIOS:
1043*82527734SSukumar Swaminathan 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1044*82527734SSukumar Swaminathan 			(void) strcpy(file->label, "ISCSI BIOS");
1045*82527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
1046*82527734SSukumar Swaminathan 			break;
1047*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_PXE_BIOS:
1048*82527734SSukumar Swaminathan 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1049*82527734SSukumar Swaminathan 			(void) strcpy(file->label, "PXE BIOS");
1050*82527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
1051*82527734SSukumar Swaminathan 			break;
1052*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_BIOS:
1053*82527734SSukumar Swaminathan 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1054*82527734SSukumar Swaminathan 			(void) strcpy(file->label, "FCOE BIOS");
1055*82527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
1056*82527734SSukumar Swaminathan 			break;
1057*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
1058*82527734SSukumar Swaminathan 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1059*82527734SSukumar Swaminathan 			(void) strcpy(file->label, "ISCSI FIRMWARE");
1060*82527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
1061*82527734SSukumar Swaminathan 			break;
1062*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_FIRMWARE:
1063*82527734SSukumar Swaminathan 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1064*82527734SSukumar Swaminathan 			(void) strcpy(file->label, "FCOE FIRMWARE");
1065*82527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
1066*82527734SSukumar Swaminathan 			break;
1067*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_BACKUP:
1068*82527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_BACKUP:
1069*82527734SSukumar Swaminathan 			continue;
1070*82527734SSukumar Swaminathan 
1071*82527734SSukumar Swaminathan 		default:
1072*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1073*82527734SSukumar Swaminathan 			    "Unknown image type found.  type=%x",
1074*82527734SSukumar Swaminathan 			    entry->type);
1075*82527734SSukumar Swaminathan 			continue;
1076*82527734SSukumar Swaminathan 		}
1077*82527734SSukumar Swaminathan 
1078*82527734SSukumar Swaminathan 		file->image_size = entry->image_size;
1079*82527734SSukumar Swaminathan 		image_size = BE_SWAP32(entry->image_size);
1080*82527734SSukumar Swaminathan 
1081*82527734SSukumar Swaminathan 		if (ufi_plus) {
1082*82527734SSukumar Swaminathan 			file->image_offset = entry->offset;
1083*82527734SSukumar Swaminathan 			file->block_size   = entry->pad_size;
1084*82527734SSukumar Swaminathan 			file->block_crc    = entry->checksum;
1085*82527734SSukumar Swaminathan 		} else {
1086*82527734SSukumar Swaminathan 			file->image_offset = entry->offset +
1087*82527734SSukumar Swaminathan 			    sizeof (emlxs_sli4_ufi_header_t);
1088*82527734SSukumar Swaminathan 
1089*82527734SSukumar Swaminathan 			/* Get entry block size and crc */
1090*82527734SSukumar Swaminathan 			k = file->image_offset + file->image_size;
1091*82527734SSukumar Swaminathan 			k &= 0xFFFFFFFC;
1092*82527734SSukumar Swaminathan 
1093*82527734SSukumar Swaminathan 			wptr = (uint32_t *)(buffer +  k);
1094*82527734SSukumar Swaminathan 			for (; k < len; k += 4) {
1095*82527734SSukumar Swaminathan 				if (*wptr++ == image_size) {
1096*82527734SSukumar Swaminathan 					/* Calculate block_size */
1097*82527734SSukumar Swaminathan 					file->block_size = (k + 8) -
1098*82527734SSukumar Swaminathan 					    file->image_offset;
1099*82527734SSukumar Swaminathan 
1100*82527734SSukumar Swaminathan 					/* Read block_crc */
1101*82527734SSukumar Swaminathan 					value = *wptr;
1102*82527734SSukumar Swaminathan 					file->block_crc = BE_SWAP32(value);
1103*82527734SSukumar Swaminathan 
1104*82527734SSukumar Swaminathan 					break;
1105*82527734SSukumar Swaminathan 				}
1106*82527734SSukumar Swaminathan 			}
1107*82527734SSukumar Swaminathan 
1108*82527734SSukumar Swaminathan 			if (k >= len) {
1109*82527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1110*82527734SSukumar Swaminathan 				    "%s: End of block not found. offset=%x",
1111*82527734SSukumar Swaminathan 				    file->label, file->image_offset);
1112*82527734SSukumar Swaminathan 
1113*82527734SSukumar Swaminathan 				bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1114*82527734SSukumar Swaminathan 				return (EMLXS_IMAGE_BAD);
1115*82527734SSukumar Swaminathan 			}
1116*82527734SSukumar Swaminathan 		}
1117*82527734SSukumar Swaminathan 
1118*82527734SSukumar Swaminathan 		/* Make sure image will fit in block specified */
1119*82527734SSukumar Swaminathan 		if (file->image_size + 8 > file->block_size) {
1120*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1121*82527734SSukumar Swaminathan 			    "%s: Image too large for block. image=%x block=%x",
1122*82527734SSukumar Swaminathan 			    file->label, file->image_size, file->block_size);
1123*82527734SSukumar Swaminathan 
1124*82527734SSukumar Swaminathan 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1125*82527734SSukumar Swaminathan 			return (EMLXS_IMAGE_BAD);
1126*82527734SSukumar Swaminathan 		}
1127*82527734SSukumar Swaminathan 
1128*82527734SSukumar Swaminathan 		/* Automatically create a backup file entry for firmware */
1129*82527734SSukumar Swaminathan 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1130*82527734SSukumar Swaminathan 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1131*82527734SSukumar Swaminathan 			(void) strcpy(file2->label, "FCOE BACKUP");
1132*82527734SSukumar Swaminathan 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1133*82527734SSukumar Swaminathan 			file2->image_offset = file->image_offset;
1134*82527734SSukumar Swaminathan 			file2->image_size = file->image_size;
1135*82527734SSukumar Swaminathan 			file2->block_size = file->block_size;
1136*82527734SSukumar Swaminathan 			file2->block_crc = file->block_crc;
1137*82527734SSukumar Swaminathan 
1138*82527734SSukumar Swaminathan 			/* Save FCOE version info */
1139*82527734SSukumar Swaminathan 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1140*82527734SSukumar Swaminathan 			(void) strncpy(fw_image->label, (char *)bptr,
1141*82527734SSukumar Swaminathan 			    BE_VERSION_SIZE);
1142*82527734SSukumar Swaminathan 			fw_image->version = file->block_crc;
1143*82527734SSukumar Swaminathan 
1144*82527734SSukumar Swaminathan 		} else if (file->type ==
1145*82527734SSukumar Swaminathan 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1146*82527734SSukumar Swaminathan 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1147*82527734SSukumar Swaminathan 			(void) strcpy(file2->label, "ISCSI BACKUP");
1148*82527734SSukumar Swaminathan 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1149*82527734SSukumar Swaminathan 			file2->image_offset = file->image_offset;
1150*82527734SSukumar Swaminathan 			file2->image_size = file->image_size;
1151*82527734SSukumar Swaminathan 			file2->block_size = file->block_size;
1152*82527734SSukumar Swaminathan 			file2->block_crc = file->block_crc;
1153*82527734SSukumar Swaminathan 		}
1154*82527734SSukumar Swaminathan 	}
1155*82527734SSukumar Swaminathan 
1156*82527734SSukumar Swaminathan 	if (fw_image->version == 0) {
1157*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1158*82527734SSukumar Swaminathan 		    "Unable to find FCOE firmware component.");
1159*82527734SSukumar Swaminathan 
1160*82527734SSukumar Swaminathan 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1161*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
1162*82527734SSukumar Swaminathan 	}
1163*82527734SSukumar Swaminathan 
1164*82527734SSukumar Swaminathan 	/* Display contents */
1165*82527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1166*82527734SSukumar Swaminathan 	    "UFI Image: %08x, %s", fw_image->version, fw_image->label);
1167*82527734SSukumar Swaminathan 
1168*82527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1169*82527734SSukumar Swaminathan 		file = &fw_image->file[i];
1170*82527734SSukumar Swaminathan 
1171*82527734SSukumar Swaminathan 		if (file->image_size == 0) {
1172*82527734SSukumar Swaminathan 			continue;
1173*82527734SSukumar Swaminathan 		}
1174*82527734SSukumar Swaminathan 
1175*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1176*82527734SSukumar Swaminathan 		    "%s: type=%x block=%x image=%x offset=%x crc=%x",
1177*82527734SSukumar Swaminathan 		    file->label, file->type, file->block_size,
1178*82527734SSukumar Swaminathan 		    file->image_size, file->image_offset, file->block_crc);
1179*82527734SSukumar Swaminathan 	}
1180*82527734SSukumar Swaminathan 
1181*82527734SSukumar Swaminathan 	return (0);
1182*82527734SSukumar Swaminathan 
1183*82527734SSukumar Swaminathan } /* emlxs_sli4_validate_image() */
1184*82527734SSukumar Swaminathan 
1185*82527734SSukumar Swaminathan 
1186*82527734SSukumar Swaminathan static int32_t
1187*82527734SSukumar Swaminathan emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
1188*82527734SSukumar Swaminathan     uint32_t offline)
1189*82527734SSukumar Swaminathan {
1190*82527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
1191*82527734SSukumar Swaminathan 	uint32_t i;
1192*82527734SSukumar Swaminathan 	uint32_t update = 0;
1193*82527734SSukumar Swaminathan 	uint32_t rval = 0;
1194*82527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
1195*82527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
1196*82527734SSukumar Swaminathan 	emlxs_be_fw_image_t fw_image;
1197*82527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file;
1198*82527734SSukumar Swaminathan 
1199*82527734SSukumar Swaminathan 	/* For now we will not take the driver offline during a download */
1200*82527734SSukumar Swaminathan 	offline = 0;
1201*82527734SSukumar Swaminathan 
1202*82527734SSukumar Swaminathan 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
1203*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1204*82527734SSukumar Swaminathan 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
1205*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
1206*82527734SSukumar Swaminathan 	}
1207*82527734SSukumar Swaminathan 
1208*82527734SSukumar Swaminathan 	if (buffer == NULL || len == 0) {
1209*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1210*82527734SSukumar Swaminathan 		    "Empty buffer provided. buf=%p size=%d", buffer, len);
1211*82527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
1212*82527734SSukumar Swaminathan 	}
1213*82527734SSukumar Swaminathan 
1214*82527734SSukumar Swaminathan 	/* Validate image */
1215*82527734SSukumar Swaminathan 	if ((rval = emlxs_sli4_validate_image(hba, buffer, len, &fw_image))) {
1216*82527734SSukumar Swaminathan 		return (rval);
1217*82527734SSukumar Swaminathan 	}
1218*82527734SSukumar Swaminathan 
1219*82527734SSukumar Swaminathan 	/* Allocate resources */
1220*82527734SSukumar Swaminathan 
1221*82527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1222*82527734SSukumar Swaminathan 	    KM_SLEEP)) == NULL) {
1223*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1224*82527734SSukumar Swaminathan 		    "Unable to allocate mailbox buffer.");
1225*82527734SSukumar Swaminathan 
1226*82527734SSukumar Swaminathan 		offline = 0;
1227*82527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
1228*82527734SSukumar Swaminathan 		goto done;
1229*82527734SSukumar Swaminathan 	}
1230*82527734SSukumar Swaminathan 
1231*82527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
1232*82527734SSukumar Swaminathan 	    sizeof (IOCTL_COMMON_FLASHROM) + BE_MAX_XFER_SIZE))) == NULL) {
1233*82527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1234*82527734SSukumar Swaminathan 		    "Unable to allocate flash buffer.");
1235*82527734SSukumar Swaminathan 
1236*82527734SSukumar Swaminathan 		offline = 0;
1237*82527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
1238*82527734SSukumar Swaminathan 		goto done;
1239*82527734SSukumar Swaminathan 	}
1240*82527734SSukumar Swaminathan 
1241*82527734SSukumar Swaminathan 	/* Check if update is required */
1242*82527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1243*82527734SSukumar Swaminathan 		file = &fw_image.file[i];
1244*82527734SSukumar Swaminathan 
1245*82527734SSukumar Swaminathan 		if (file->image_size == 0) {
1246*82527734SSukumar Swaminathan 			continue;
1247*82527734SSukumar Swaminathan 		}
1248*82527734SSukumar Swaminathan 
1249*82527734SSukumar Swaminathan 		rval = emlxs_sli4_verify_crc(hba, file, mbq, mp);
1250fcf3ce44SJohn Forte 
1251*82527734SSukumar Swaminathan 		if (rval == 0) {
1252*82527734SSukumar Swaminathan 			file->image_size = 0;
1253*82527734SSukumar Swaminathan 			continue;
1254*82527734SSukumar Swaminathan 		}
1255*82527734SSukumar Swaminathan 
1256*82527734SSukumar Swaminathan 		update++;
1257*82527734SSukumar Swaminathan 	}
1258*82527734SSukumar Swaminathan 
1259*82527734SSukumar Swaminathan 	if (!update) {
1260*82527734SSukumar Swaminathan 		offline = 0;
1261*82527734SSukumar Swaminathan 		goto done;
1262*82527734SSukumar Swaminathan 	}
1263*82527734SSukumar Swaminathan 
1264*82527734SSukumar Swaminathan 	/*
1265*82527734SSukumar Swaminathan 	 * Everything checks out, now to just do it
1266*82527734SSukumar Swaminathan 	 */
1267*82527734SSukumar Swaminathan 	if (offline) {
1268*82527734SSukumar Swaminathan 		if (emlxs_offline(hba) != FC_SUCCESS) {
1269*82527734SSukumar Swaminathan 
1270*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1271*82527734SSukumar Swaminathan 			    "Unable to take adapter offline.");
1272*82527734SSukumar Swaminathan 
1273*82527734SSukumar Swaminathan 			offline = 0;
1274*82527734SSukumar Swaminathan 			rval = EMLXS_OFFLINE_FAILED;
1275*82527734SSukumar Swaminathan 			goto done;
1276*82527734SSukumar Swaminathan 		}
1277*82527734SSukumar Swaminathan 	}
1278*82527734SSukumar Swaminathan 
1279*82527734SSukumar Swaminathan 	/* Download entries which require update */
1280*82527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1281*82527734SSukumar Swaminathan 		file = &fw_image.file[i];
1282*82527734SSukumar Swaminathan 
1283*82527734SSukumar Swaminathan 		if (file->image_size == 0) {
1284*82527734SSukumar Swaminathan 			continue;
1285*82527734SSukumar Swaminathan 		}
1286*82527734SSukumar Swaminathan 
1287*82527734SSukumar Swaminathan 		rval = emlxs_sli4_flash_image(hba, buffer, file, mbq, mp);
1288*82527734SSukumar Swaminathan 
1289*82527734SSukumar Swaminathan 		if (rval != 0) {
1290*82527734SSukumar Swaminathan 			goto done;
1291*82527734SSukumar Swaminathan 		}
1292*82527734SSukumar Swaminathan 	}
1293*82527734SSukumar Swaminathan 
1294*82527734SSukumar Swaminathan done:
1295*82527734SSukumar Swaminathan 	if (mbq) {
1296*82527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1297*82527734SSukumar Swaminathan 	}
1298*82527734SSukumar Swaminathan 
1299*82527734SSukumar Swaminathan 	if (mp) {
1300*82527734SSukumar Swaminathan 		(void) emlxs_mem_buf_free(hba, mp);
1301*82527734SSukumar Swaminathan 	}
1302*82527734SSukumar Swaminathan 
1303*82527734SSukumar Swaminathan 	if (offline) {
1304*82527734SSukumar Swaminathan 		(void) emlxs_online(hba);
1305*82527734SSukumar Swaminathan 	}
1306*82527734SSukumar Swaminathan 
1307*82527734SSukumar Swaminathan 	if (rval == 0) {
1308*82527734SSukumar Swaminathan 		if (update) {
1309*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1310*82527734SSukumar Swaminathan 			    "Status good.");
1311*82527734SSukumar Swaminathan 
1312*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
1313*82527734SSukumar Swaminathan 			    "Please reboot system or power cycle adapter "
1314*82527734SSukumar Swaminathan 			    "to activate new firmware: %s", fw_image.label);
1315*82527734SSukumar Swaminathan 
1316*82527734SSukumar Swaminathan 		} else {
1317*82527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1318*82527734SSukumar Swaminathan 			    "No firmware update required.");
1319*82527734SSukumar Swaminathan 		}
1320*82527734SSukumar Swaminathan 	}
1321*82527734SSukumar Swaminathan 
1322*82527734SSukumar Swaminathan 	return (rval);
1323*82527734SSukumar Swaminathan 
1324*82527734SSukumar Swaminathan } /* emlxs_sli4_fw_download() */
1325fcf3ce44SJohn Forte 
1326fcf3ce44SJohn Forte 
1327fcf3ce44SJohn Forte extern int32_t
1328fcf3ce44SJohn Forte emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer,
1329fcf3ce44SJohn Forte     uint32_t len)
1330fcf3ce44SJohn Forte {
1331fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1332fcf3ce44SJohn Forte 	MAILBOXQ *mbox = NULL;
1333fcf3ce44SJohn Forte 	MAILBOX *mb;
1334fcf3ce44SJohn Forte 	uint32_t rval = 0;
1335fcf3ce44SJohn Forte 	uint32_t region_id;
1336fcf3ce44SJohn Forte 	uint32_t id;
1337*82527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
1338fcf3ce44SJohn Forte 	caddr_t local_buffer;
1339fcf3ce44SJohn Forte 	uint32_t *bptr1;
1340fcf3ce44SJohn Forte 	uint32_t *bptr2;
1341fcf3ce44SJohn Forte 	uint32_t i;
1342*82527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
1343fcf3ce44SJohn Forte 
1344fcf3ce44SJohn Forte 	if (buffer == NULL || len == 0) {
1345fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1346fcf3ce44SJohn Forte 	}
1347*82527734SSukumar Swaminathan 
1348*82527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
1349fcf3ce44SJohn Forte 	/* We need to swap the image buffer before we start */
1350fcf3ce44SJohn Forte 
1351fcf3ce44SJohn Forte 	/*
1352fcf3ce44SJohn Forte 	 * Use KM_SLEEP to allocate a temporary buffer
1353fcf3ce44SJohn Forte 	 */
1354fcf3ce44SJohn Forte 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
1355fcf3ce44SJohn Forte 
1356fcf3ce44SJohn Forte 	/* Perform a 32 bit swap of the image */
1357fcf3ce44SJohn Forte 	bptr1 = (uint32_t *)local_buffer;
1358fcf3ce44SJohn Forte 	bptr2 = (uint32_t *)buffer;
1359fcf3ce44SJohn Forte 
1360fcf3ce44SJohn Forte 	for (i = 0; i < (len / 4); i++) {
1361*82527734SSukumar Swaminathan 		*bptr1 = SWAP32(*bptr2);
1362fcf3ce44SJohn Forte 		bptr1++;
1363fcf3ce44SJohn Forte 		bptr2++;
1364fcf3ce44SJohn Forte 	}
1365fcf3ce44SJohn Forte 
1366fcf3ce44SJohn Forte 	/* Replace the original buffer */
1367fcf3ce44SJohn Forte 	buffer = local_buffer;
1368fcf3ce44SJohn Forte 
1369*82527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
1370fcf3ce44SJohn Forte 
1371fcf3ce44SJohn Forte 	if (len > 128) {
1372fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1373291a2b48SSukumar Swaminathan 		    "Invalid image length: 0x%x > 128", len);
1374fcf3ce44SJohn Forte 
1375fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1376fcf3ce44SJohn Forte 	}
1377291a2b48SSukumar Swaminathan 
1378fcf3ce44SJohn Forte 	/* Check the region number */
1379fcf3ce44SJohn Forte 	if ((region > 2) && (region != 0xff)) {
1380fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1381291a2b48SSukumar Swaminathan 		    "Invalid region id: 0x%x", region);
1382fcf3ce44SJohn Forte 
1383fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1384fcf3ce44SJohn Forte 
1385fcf3ce44SJohn Forte 	}
1386291a2b48SSukumar Swaminathan 
1387fcf3ce44SJohn Forte 	/* Check the image vendor id */
1388fcf3ce44SJohn Forte 	id = *(int32_t *)buffer;
1389fcf3ce44SJohn Forte 	if ((id & 0xffff) != 0x10df) {
1390fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1391291a2b48SSukumar Swaminathan 		    "Invalid image id: 0x%x", id);
1392fcf3ce44SJohn Forte 
1393fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
1394fcf3ce44SJohn Forte 	}
1395291a2b48SSukumar Swaminathan 
1396291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1397291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1398fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1399fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
1400fcf3ce44SJohn Forte 
1401fcf3ce44SJohn Forte 		rval = 1;
1402fcf3ce44SJohn Forte 
1403fcf3ce44SJohn Forte 		goto done;
1404fcf3ce44SJohn Forte 	}
1405291a2b48SSukumar Swaminathan 
1406fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
1407fcf3ce44SJohn Forte 
1408fcf3ce44SJohn Forte 	/*
1409fcf3ce44SJohn Forte 	 * Everything checks out, now to just do it
1410fcf3ce44SJohn Forte 	 */
1411fcf3ce44SJohn Forte 	if (emlxs_offline(hba) != FC_SUCCESS) {
1412fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1413fcf3ce44SJohn Forte 		    "Unable to take HBA offline.");
1414fcf3ce44SJohn Forte 
1415fcf3ce44SJohn Forte 		rval = EMLXS_OFFLINE_FAILED;
1416fcf3ce44SJohn Forte 
1417fcf3ce44SJohn Forte 		goto done;
1418fcf3ce44SJohn Forte 	}
1419291a2b48SSukumar Swaminathan 
1420*82527734SSukumar Swaminathan 	if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
1421fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1422fcf3ce44SJohn Forte 		    "Unable to restart adapter.");
1423fcf3ce44SJohn Forte 
1424fcf3ce44SJohn Forte 		rval = EMLXS_OFFLINE_FAILED;
1425fcf3ce44SJohn Forte 
1426fcf3ce44SJohn Forte 		goto done;
1427fcf3ce44SJohn Forte 	}
1428291a2b48SSukumar Swaminathan 
1429fcf3ce44SJohn Forte 	/* Check if default region is requested */
1430fcf3ce44SJohn Forte 	if (region == 0xff) {
1431fcf3ce44SJohn Forte 		/*
1432291a2b48SSukumar Swaminathan 		 * Sun-branded Helios and Zypher have different
1433291a2b48SSukumar Swaminathan 		 * default PCI region
1434fcf3ce44SJohn Forte 		 */
1435fcf3ce44SJohn Forte 		if ((hba->model_info.flags & EMLXS_SUN_BRANDED) &&
1436fcf3ce44SJohn Forte 		    (hba->model_info.chip &
1437fcf3ce44SJohn Forte 		    (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
1438fcf3ce44SJohn Forte 			region = 2;
1439fcf3ce44SJohn Forte 		} else {
1440fcf3ce44SJohn Forte 			region = 0;
1441fcf3ce44SJohn Forte 		}
1442fcf3ce44SJohn Forte 	}
1443291a2b48SSukumar Swaminathan 
1444fcf3ce44SJohn Forte 	/* Set region id based on PCI region requested */
1445fcf3ce44SJohn Forte 	region_id = DEF_PCI_CFG_REGION_ID + region;
1446fcf3ce44SJohn Forte 
1447fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1448291a2b48SSukumar Swaminathan 	    "PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
1449291a2b48SSukumar Swaminathan 	    region_id, id, len);
1450fcf3ce44SJohn Forte 
1451fcf3ce44SJohn Forte 	/* Copy the data buffer to SLIM */
1452fcf3ce44SJohn Forte 	WRITE_SLIM_COPY(hba, (uint32_t *)buffer,
1453*82527734SSukumar Swaminathan 	    (volatile uint32_t *)((volatile char *)hba->sli.sli3.slim_addr +
1454291a2b48SSukumar Swaminathan 	    sizeof (MAILBOX)), (len / sizeof (uint32_t)));
1455fcf3ce44SJohn Forte 
14564baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
1457*82527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
14584baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
14594baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
14604baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
14614baa2c25SSukumar Swaminathan 		rval = 1;
14624baa2c25SSukumar Swaminathan 	}
14634baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
14644baa2c25SSukumar Swaminathan 
1465*82527734SSukumar Swaminathan 	emlxs_format_update_pci_cfg(hba, mbox, region_id, len);
1466fcf3ce44SJohn Forte 
1467*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
1468fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1469291a2b48SSukumar Swaminathan 		    "Unable to update PCI configuration: Mailbox cmd=%x "
1470291a2b48SSukumar Swaminathan 		    "status=%x info=%d", mb->mbxCommand, mb->mbxStatus,
1471fcf3ce44SJohn Forte 		    mb->un.varUpdateCfg.rsp_info);
1472fcf3ce44SJohn Forte 
1473fcf3ce44SJohn Forte 		rval = 1;
1474fcf3ce44SJohn Forte 	}
1475291a2b48SSukumar Swaminathan 
1476fcf3ce44SJohn Forte 	(void) emlxs_online(hba);
1477fcf3ce44SJohn Forte 
1478fcf3ce44SJohn Forte 	if (rval == 0) {
1479fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1480fcf3ce44SJohn Forte 		    "Status good.");
1481fcf3ce44SJohn Forte 	}
1482291a2b48SSukumar Swaminathan 
1483fcf3ce44SJohn Forte done:
1484fcf3ce44SJohn Forte 
1485fcf3ce44SJohn Forte 	if (mbox) {
1486fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
1487fcf3ce44SJohn Forte 	}
1488*82527734SSukumar Swaminathan 
1489*82527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
1490fcf3ce44SJohn Forte 	/* Free the local buffer */
1491fcf3ce44SJohn Forte 	kmem_free(local_buffer, len);
1492*82527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
1493fcf3ce44SJohn Forte 
1494fcf3ce44SJohn Forte 	return (rval);
1495fcf3ce44SJohn Forte 
1496*82527734SSukumar Swaminathan } /* emlxs_cfl_download */
1497fcf3ce44SJohn Forte 
1498fcf3ce44SJohn Forte 
1499fcf3ce44SJohn Forte static uint32_t
1500fcf3ce44SJohn Forte emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr)
1501fcf3ce44SJohn Forte {
1502fcf3ce44SJohn Forte 	uint32_t Temp;
1503fcf3ce44SJohn Forte 	uint32_t CkSum;
1504fcf3ce44SJohn Forte 
1505fcf3ce44SJohn Forte 	EndAddr++;
1506fcf3ce44SJohn Forte 	CkSum = SLI_CKSUM_SEED;
1507fcf3ce44SJohn Forte 
1508fcf3ce44SJohn Forte 	CkSum = (CkSum >> 1) | (CkSum << 31);
1509fcf3ce44SJohn Forte 	while (StartAddr != EndAddr) {
1510fcf3ce44SJohn Forte 		CkSum = (CkSum << 1) | (CkSum >> 31);
1511fcf3ce44SJohn Forte 		Temp = *StartAddr;
1512fcf3ce44SJohn Forte 
1513fcf3ce44SJohn Forte 		CkSum ^= Temp;
1514fcf3ce44SJohn Forte 		StartAddr++;
1515fcf3ce44SJohn Forte 	}
1516fcf3ce44SJohn Forte 
1517fcf3ce44SJohn Forte 	return (CkSum << 1) | (CkSum >> 31);
1518fcf3ce44SJohn Forte 
1519*82527734SSukumar Swaminathan } /* emlxs_valid_cksum() */
1520fcf3ce44SJohn Forte 
1521fcf3ce44SJohn Forte 
1522fcf3ce44SJohn Forte static void
1523fcf3ce44SJohn Forte emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr)
1524fcf3ce44SJohn Forte {
1525fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1526fcf3ce44SJohn Forte 
1527291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: ");
1528fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1529fcf3ce44SJohn Forte 	    "AIF Header: compress_br = 0x%x", AifHdr->CompressBr);
1530fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1531fcf3ce44SJohn Forte 	    "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr);
1532fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1533fcf3ce44SJohn Forte 	    "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr);
1534fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1535fcf3ce44SJohn Forte 	    "AIF Header: entry_br = 0x%x", AifHdr->EntryBr);
1536fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1537fcf3ce44SJohn Forte 	    "AIF Header: area_id = 0x%x", AifHdr->Area_ID);
1538fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1539fcf3ce44SJohn Forte 	    "AIF Header: rosize = 0x%x", AifHdr->RoSize);
1540fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1541fcf3ce44SJohn Forte 	    "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize);
1542fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1543fcf3ce44SJohn Forte 	    "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize);
1544fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1545fcf3ce44SJohn Forte 	    "AIF Header: dbgtype = 0x%x", AifHdr->DbgType);
1546fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1547fcf3ce44SJohn Forte 	    "AIF Header: imagebase = 0x%x", AifHdr->ImageBase);
1548fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1549fcf3ce44SJohn Forte 	    "AIF Header: area_size = 0x%x", AifHdr->Area_Size);
1550fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1551fcf3ce44SJohn Forte 	    "AIF Header: address_mode = 0x%x", AifHdr->AddressMode);
1552fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1553fcf3ce44SJohn Forte 	    "AIF Header: database = 0x%x", AifHdr->DataBase);
1554fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1555fcf3ce44SJohn Forte 	    "AIF Header: aversion = 0x%x", AifHdr->AVersion);
1556fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1557fcf3ce44SJohn Forte 	    "AIF Header: spare2 = 0x%x", AifHdr->Spare2);
1558fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1559fcf3ce44SJohn Forte 	    "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi);
1560fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1561fcf3ce44SJohn Forte 	    "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]);
1562fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1563fcf3ce44SJohn Forte 	    "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]);
1564fcf3ce44SJohn Forte 
1565*82527734SSukumar Swaminathan } /* emlxs_disp_aif_header() */
1566fcf3ce44SJohn Forte 
1567fcf3ce44SJohn Forte 
1568fcf3ce44SJohn Forte 
1569fcf3ce44SJohn Forte static void
1570fcf3ce44SJohn Forte emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image)
1571fcf3ce44SJohn Forte {
1572fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1573fcf3ce44SJohn Forte 
1574291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: ");
1575fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1576fcf3ce44SJohn Forte 	    "Img Header: BlockSize = 0x%x", image->BlockSize);
1577fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1578fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Type = 0x%x", image->Id.Type);
1579fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1580fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Id = 0x%x", image->Id.Id);
1581fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1582fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver);
1583fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1584fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev);
1585fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1586fcf3ce44SJohn Forte 	    "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp);
1587fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1588fcf3ce44SJohn Forte 	    "Img Header: Flags = 0x%x", image->Flags);
1589fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1590fcf3ce44SJohn Forte 	    "Img Header: EntryAdr = 0x%x", image->EntryAdr);
1591fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1592fcf3ce44SJohn Forte 	    "Img Header: InitAdr = 0x%x", image->InitAdr);
1593fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1594fcf3ce44SJohn Forte 	    "Img Header: ExitAdr = 0x%x", image->ExitAdr);
1595fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1596fcf3ce44SJohn Forte 	    "Img Header: ImageBase = 0x%x", image->ImageBase);
1597fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1598fcf3ce44SJohn Forte 	    "Img Header: ImageSize = 0x%x", image->ImageSize);
1599fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1600fcf3ce44SJohn Forte 	    "Img Header: ZinitSize = 0x%x", image->ZinitSize);
1601fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1602fcf3ce44SJohn Forte 	    "Img Header: RelocSize = 0x%x", image->RelocSize);
1603fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1604fcf3ce44SJohn Forte 	    "Img Header: HdrCks = 0x%x", image->HdrCks);
1605fcf3ce44SJohn Forte 
1606*82527734SSukumar Swaminathan } /* emlxs_dump_image_header() */
1607fcf3ce44SJohn Forte 
1608fcf3ce44SJohn Forte 
1609fcf3ce44SJohn Forte static void
1610*82527734SSukumar Swaminathan emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t Type,
1611*82527734SSukumar Swaminathan     uint32_t RegionId, uint32_t WordCount, uint32_t BaseAddr)
1612fcf3ce44SJohn Forte {
1613fcf3ce44SJohn Forte 
1614*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1615*82527734SSukumar Swaminathan 		MAILBOX4 *mb = (MAILBOX4 *)mbq;
1616*82527734SSukumar Swaminathan 
1617*82527734SSukumar Swaminathan 		/* Clear the local dump_region */
1618*82527734SSukumar Swaminathan 		bzero(hba->sli.sli4.dump_region.virt,
1619*82527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size);
1620*82527734SSukumar Swaminathan 
1621*82527734SSukumar Swaminathan 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1622*82527734SSukumar Swaminathan 
1623*82527734SSukumar Swaminathan 		mb->mbxCommand = MBX_DUMP_MEMORY;
1624*82527734SSukumar Swaminathan 		mb->un.varDmp4.type = Type;
1625*82527734SSukumar Swaminathan 		mb->un.varDmp4.entry_index = BaseAddr;
1626*82527734SSukumar Swaminathan 		mb->un.varDmp4.region_id = RegionId;
1627*82527734SSukumar Swaminathan 
1628*82527734SSukumar Swaminathan 		mb->un.varDmp4.available_cnt = min((WordCount*4),
1629*82527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size);
1630*82527734SSukumar Swaminathan 		mb->un.varDmp4.addrHigh =
1631*82527734SSukumar Swaminathan 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
1632*82527734SSukumar Swaminathan 		mb->un.varDmp4.addrLow =
1633*82527734SSukumar Swaminathan 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
1634*82527734SSukumar Swaminathan 		mb->un.varDmp4.rsp_cnt = 0;
1635*82527734SSukumar Swaminathan 
1636*82527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
1637*82527734SSukumar Swaminathan 
1638*82527734SSukumar Swaminathan 	} else {
1639*82527734SSukumar Swaminathan 		MAILBOX *mb = (MAILBOX *)mbq;
1640*82527734SSukumar Swaminathan 
1641*82527734SSukumar Swaminathan 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1642*82527734SSukumar Swaminathan 
1643*82527734SSukumar Swaminathan 		mb->mbxCommand = MBX_DUMP_MEMORY;
1644*82527734SSukumar Swaminathan 		mb->un.varDmp.type = Type;
1645*82527734SSukumar Swaminathan 		mb->un.varDmp.region_id = RegionId;
1646*82527734SSukumar Swaminathan 		mb->un.varDmp.word_cnt = WordCount;
1647*82527734SSukumar Swaminathan 		mb->un.varDmp.base_adr = BaseAddr;
1648*82527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
1649*82527734SSukumar Swaminathan 	}
1650*82527734SSukumar Swaminathan 
1651*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1652fcf3ce44SJohn Forte 
1653fcf3ce44SJohn Forte 	return;
1654fcf3ce44SJohn Forte 
1655*82527734SSukumar Swaminathan } /* emlxs_format_dump() */
1656fcf3ce44SJohn Forte 
1657fcf3ce44SJohn Forte 
1658fcf3ce44SJohn Forte /* ARGSUSED */
1659fcf3ce44SJohn Forte static uint32_t
1660291a2b48SSukumar Swaminathan emlxs_start_abs_download(emlxs_hba_t *hba,
1661291a2b48SSukumar Swaminathan     PAIF_HDR AifHdr,
1662291a2b48SSukumar Swaminathan     caddr_t Buffer,
1663291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS WakeUpParms,
1664291a2b48SSukumar Swaminathan     uint32_t MaxRbusSramSize,
1665fcf3ce44SJohn Forte     uint32_t MaxIbusSramSize, PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile)
1666fcf3ce44SJohn Forte {
1667fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1668fcf3ce44SJohn Forte 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
1669fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
1670fcf3ce44SJohn Forte 	uint32_t *Src;
1671fcf3ce44SJohn Forte 	uint32_t *Dst;
1672fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
1673fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
1674fcf3ce44SJohn Forte 	MAILBOX *mb;
1675fcf3ce44SJohn Forte 	uint32_t rval = 1;
1676fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
1677fcf3ce44SJohn Forte 	uint32_t DlToAddr = AifHdr->ImageBase;
1678fcf3ce44SJohn Forte 	uint32_t DlCount;
1679fcf3ce44SJohn Forte 	uint32_t i;
1680fcf3ce44SJohn Forte 
1681fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1682fcf3ce44SJohn Forte 	    "Performing absolute download...");
1683fcf3ce44SJohn Forte 
1684291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
1685291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1686fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1687fcf3ce44SJohn Forte 		    "Unable to allocate data buffer.");
1688fcf3ce44SJohn Forte 
1689fcf3ce44SJohn Forte 		return (rval);
1690fcf3ce44SJohn Forte 	}
1691291a2b48SSukumar Swaminathan 
1692291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1693291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1694fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1695fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
1696fcf3ce44SJohn Forte 
1697fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
1698fcf3ce44SJohn Forte 
1699fcf3ce44SJohn Forte 		return (rval);
1700fcf3ce44SJohn Forte 	}
1701291a2b48SSukumar Swaminathan 
1702fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
1703fcf3ce44SJohn Forte 
1704fcf3ce44SJohn Forte 	Buffer += sizeof (AIF_HDR);
1705fcf3ce44SJohn Forte 
1706291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash...");
1707fcf3ce44SJohn Forte 
1708fcf3ce44SJohn Forte 	if (DwcFile) {
1709*82527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0,
1710291a2b48SSukumar Swaminathan 		    0, 0, NULL);
1711fcf3ce44SJohn Forte 	} else {
1712*82527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount,
1713291a2b48SSukumar Swaminathan 		    ERASE_FLASH, 0, 0, 0, NULL);
1714fcf3ce44SJohn Forte 	}
1715fcf3ce44SJohn Forte 
1716*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
1717fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1718fcf3ce44SJohn Forte 		    "Unable to erase Flash: Mailbox cmd=%x status=%x",
1719fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
1720fcf3ce44SJohn Forte 
1721fcf3ce44SJohn Forte 		rval = 1;
1722fcf3ce44SJohn Forte 
1723fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
1724fcf3ce44SJohn Forte 	}
1725291a2b48SSukumar Swaminathan 
1726291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1727291a2b48SSukumar Swaminathan 	    "Programming flash...");
1728fcf3ce44SJohn Forte 
1729fcf3ce44SJohn Forte 	while (DlByteCount) {
1730fcf3ce44SJohn Forte 
1731fcf3ce44SJohn Forte 		if (DlByteCount > SegSize) {
1732fcf3ce44SJohn Forte 			DlCount = SegSize;
1733fcf3ce44SJohn Forte 		} else {
1734fcf3ce44SJohn Forte 			DlCount = DlByteCount;
1735fcf3ce44SJohn Forte 		}
1736fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
1737fcf3ce44SJohn Forte 
1738fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
1739fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
1740fcf3ce44SJohn Forte 
1741fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
1742fcf3ce44SJohn Forte 			*Dst = *Src;
1743fcf3ce44SJohn Forte 			Dst++;
1744fcf3ce44SJohn Forte 			Src++;
1745fcf3ce44SJohn Forte 		}
1746fcf3ce44SJohn Forte 
1747fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
1748*82527734SSukumar Swaminathan 		    (volatile uint32_t *)
1749*82527734SSukumar Swaminathan 		    ((volatile char *)hba->sli.sli3.slim_addr +
1750291a2b48SSukumar Swaminathan 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
1751fcf3ce44SJohn Forte 
1752*82527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, DlToAddr, DlCount,
1753291a2b48SSukumar Swaminathan 		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL);
1754fcf3ce44SJohn Forte 
1755*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
1756291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
1757fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1758fcf3ce44SJohn Forte 			    "Unable to program Flash: Mailbox cmd=%x status=%x",
1759fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
1760fcf3ce44SJohn Forte 
1761fcf3ce44SJohn Forte 			rval = 1;
1762fcf3ce44SJohn Forte 
1763fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
1764fcf3ce44SJohn Forte 		}
1765291a2b48SSukumar Swaminathan 
1766fcf3ce44SJohn Forte 		Buffer += DlCount;
1767fcf3ce44SJohn Forte 		DlToAddr += DlCount;
1768fcf3ce44SJohn Forte 	}
1769fcf3ce44SJohn Forte 
17704baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
1771*82527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
17724baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
17734baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
17744baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
17754baa2c25SSukumar Swaminathan 
17764baa2c25SSukumar Swaminathan 		rval = 1;
17774baa2c25SSukumar Swaminathan 
17784baa2c25SSukumar Swaminathan 		goto EXIT_ABS_DOWNLOAD;
17794baa2c25SSukumar Swaminathan 	}
17804baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
17814baa2c25SSukumar Swaminathan 
1782fcf3ce44SJohn Forte 	bzero((caddr_t)&ImageHdr, sizeof (IMAGE_HDR));
1783fcf3ce44SJohn Forte 	ImageHdr.Id.Type = FUNC_FIRMWARE;
1784fcf3ce44SJohn Forte 
1785fcf3ce44SJohn Forte 	switch (MaxRbusSramSize) {
1786fcf3ce44SJohn Forte 	case REDUCED_RBUS_SRAM_CFG:
1787fcf3ce44SJohn Forte 		ImageHdr.Id.Id = REDUCED_SRAM_CFG_PROG_ID;
1788fcf3ce44SJohn Forte 		break;
1789fcf3ce44SJohn Forte 	case FULL_RBUS_SRAM_CFG:
1790fcf3ce44SJohn Forte 		ImageHdr.Id.Id = FULL_SRAM_CFG_PROG_ID;
1791fcf3ce44SJohn Forte 		break;
1792fcf3ce44SJohn Forte 	default:
1793fcf3ce44SJohn Forte 		ImageHdr.Id.Id = OTHER_SRAM_CFG_PROG_ID;
1794fcf3ce44SJohn Forte 		break;
1795fcf3ce44SJohn Forte 	}
1796fcf3ce44SJohn Forte 
1797fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
1798fcf3ce44SJohn Forte 
1799fcf3ce44SJohn Forte 	if (AbsWakeUpParms) {
1800291a2b48SSukumar Swaminathan 		rval =
1801291a2b48SSukumar Swaminathan 		    emlxs_update_wakeup_parms(hba, AbsWakeUpParms,
1802fcf3ce44SJohn Forte 		    WakeUpParms);
1803fcf3ce44SJohn Forte 	} else {
1804291a2b48SSukumar Swaminathan 		rval =
1805291a2b48SSukumar Swaminathan 		    emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
1806fcf3ce44SJohn Forte 		    &ImageHdr.Id, 1);
1807fcf3ce44SJohn Forte 	}
1808fcf3ce44SJohn Forte 
1809fcf3ce44SJohn Forte EXIT_ABS_DOWNLOAD:
1810fcf3ce44SJohn Forte 	if (DataBuffer) {
1811fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
1812fcf3ce44SJohn Forte 	}
1813291a2b48SSukumar Swaminathan 
1814fcf3ce44SJohn Forte 	if (mbox) {
1815fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
1816fcf3ce44SJohn Forte 	}
1817291a2b48SSukumar Swaminathan 
1818fcf3ce44SJohn Forte 	return (rval);
1819fcf3ce44SJohn Forte 
1820*82527734SSukumar Swaminathan } /* emlxs_start_abs_download() */
1821fcf3ce44SJohn Forte 
1822fcf3ce44SJohn Forte 
1823fcf3ce44SJohn Forte /* ARGSUSED */
1824fcf3ce44SJohn Forte static void
1825*82527734SSukumar Swaminathan emlxs_format_prog_flash(MAILBOXQ *mbq,
1826291a2b48SSukumar Swaminathan     uint32_t Base,
1827291a2b48SSukumar Swaminathan     uint32_t DlByteCount,
1828291a2b48SSukumar Swaminathan     uint32_t Function,
1829291a2b48SSukumar Swaminathan     uint32_t Complete,
1830291a2b48SSukumar Swaminathan     uint32_t BdeAddress, uint32_t BdeSize, PROG_ID *ProgId)
1831fcf3ce44SJohn Forte {
1832*82527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
1833*82527734SSukumar Swaminathan 
1834291a2b48SSukumar Swaminathan 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1835fcf3ce44SJohn Forte 
1836fcf3ce44SJohn Forte 	if (ProgId)
1837fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_DOWN_LOAD;
1838fcf3ce44SJohn Forte 	else
1839fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_SM;
1840fcf3ce44SJohn Forte 
1841fcf3ce44SJohn Forte 	mb->un.varLdSM.load_cmplt = Complete;
1842fcf3ce44SJohn Forte 	mb->un.varLdSM.method = DL_FROM_SLIM;
1843fcf3ce44SJohn Forte 	mb->un.varLdSM.update_flash = 1;
1844fcf3ce44SJohn Forte 	mb->un.varLdSM.erase_or_prog = Function;
1845fcf3ce44SJohn Forte 	mb->un.varLdSM.dl_to_adr = Base;
1846fcf3ce44SJohn Forte 	mb->un.varLdSM.dl_len = DlByteCount;
1847fcf3ce44SJohn Forte 
1848fcf3ce44SJohn Forte 	if (BdeSize) {
1849fcf3ce44SJohn Forte 		mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
1850fcf3ce44SJohn Forte 	} else if (ProgId) {
1851fcf3ce44SJohn Forte 		mb->un.varLdSM.un.prog_id = *ProgId;
1852fcf3ce44SJohn Forte 	} else {
1853fcf3ce44SJohn Forte 		mb->un.varLdSM.un.dl_from_slim_offset = 0;
1854fcf3ce44SJohn Forte 	}
1855fcf3ce44SJohn Forte 
1856fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
1857*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
1858fcf3ce44SJohn Forte 
1859*82527734SSukumar Swaminathan } /* emlxs_format_prog_flash() */
1860fcf3ce44SJohn Forte 
1861fcf3ce44SJohn Forte 
1862fcf3ce44SJohn Forte static void
1863*82527734SSukumar Swaminathan emlxs_format_update_parms(MAILBOXQ *mbq, PWAKE_UP_PARMS WakeUpParms)
1864fcf3ce44SJohn Forte {
1865*82527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
1866*82527734SSukumar Swaminathan 
1867fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1868fcf3ce44SJohn Forte 
1869fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UPDATE_CFG;
1870fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
1871fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID;
1872fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS);
1873fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS);
1874fcf3ce44SJohn Forte 
1875291a2b48SSukumar Swaminathan 	bcopy((caddr_t)WakeUpParms,
1876291a2b48SSukumar Swaminathan 	    (caddr_t)&(mb->un.varUpdateCfg.cfg_data),
1877fcf3ce44SJohn Forte 	    sizeof (WAKE_UP_PARMS));
1878*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
1879fcf3ce44SJohn Forte 
1880*82527734SSukumar Swaminathan } /* emlxs_format_update_parms () */
1881fcf3ce44SJohn Forte 
1882fcf3ce44SJohn Forte 
1883fcf3ce44SJohn Forte /* ARGSUSED */
1884fcf3ce44SJohn Forte static void
1885*82527734SSukumar Swaminathan emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
1886fcf3ce44SJohn Forte     uint32_t region_id, uint32_t size)
1887fcf3ce44SJohn Forte {
1888*82527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
1889*82527734SSukumar Swaminathan 
1890fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1891fcf3ce44SJohn Forte 
1892fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UPDATE_CFG;
1893fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.Vbit = 1;
1894fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.Obit = 1;
1895fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET;
1896fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
1897fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.region_id = region_id;
1898fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.entry_len = size;
1899fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.byte_len = size;
1900*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
1901fcf3ce44SJohn Forte 
1902*82527734SSukumar Swaminathan } /* emlxs_format_update_pci_cfg() */
1903fcf3ce44SJohn Forte 
1904fcf3ce44SJohn Forte 
1905fcf3ce44SJohn Forte 
1906fcf3ce44SJohn Forte static uint32_t
1907fcf3ce44SJohn Forte emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1908fcf3ce44SJohn Forte     PROG_ID * prog_id, uint32_t proc_erom)
1909fcf3ce44SJohn Forte {
1910fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1911fcf3ce44SJohn Forte 	MAILBOX *mb;
1912fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
1913fcf3ce44SJohn Forte 	uint32_t rval = 0;
1914fcf3ce44SJohn Forte 
1915291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1916291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1917fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1918fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
1919fcf3ce44SJohn Forte 
1920fcf3ce44SJohn Forte 		return (1);
1921fcf3ce44SJohn Forte 	}
1922fcf3ce44SJohn Forte 
1923291a2b48SSukumar Swaminathan 	mb = (MAILBOX *)mbox;
1924291a2b48SSukumar Swaminathan 
1925291a2b48SSukumar Swaminathan 	if (proc_erom && !(hba->model_info.chip &
1926fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
1927fcf3ce44SJohn Forte 		WakeUpParms->u1.EROM_prog_id = *prog_id;
1928fcf3ce44SJohn Forte 		(void) emlxs_update_exp_rom(hba, WakeUpParms);
1929fcf3ce44SJohn Forte 	}
1930291a2b48SSukumar Swaminathan 
1931fcf3ce44SJohn Forte 	WakeUpParms->u0.boot_bios_id = *prog_id;
1932fcf3ce44SJohn Forte 
1933*82527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
1934fcf3ce44SJohn Forte 
1935*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
1936fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1937291a2b48SSukumar Swaminathan 		    "Unable to update boot wakeup parms: Mailbox cmd=%x "
1938291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
1939fcf3ce44SJohn Forte 
1940fcf3ce44SJohn Forte 		rval = 1;
1941fcf3ce44SJohn Forte 	}
1942291a2b48SSukumar Swaminathan 
1943fcf3ce44SJohn Forte 	if (mbox) {
1944fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
1945fcf3ce44SJohn Forte 	}
1946291a2b48SSukumar Swaminathan 
1947fcf3ce44SJohn Forte 	return (rval);
1948fcf3ce44SJohn Forte 
1949*82527734SSukumar Swaminathan } /* emlxs_update_boot_wakeup_parms() */
1950fcf3ce44SJohn Forte 
1951fcf3ce44SJohn Forte 
1952fcf3ce44SJohn Forte 
1953fcf3ce44SJohn Forte static uint32_t
1954fcf3ce44SJohn Forte emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1955fcf3ce44SJohn Forte     PROG_ID *prog_id)
1956fcf3ce44SJohn Forte {
1957fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1958fcf3ce44SJohn Forte 	uint32_t rval = 0;
1959fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
1960fcf3ce44SJohn Forte 	MAILBOX *mb;
1961fcf3ce44SJohn Forte 
1962291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1963291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
1964fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1965fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
1966fcf3ce44SJohn Forte 
1967fcf3ce44SJohn Forte 		return (1);
1968fcf3ce44SJohn Forte 	}
1969291a2b48SSukumar Swaminathan 
1970fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
1971fcf3ce44SJohn Forte 
1972fcf3ce44SJohn Forte 	WakeUpParms->prog_id = *prog_id;
1973fcf3ce44SJohn Forte 
1974*82527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
1975fcf3ce44SJohn Forte 
1976*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
1977fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1978291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
1979291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
1980fcf3ce44SJohn Forte 
1981fcf3ce44SJohn Forte 		rval = 1;
1982fcf3ce44SJohn Forte 	}
1983291a2b48SSukumar Swaminathan 
1984fcf3ce44SJohn Forte 	if (mbox) {
1985fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
1986fcf3ce44SJohn Forte 	}
1987291a2b48SSukumar Swaminathan 
1988fcf3ce44SJohn Forte 	return (rval);
1989fcf3ce44SJohn Forte 
1990*82527734SSukumar Swaminathan } /* emlxs_update_ff_wakeup_parms() */
1991fcf3ce44SJohn Forte 
1992fcf3ce44SJohn Forte 
1993fcf3ce44SJohn Forte static uint32_t
1994fcf3ce44SJohn Forte emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
1995291a2b48SSukumar Swaminathan     PROG_ID * prog_id)
1996fcf3ce44SJohn Forte {
1997fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1998fcf3ce44SJohn Forte 	uint32_t rval = 0;
1999fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2000fcf3ce44SJohn Forte 	MAILBOX *mb;
2001fcf3ce44SJohn Forte 
2002291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2003291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2004fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2005fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2006fcf3ce44SJohn Forte 
2007fcf3ce44SJohn Forte 		return (1);
2008fcf3ce44SJohn Forte 	}
2009291a2b48SSukumar Swaminathan 
2010fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2011fcf3ce44SJohn Forte 
2012fcf3ce44SJohn Forte 	WakeUpParms->sli1_prog_id = *prog_id;
2013fcf3ce44SJohn Forte 
2014*82527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2015fcf3ce44SJohn Forte 
2016*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2017fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2018291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2019291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2020fcf3ce44SJohn Forte 
2021fcf3ce44SJohn Forte 		rval = 1;
2022fcf3ce44SJohn Forte 	}
2023291a2b48SSukumar Swaminathan 
2024fcf3ce44SJohn Forte 	if (mbox) {
2025fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2026fcf3ce44SJohn Forte 	}
2027291a2b48SSukumar Swaminathan 
2028fcf3ce44SJohn Forte 	return (rval);
2029fcf3ce44SJohn Forte 
2030*82527734SSukumar Swaminathan } /* emlxs_update_sli1_wakeup_parms() */
2031fcf3ce44SJohn Forte 
2032fcf3ce44SJohn Forte 
2033fcf3ce44SJohn Forte static uint32_t
2034fcf3ce44SJohn Forte emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2035291a2b48SSukumar Swaminathan     PROG_ID * prog_id)
2036fcf3ce44SJohn Forte {
2037fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2038fcf3ce44SJohn Forte 	uint32_t rval = 0;
2039fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2040fcf3ce44SJohn Forte 	MAILBOX *mb;
2041fcf3ce44SJohn Forte 
2042291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2043291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2044fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2045fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2046fcf3ce44SJohn Forte 
2047fcf3ce44SJohn Forte 		return (1);
2048fcf3ce44SJohn Forte 	}
2049291a2b48SSukumar Swaminathan 
2050fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2051fcf3ce44SJohn Forte 
2052fcf3ce44SJohn Forte 	WakeUpParms->sli2_prog_id = *prog_id;
2053fcf3ce44SJohn Forte 
2054*82527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2055fcf3ce44SJohn Forte 
2056*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2057fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2058291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2059291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2060fcf3ce44SJohn Forte 
2061fcf3ce44SJohn Forte 		rval = 1;
2062fcf3ce44SJohn Forte 	}
2063291a2b48SSukumar Swaminathan 
2064fcf3ce44SJohn Forte 	if (mbox) {
2065fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2066fcf3ce44SJohn Forte 	}
2067291a2b48SSukumar Swaminathan 
2068fcf3ce44SJohn Forte 	return (rval);
2069fcf3ce44SJohn Forte 
2070*82527734SSukumar Swaminathan } /* emlxs_update_sli2_wakeup_parms() */
2071fcf3ce44SJohn Forte 
2072fcf3ce44SJohn Forte 
2073fcf3ce44SJohn Forte static uint32_t
2074fcf3ce44SJohn Forte emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2075fcf3ce44SJohn Forte     PROG_ID *prog_id)
2076fcf3ce44SJohn Forte {
2077fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2078fcf3ce44SJohn Forte 	uint32_t rval = 0;
2079fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2080fcf3ce44SJohn Forte 	MAILBOX *mb;
2081fcf3ce44SJohn Forte 
2082291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2083291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2084fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2085fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2086fcf3ce44SJohn Forte 
2087fcf3ce44SJohn Forte 		return (1);
2088fcf3ce44SJohn Forte 	}
2089291a2b48SSukumar Swaminathan 
2090fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2091fcf3ce44SJohn Forte 
2092fcf3ce44SJohn Forte 	WakeUpParms->sli3_prog_id = *prog_id;
2093fcf3ce44SJohn Forte 
2094*82527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2095fcf3ce44SJohn Forte 
2096*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2097fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2098291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2099291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2100fcf3ce44SJohn Forte 
2101fcf3ce44SJohn Forte 		rval = 1;
2102fcf3ce44SJohn Forte 	}
2103291a2b48SSukumar Swaminathan 
2104fcf3ce44SJohn Forte 	if (mbox) {
2105fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2106fcf3ce44SJohn Forte 	}
2107291a2b48SSukumar Swaminathan 
2108fcf3ce44SJohn Forte 	return (rval);
2109fcf3ce44SJohn Forte 
2110*82527734SSukumar Swaminathan } /* emlxs_update_sli3_wakeup_parms() */
2111fcf3ce44SJohn Forte 
2112fcf3ce44SJohn Forte 
2113fcf3ce44SJohn Forte static uint32_t
2114fcf3ce44SJohn Forte emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2115fcf3ce44SJohn Forte     PROG_ID *prog_id)
2116fcf3ce44SJohn Forte {
2117fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2118fcf3ce44SJohn Forte 	uint32_t rval = 0;
2119fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2120fcf3ce44SJohn Forte 	MAILBOX *mb;
2121fcf3ce44SJohn Forte 
2122291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2123291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2124fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2125fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2126fcf3ce44SJohn Forte 
2127fcf3ce44SJohn Forte 		return (1);
2128fcf3ce44SJohn Forte 	}
2129291a2b48SSukumar Swaminathan 
2130fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2131fcf3ce44SJohn Forte 
2132fcf3ce44SJohn Forte 	WakeUpParms->sli4_prog_id = *prog_id;
2133fcf3ce44SJohn Forte 
2134*82527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2135fcf3ce44SJohn Forte 
2136*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2137fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2138291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2139291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2140fcf3ce44SJohn Forte 
2141fcf3ce44SJohn Forte 		rval = 1;
2142fcf3ce44SJohn Forte 	}
2143291a2b48SSukumar Swaminathan 
2144fcf3ce44SJohn Forte 	if (mbox) {
2145fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2146fcf3ce44SJohn Forte 	}
2147291a2b48SSukumar Swaminathan 
2148fcf3ce44SJohn Forte 	return (rval);
2149fcf3ce44SJohn Forte 
2150*82527734SSukumar Swaminathan } /* emlxs_update_sli4_wakeup_parms() */
2151fcf3ce44SJohn Forte 
2152fcf3ce44SJohn Forte 
2153fcf3ce44SJohn Forte /* ARGSUSED */
2154fcf3ce44SJohn Forte static uint32_t
2155291a2b48SSukumar Swaminathan emlxs_start_rel_download(emlxs_hba_t *hba,
2156291a2b48SSukumar Swaminathan     PIMAGE_HDR ImageHdr,
2157291a2b48SSukumar Swaminathan     caddr_t Buffer,
2158291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS WakeUpParms,
2159fcf3ce44SJohn Forte     uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize)
2160fcf3ce44SJohn Forte {
2161fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2162fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2163fcf3ce44SJohn Forte 	MAILBOX *mb;
2164fcf3ce44SJohn Forte 	uint32_t *Src;
2165fcf3ce44SJohn Forte 	uint32_t *Dst;
2166fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
2167fcf3ce44SJohn Forte 	uint32_t rval = 1;
2168fcf3ce44SJohn Forte 	uint32_t DlByteCount = ImageHdr->BlockSize;
2169fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
2170fcf3ce44SJohn Forte 	uint32_t DlCount;
2171fcf3ce44SJohn Forte 	uint32_t i;
2172fcf3ce44SJohn Forte 
2173fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2174fcf3ce44SJohn Forte 	    "Performing relative download...");
2175fcf3ce44SJohn Forte 
2176291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
2177291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2178fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2179fcf3ce44SJohn Forte 		    "Unable to allocate data buffer.");
2180fcf3ce44SJohn Forte 
2181fcf3ce44SJohn Forte 		return (rval);
2182fcf3ce44SJohn Forte 	}
2183291a2b48SSukumar Swaminathan 
2184291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2185291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2186fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2187fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2188fcf3ce44SJohn Forte 
2189fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2190fcf3ce44SJohn Forte 
2191fcf3ce44SJohn Forte 		return (rval);
2192fcf3ce44SJohn Forte 	}
2193291a2b48SSukumar Swaminathan 
2194fcf3ce44SJohn Forte 	if (ImageHdr->Id.Type == FUNC_FIRMWARE) {
2195fcf3ce44SJohn Forte 		switch (MaxRbusSramSize) {
2196fcf3ce44SJohn Forte 		case REDUCED_RBUS_SRAM_CFG:
2197fcf3ce44SJohn Forte 			if (ImageHdr->Id.Id != REDUCED_SRAM_CFG_PROG_ID) {
2198291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2199291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
2200fcf3ce44SJohn Forte 				    "Invalid header id.");
2201fcf3ce44SJohn Forte 
2202fcf3ce44SJohn Forte 				return (1);
2203fcf3ce44SJohn Forte 			}
2204fcf3ce44SJohn Forte 			break;
2205fcf3ce44SJohn Forte 		case FULL_RBUS_SRAM_CFG:
2206fcf3ce44SJohn Forte 			if (ImageHdr->Id.Id != FULL_SRAM_CFG_PROG_ID) {
2207291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2208291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
2209fcf3ce44SJohn Forte 				    "Invalid header id.");
2210fcf3ce44SJohn Forte 
2211fcf3ce44SJohn Forte 				return (1);
2212fcf3ce44SJohn Forte 			}
2213fcf3ce44SJohn Forte 			break;
2214fcf3ce44SJohn Forte 		default:
2215fcf3ce44SJohn Forte 			if (ImageHdr->Id.Id != OTHER_SRAM_CFG_PROG_ID) {
2216291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2217291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
2218fcf3ce44SJohn Forte 				    "Invalid header id.");
2219fcf3ce44SJohn Forte 
2220fcf3ce44SJohn Forte 				return (1);
2221fcf3ce44SJohn Forte 			}
2222fcf3ce44SJohn Forte 			break;
2223fcf3ce44SJohn Forte 		}
2224fcf3ce44SJohn Forte 	}
2225291a2b48SSukumar Swaminathan 
2226fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2227fcf3ce44SJohn Forte 
2228*82527734SSukumar Swaminathan 	emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
2229291a2b48SSukumar Swaminathan 	    &ImageHdr->Id);
2230fcf3ce44SJohn Forte 
2231fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash...");
2232fcf3ce44SJohn Forte 
2233*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2234fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2235fcf3ce44SJohn Forte 		    "Unable to erase flash. Mailbox cmd=%x status=%x",
2236fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
2237fcf3ce44SJohn Forte 
2238fcf3ce44SJohn Forte 		rval = 1;
2239fcf3ce44SJohn Forte 
2240fcf3ce44SJohn Forte 		goto EXIT_REL_DOWNLOAD;
2241fcf3ce44SJohn Forte 	}
2242291a2b48SSukumar Swaminathan 
2243291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2244291a2b48SSukumar Swaminathan 	    "Programming flash...");
2245fcf3ce44SJohn Forte 
2246fcf3ce44SJohn Forte 	while (DlByteCount) {
2247fcf3ce44SJohn Forte 		if (DlByteCount > SegSize) {
2248fcf3ce44SJohn Forte 			DlCount = SegSize;
2249fcf3ce44SJohn Forte 		} else {
2250fcf3ce44SJohn Forte 			DlCount = DlByteCount;
2251fcf3ce44SJohn Forte 		}
2252fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
2253fcf3ce44SJohn Forte 
2254fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
2255fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
2256fcf3ce44SJohn Forte 
2257fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
2258fcf3ce44SJohn Forte 			*Dst = *Src;
2259fcf3ce44SJohn Forte 			Dst++;
2260fcf3ce44SJohn Forte 			Src++;
2261fcf3ce44SJohn Forte 		}
2262fcf3ce44SJohn Forte 
2263fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
2264*82527734SSukumar Swaminathan 		    (volatile uint32_t *)
2265*82527734SSukumar Swaminathan 		    ((volatile char *)hba->sli.sli3.slim_addr +
2266291a2b48SSukumar Swaminathan 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2267fcf3ce44SJohn Forte 
2268*82527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox,
2269291a2b48SSukumar Swaminathan 		    0,
2270291a2b48SSukumar Swaminathan 		    DlCount,
2271291a2b48SSukumar Swaminathan 		    PROGRAM_FLASH,
2272fcf3ce44SJohn Forte 		    (DlByteCount) ? 0 : 1, 0, DlCount, &ImageHdr->Id);
2273fcf3ce44SJohn Forte 
2274*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2275291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
2276fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2277fcf3ce44SJohn Forte 			    "Unable to program flash. Mailbox cmd=%x status=%x",
2278fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
2279fcf3ce44SJohn Forte 
2280fcf3ce44SJohn Forte 			rval = 1;
2281fcf3ce44SJohn Forte 
2282fcf3ce44SJohn Forte 			goto EXIT_REL_DOWNLOAD;
2283fcf3ce44SJohn Forte 		}
2284291a2b48SSukumar Swaminathan 
2285fcf3ce44SJohn Forte 		Buffer += DlCount;
2286fcf3ce44SJohn Forte 	}
2287fcf3ce44SJohn Forte 
22884baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
2289*82527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
22904baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
22914baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
22924baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
22934baa2c25SSukumar Swaminathan 
22944baa2c25SSukumar Swaminathan 		rval = 1;
22954baa2c25SSukumar Swaminathan 
22964baa2c25SSukumar Swaminathan 		goto EXIT_REL_DOWNLOAD;
22974baa2c25SSukumar Swaminathan 	}
22984baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
22994baa2c25SSukumar Swaminathan 
2300fcf3ce44SJohn Forte 	switch (ImageHdr->Id.Type) {
2301fcf3ce44SJohn Forte 	case TEST_PROGRAM:
2302fcf3ce44SJohn Forte 		rval = 0;
2303fcf3ce44SJohn Forte 		break;
2304fcf3ce44SJohn Forte 
2305fcf3ce44SJohn Forte 	case FUNC_FIRMWARE:
2306fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2307fcf3ce44SJohn Forte 		    "FF: Updating parms...");
2308291a2b48SSukumar Swaminathan 		rval =
2309291a2b48SSukumar Swaminathan 		    emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
2310fcf3ce44SJohn Forte 		    &ImageHdr->Id);
2311fcf3ce44SJohn Forte 		break;
2312fcf3ce44SJohn Forte 
2313fcf3ce44SJohn Forte 	case BOOT_BIOS:
2314fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2315fcf3ce44SJohn Forte 		    "BOOT: Updating parms...");
2316291a2b48SSukumar Swaminathan 		rval =
2317291a2b48SSukumar Swaminathan 		    emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
2318fcf3ce44SJohn Forte 		    &ImageHdr->Id, 1);
2319fcf3ce44SJohn Forte 		break;
2320fcf3ce44SJohn Forte 
2321fcf3ce44SJohn Forte 	case SLI1_OVERLAY:
2322fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2323fcf3ce44SJohn Forte 		    "SLI1: Updating parms...");
2324291a2b48SSukumar Swaminathan 		rval =
2325291a2b48SSukumar Swaminathan 		    emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
2326fcf3ce44SJohn Forte 		    &ImageHdr->Id);
2327fcf3ce44SJohn Forte 		break;
2328fcf3ce44SJohn Forte 
2329fcf3ce44SJohn Forte 	case SLI2_OVERLAY:
2330fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2331fcf3ce44SJohn Forte 		    "SLI2: Updating parms...");
2332291a2b48SSukumar Swaminathan 		rval =
2333291a2b48SSukumar Swaminathan 		    emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
2334fcf3ce44SJohn Forte 		    &ImageHdr->Id);
2335fcf3ce44SJohn Forte 		break;
2336fcf3ce44SJohn Forte 
2337fcf3ce44SJohn Forte 	case SLI3_OVERLAY:
2338fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2339fcf3ce44SJohn Forte 		    "SLI3: Updating parms...");
2340291a2b48SSukumar Swaminathan 		rval =
2341291a2b48SSukumar Swaminathan 		    emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
2342fcf3ce44SJohn Forte 		    &ImageHdr->Id);
2343fcf3ce44SJohn Forte 		break;
2344fcf3ce44SJohn Forte 
2345fcf3ce44SJohn Forte 	case SLI4_OVERLAY:
2346fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2347fcf3ce44SJohn Forte 		    "SLI4: Updating parms...");
2348291a2b48SSukumar Swaminathan 		rval =
2349291a2b48SSukumar Swaminathan 		    emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
2350fcf3ce44SJohn Forte 		    &ImageHdr->Id);
2351fcf3ce44SJohn Forte 		break;
2352fcf3ce44SJohn Forte 
2353fcf3ce44SJohn Forte 	default:
2354fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2355291a2b48SSukumar Swaminathan 		    "Image type not supported. Type=%x", ImageHdr->Id.Type);
2356fcf3ce44SJohn Forte 
2357fcf3ce44SJohn Forte 		break;
2358fcf3ce44SJohn Forte 	}
2359fcf3ce44SJohn Forte 
2360fcf3ce44SJohn Forte EXIT_REL_DOWNLOAD:
2361fcf3ce44SJohn Forte 	if (DataBuffer) {
2362fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2363fcf3ce44SJohn Forte 	}
2364291a2b48SSukumar Swaminathan 
2365fcf3ce44SJohn Forte 	if (mbox) {
2366fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2367fcf3ce44SJohn Forte 	}
2368291a2b48SSukumar Swaminathan 
2369fcf3ce44SJohn Forte 	return (rval);
2370fcf3ce44SJohn Forte 
2371*82527734SSukumar Swaminathan } /* emlxs_start_rel_download() */
2372fcf3ce44SJohn Forte 
2373fcf3ce44SJohn Forte 
2374fcf3ce44SJohn Forte #define	FLASH_POLLING_BIT	0x80
2375fcf3ce44SJohn Forte #define	FLASH_ERROR_BIT		0x20
2376fcf3ce44SJohn Forte 
2377291a2b48SSukumar Swaminathan typedef struct _flash_t
2378291a2b48SSukumar Swaminathan {
2379291a2b48SSukumar Swaminathan 	uint32_t	offset;
2380291a2b48SSukumar Swaminathan 	uint8_t		val;
2381fcf3ce44SJohn Forte } flash_t;
2382fcf3ce44SJohn Forte 
2383fcf3ce44SJohn Forte 
2384fcf3ce44SJohn Forte 
2385fcf3ce44SJohn Forte static uint32_t
2386291a2b48SSukumar Swaminathan emlxs_write_fcode_flash(emlxs_hba_t *hba,
2387291a2b48SSukumar Swaminathan     PIMAGE_HDR ImageHdr, caddr_t Buffer)
2388fcf3ce44SJohn Forte {
2389fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2390fcf3ce44SJohn Forte 	uint8_t bb;
2391fcf3ce44SJohn Forte 	uint8_t cc;
2392fcf3ce44SJohn Forte 	uint8_t *src;
2393fcf3ce44SJohn Forte 	uint32_t DlByteCount = ImageHdr->BlockSize;
2394fcf3ce44SJohn Forte 	uint32_t i;
2395fcf3ce44SJohn Forte 	uint32_t j;
2396fcf3ce44SJohn Forte 	uint32_t k;
2397fcf3ce44SJohn Forte 
2398291a2b48SSukumar Swaminathan 	flash_t wr[3] = {
2399fcf3ce44SJohn Forte 		{0x555, 0xaa},
2400fcf3ce44SJohn Forte 		{0x2aa, 0x55},
2401fcf3ce44SJohn Forte 		{0x555, 0xa0}
2402fcf3ce44SJohn Forte 	};
2403fcf3ce44SJohn Forte 
2404fcf3ce44SJohn Forte 	/* Load Fcode */
2405fcf3ce44SJohn Forte 	src = (uint8_t *)Buffer + sizeof (IMAGE_HDR);
2406fcf3ce44SJohn Forte 	for (i = 0; i < DlByteCount; i++) {
2407fcf3ce44SJohn Forte 		for (k = 0; k < 3; k++) {
2408fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
2409fcf3ce44SJohn Forte 		}
2410fcf3ce44SJohn Forte 
2411fcf3ce44SJohn Forte 		/* Reverse Endian word alignment */
2412fcf3ce44SJohn Forte 		j = (i & 3) ^ 3;
2413fcf3ce44SJohn Forte 
2414fcf3ce44SJohn Forte 		bb = src[j];
2415fcf3ce44SJohn Forte 
2416fcf3ce44SJohn Forte 		if (j == 0) {
2417fcf3ce44SJohn Forte 			src += 4;
2418fcf3ce44SJohn Forte 		}
2419291a2b48SSukumar Swaminathan 
2420fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
2421fcf3ce44SJohn Forte 
2422fcf3ce44SJohn Forte 		/* check for complete */
2423fcf3ce44SJohn Forte 		for (;;) {
2424fcf3ce44SJohn Forte 			DELAYUS(20);
2425fcf3ce44SJohn Forte 
2426fcf3ce44SJohn Forte 			cc = SBUS_READ_FLASH_COPY(hba, i);
2427fcf3ce44SJohn Forte 
2428fcf3ce44SJohn Forte 			/* If data matches then continue */
2429fcf3ce44SJohn Forte 			if (cc == bb) {
2430fcf3ce44SJohn Forte 				break;
2431fcf3ce44SJohn Forte 			}
2432291a2b48SSukumar Swaminathan 
2433291a2b48SSukumar Swaminathan 			/* Polling bit will be inverse final value */
2434291a2b48SSukumar Swaminathan 			/* while active */
2435fcf3ce44SJohn Forte 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
2436fcf3ce44SJohn Forte 				/* Still busy */
2437fcf3ce44SJohn Forte 
2438fcf3ce44SJohn Forte 				/* Check for error bit */
2439fcf3ce44SJohn Forte 				if (cc & FLASH_ERROR_BIT) {
2440fcf3ce44SJohn Forte 					/* Read data one more time */
2441fcf3ce44SJohn Forte 					cc = SBUS_READ_FLASH_COPY(hba, i);
2442fcf3ce44SJohn Forte 
2443fcf3ce44SJohn Forte 					/* Check if data matches */
2444fcf3ce44SJohn Forte 					if (cc == bb) {
2445fcf3ce44SJohn Forte 						break;
2446fcf3ce44SJohn Forte 					}
2447291a2b48SSukumar Swaminathan 
2448fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2449fcf3ce44SJohn Forte 					    &emlxs_download_failed_msg,
2450fcf3ce44SJohn Forte 					    "FCode write error: offset:%x "
2451291a2b48SSukumar Swaminathan 					    "wrote:%x read:%x\n", i, bb, cc);
2452fcf3ce44SJohn Forte 
2453fcf3ce44SJohn Forte 					return (1);
2454fcf3ce44SJohn Forte 				}
2455fcf3ce44SJohn Forte 			}
2456fcf3ce44SJohn Forte 		}
2457fcf3ce44SJohn Forte 	}
2458fcf3ce44SJohn Forte 
2459fcf3ce44SJohn Forte 	/* Load Header */
2460fcf3ce44SJohn Forte 	src = (uint8_t *)ImageHdr;
2461fcf3ce44SJohn Forte 
2462fcf3ce44SJohn Forte 	for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) {
2463fcf3ce44SJohn Forte 		for (k = 0; k < 3; k++) {
2464fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
2465fcf3ce44SJohn Forte 		}
2466fcf3ce44SJohn Forte 
2467fcf3ce44SJohn Forte 		/* Reverse Endian word alignment */
2468fcf3ce44SJohn Forte 		j = (i & 3) ^ 3;
2469fcf3ce44SJohn Forte 
2470fcf3ce44SJohn Forte 		bb = src[j];
2471fcf3ce44SJohn Forte 
2472fcf3ce44SJohn Forte 		if (j == 0) {
2473fcf3ce44SJohn Forte 			src += 4;
2474fcf3ce44SJohn Forte 		}
2475291a2b48SSukumar Swaminathan 
2476fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
2477fcf3ce44SJohn Forte 
2478fcf3ce44SJohn Forte 		/* check for complete */
2479fcf3ce44SJohn Forte 		for (;;) {
2480fcf3ce44SJohn Forte 			DELAYUS(20);
2481fcf3ce44SJohn Forte 
2482fcf3ce44SJohn Forte 			cc = SBUS_READ_FLASH_COPY(hba, i);
2483fcf3ce44SJohn Forte 
2484fcf3ce44SJohn Forte 			/* If data matches then continue */
2485fcf3ce44SJohn Forte 			if (cc == bb) {
2486fcf3ce44SJohn Forte 				break;
2487fcf3ce44SJohn Forte 			}
2488291a2b48SSukumar Swaminathan 
2489291a2b48SSukumar Swaminathan 			/* Polling bit will be inverse final value */
2490291a2b48SSukumar Swaminathan 			/* while active */
2491fcf3ce44SJohn Forte 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
2492fcf3ce44SJohn Forte 				/* Still busy */
2493fcf3ce44SJohn Forte 
2494fcf3ce44SJohn Forte 				/* Check for error bit */
2495fcf3ce44SJohn Forte 				if (cc & FLASH_ERROR_BIT) {
2496fcf3ce44SJohn Forte 					/* Read data one more time */
2497fcf3ce44SJohn Forte 					cc = SBUS_READ_FLASH_COPY(hba, i);
2498fcf3ce44SJohn Forte 
2499fcf3ce44SJohn Forte 					/* Check if data matches */
2500fcf3ce44SJohn Forte 					if (cc == bb) {
2501fcf3ce44SJohn Forte 						break;
2502fcf3ce44SJohn Forte 					}
2503291a2b48SSukumar Swaminathan 
2504fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
2505fcf3ce44SJohn Forte 					    &emlxs_download_failed_msg,
2506fcf3ce44SJohn Forte 					    "FCode write error: offset:%x "
2507291a2b48SSukumar Swaminathan 					    "wrote:%x read:%x\n", i, bb, cc);
2508fcf3ce44SJohn Forte 
2509fcf3ce44SJohn Forte 					return (1);
2510fcf3ce44SJohn Forte 				}
2511fcf3ce44SJohn Forte 			}
2512fcf3ce44SJohn Forte 		}
2513fcf3ce44SJohn Forte 	}
2514fcf3ce44SJohn Forte 
25154baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
2516*82527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
25174baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
25184baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
25194baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
25204baa2c25SSukumar Swaminathan 		return (1);
25214baa2c25SSukumar Swaminathan 	}
25224baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
2523291a2b48SSukumar Swaminathan 
2524fcf3ce44SJohn Forte 	return (0);
2525fcf3ce44SJohn Forte 
2526*82527734SSukumar Swaminathan } /* emlxs_write_fcode_flash() */
2527fcf3ce44SJohn Forte 
2528fcf3ce44SJohn Forte 
2529fcf3ce44SJohn Forte 
2530fcf3ce44SJohn Forte static uint32_t
2531fcf3ce44SJohn Forte emlxs_erase_fcode_flash(emlxs_hba_t *hba)
2532fcf3ce44SJohn Forte {
2533fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2534fcf3ce44SJohn Forte 	int32_t i, j;
2535fcf3ce44SJohn Forte 	uint8_t cc;
2536fcf3ce44SJohn Forte 	uint32_t offset;
2537fcf3ce44SJohn Forte 
2538291a2b48SSukumar Swaminathan 	flash_t ef[6] = {
2539fcf3ce44SJohn Forte 		{0x555, 0xaa},
2540fcf3ce44SJohn Forte 		{0x2aa, 0x55},
2541fcf3ce44SJohn Forte 		{0x555, 0x80},
2542fcf3ce44SJohn Forte 		{0x555, 0xaa},
2543fcf3ce44SJohn Forte 		{0x2aa, 0x55},
2544fcf3ce44SJohn Forte 		{0x555, 0x10}
2545fcf3ce44SJohn Forte 	};
2546fcf3ce44SJohn Forte 
2547fcf3ce44SJohn Forte 	/* Auto select */
2548291a2b48SSukumar Swaminathan 	flash_t as[3] = {
2549fcf3ce44SJohn Forte 		{0x555, 0xaa},
2550fcf3ce44SJohn Forte 		{0x2aa, 0x55},
2551fcf3ce44SJohn Forte 		{0x555, 0x90}
2552fcf3ce44SJohn Forte 	};
2553fcf3ce44SJohn Forte 
2554fcf3ce44SJohn Forte 
2555fcf3ce44SJohn Forte 	/* Check Manufacturers Code */
2556fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++) {
2557fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
2558fcf3ce44SJohn Forte 	}
2559fcf3ce44SJohn Forte 
2560fcf3ce44SJohn Forte 	cc = SBUS_READ_FLASH_COPY(hba, 0);
2561fcf3ce44SJohn Forte 
2562fcf3ce44SJohn Forte 	/* Check Device Code */
2563fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++) {
2564fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
2565fcf3ce44SJohn Forte 	}
2566fcf3ce44SJohn Forte 
2567fcf3ce44SJohn Forte 	cc = SBUS_READ_FLASH_COPY(hba, 1);
2568fcf3ce44SJohn Forte 
2569fcf3ce44SJohn Forte 
2570fcf3ce44SJohn Forte 	/* Check block protections (up to 4 16K blocks = 64K) */
2571fcf3ce44SJohn Forte 	for (j = 0; j < 4; j++) {
2572fcf3ce44SJohn Forte 		for (i = 0; i < 3; i++) {
2573fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
2574fcf3ce44SJohn Forte 		}
2575fcf3ce44SJohn Forte 
2576fcf3ce44SJohn Forte 		offset = (j << 14) | 0x2;
2577fcf3ce44SJohn Forte 
2578fcf3ce44SJohn Forte 		cc = SBUS_READ_FLASH_COPY(hba, offset);
2579fcf3ce44SJohn Forte 
2580fcf3ce44SJohn Forte 		if (cc == 0x01) {
2581fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2582fcf3ce44SJohn Forte 			    "Block %d is protected and can't be erased.", j);
2583fcf3ce44SJohn Forte 		}
2584fcf3ce44SJohn Forte 	}
2585fcf3ce44SJohn Forte 
2586fcf3ce44SJohn Forte 	/* Write erase flash sequence */
2587fcf3ce44SJohn Forte 	for (i = 0; i < 6; i++) {
2588fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val);
2589fcf3ce44SJohn Forte 	}
2590fcf3ce44SJohn Forte 
2591fcf3ce44SJohn Forte 	/* check for complete */
2592fcf3ce44SJohn Forte 	for (;;) {
2593fcf3ce44SJohn Forte 		/* Delay 3 seconds */
2594fcf3ce44SJohn Forte 		DELAYMS(3000);
2595fcf3ce44SJohn Forte 
2596fcf3ce44SJohn Forte 		cc = SBUS_READ_FLASH_COPY(hba, 0);
2597fcf3ce44SJohn Forte 
2598fcf3ce44SJohn Forte 
2599fcf3ce44SJohn Forte 		/* If data matches then continue; */
2600fcf3ce44SJohn Forte 		if (cc == 0xff) {
2601fcf3ce44SJohn Forte 			break;
2602fcf3ce44SJohn Forte 		}
2603291a2b48SSukumar Swaminathan 
2604fcf3ce44SJohn Forte 		/* Polling bit will be inverse final value while active */
2605fcf3ce44SJohn Forte 		if ((cc ^ 0xff) & FLASH_POLLING_BIT) {
2606fcf3ce44SJohn Forte 			/* Still busy */
2607fcf3ce44SJohn Forte 
2608fcf3ce44SJohn Forte 			/* Check for error bit */
2609fcf3ce44SJohn Forte 			if (cc & FLASH_ERROR_BIT) {
2610fcf3ce44SJohn Forte 				/* Read data one more time */
2611fcf3ce44SJohn Forte 				cc = SBUS_READ_FLASH_COPY(hba, 0);
2612fcf3ce44SJohn Forte 
2613fcf3ce44SJohn Forte 				/* Check if data matches */
2614fcf3ce44SJohn Forte 				if (cc == 0xff) {
2615fcf3ce44SJohn Forte 					break;
2616fcf3ce44SJohn Forte 				}
2617291a2b48SSukumar Swaminathan 
2618fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
2619fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
2620291a2b48SSukumar Swaminathan 				    "FCode write error: offset:%x wrote:%x "
2621291a2b48SSukumar Swaminathan 				    "read:%x\n", i, 0xff, cc);
2622fcf3ce44SJohn Forte 
2623fcf3ce44SJohn Forte 				return (1);
2624fcf3ce44SJohn Forte 			}
2625fcf3ce44SJohn Forte 		}
2626fcf3ce44SJohn Forte 	}
2627fcf3ce44SJohn Forte 
26284baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
2629*82527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
26304baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
26314baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
26324baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
26334baa2c25SSukumar Swaminathan 		return (1);
26344baa2c25SSukumar Swaminathan 	}
26354baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
26364baa2c25SSukumar Swaminathan 
2637fcf3ce44SJohn Forte 	return (0);
2638fcf3ce44SJohn Forte 
2639*82527734SSukumar Swaminathan } /* emlxs_erase_fcode_flash() */
2640fcf3ce44SJohn Forte 
2641fcf3ce44SJohn Forte 
2642fcf3ce44SJohn Forte extern uint32_t
2643fcf3ce44SJohn Forte emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
2644fcf3ce44SJohn Forte {
2645fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2646fcf3ce44SJohn Forte 	LOAD_ENTRY *LoadEntry;
2647fcf3ce44SJohn Forte 	LOAD_LIST *LoadList = NULL;
2648fcf3ce44SJohn Forte 	uint32_t i;
2649fcf3ce44SJohn Forte 	uint32_t rval = 0;
2650fcf3ce44SJohn Forte 
2651fcf3ce44SJohn Forte 	bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
2652fcf3ce44SJohn Forte 
2653291a2b48SSukumar Swaminathan 	if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST),
2654291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2655fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2656fcf3ce44SJohn Forte 		    "Unable to allocate LOADLIST buffer.");
2657fcf3ce44SJohn Forte 
2658fcf3ce44SJohn Forte 		rval = 1;
2659fcf3ce44SJohn Forte 		goto done;
2660fcf3ce44SJohn Forte 	}
2661291a2b48SSukumar Swaminathan 
2662fcf3ce44SJohn Forte 	if (emlxs_read_load_list(hba, LoadList)) {
2663fcf3ce44SJohn Forte 		rval = 1;
2664fcf3ce44SJohn Forte 		goto done;
2665fcf3ce44SJohn Forte 	}
2666291a2b48SSukumar Swaminathan 
2667fcf3ce44SJohn Forte 	for (i = 0; i < LoadList->entry_cnt; i++) {
2668fcf3ce44SJohn Forte 		LoadEntry = &LoadList->load_entry[i];
2669fcf3ce44SJohn Forte 		if ((LoadEntry->un.wd[0] != 0) &&
2670fcf3ce44SJohn Forte 		    (LoadEntry->un.wd[0] != 0xffffffff)) {
2671fcf3ce44SJohn Forte 			load_list[i] = LoadEntry->un.id;
2672fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2673291a2b48SSukumar Swaminathan 			    "Load List[%d]: %08x %08x", i,
2674291a2b48SSukumar Swaminathan 			    LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
2675fcf3ce44SJohn Forte 		}
2676fcf3ce44SJohn Forte 	}
2677fcf3ce44SJohn Forte 
2678fcf3ce44SJohn Forte done:
2679fcf3ce44SJohn Forte 
2680fcf3ce44SJohn Forte 	if (LoadList) {
2681fcf3ce44SJohn Forte 		kmem_free(LoadList, sizeof (LOAD_LIST));
2682fcf3ce44SJohn Forte 	}
2683291a2b48SSukumar Swaminathan 
2684fcf3ce44SJohn Forte 	return (rval);
2685fcf3ce44SJohn Forte 
2686*82527734SSukumar Swaminathan } /* emlxs_get_load_list() */
2687fcf3ce44SJohn Forte 
2688fcf3ce44SJohn Forte 
2689fcf3ce44SJohn Forte extern uint32_t
2690fcf3ce44SJohn Forte emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2691fcf3ce44SJohn Forte     uint32_t verbose)
2692fcf3ce44SJohn Forte {
2693fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2694fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2695fcf3ce44SJohn Forte 	MAILBOX *mb;
2696fcf3ce44SJohn Forte 	uint32_t rval = 0;
2697fcf3ce44SJohn Forte 	uint32_t *wd;
2698fcf3ce44SJohn Forte 
2699fcf3ce44SJohn Forte 	bzero(WakeUpParms, sizeof (WAKE_UP_PARMS));
2700fcf3ce44SJohn Forte 
2701291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2702291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2703fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2704fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2705fcf3ce44SJohn Forte 
2706fcf3ce44SJohn Forte 		return (1);
2707fcf3ce44SJohn Forte 	}
2708291a2b48SSukumar Swaminathan 
2709fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2710fcf3ce44SJohn Forte 
2711*82527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox,
2712291a2b48SSukumar Swaminathan 	    DMP_NV_PARAMS,
2713291a2b48SSukumar Swaminathan 	    WAKE_UP_PARMS_REGION_ID,
2714fcf3ce44SJohn Forte 	    sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
2715fcf3ce44SJohn Forte 
2716*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2717fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2718fcf3ce44SJohn Forte 		    "Unable to get parameters: Mailbox cmd=%x status=%x",
2719fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
2720fcf3ce44SJohn Forte 
2721fcf3ce44SJohn Forte 		if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) {
2722fcf3ce44SJohn Forte 			rval = (uint32_t)CFG_DATA_NO_REGION;
2723fcf3ce44SJohn Forte 		} else {
2724fcf3ce44SJohn Forte 			rval = 1;
2725fcf3ce44SJohn Forte 		}
2726fcf3ce44SJohn Forte 	} else {
2727*82527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2728*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
2729*82527734SSukumar Swaminathan 			    0, hba->sli.sli4.dump_region.size,
2730*82527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
2731*82527734SSukumar Swaminathan 
2732*82527734SSukumar Swaminathan 			bcopy((caddr_t)hba->sli.sli4.dump_region.virt,
2733*82527734SSukumar Swaminathan 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
2734*82527734SSukumar Swaminathan 		} else {
2735*82527734SSukumar Swaminathan 			bcopy((caddr_t)&mb->un.varDmp.resp_offset,
2736*82527734SSukumar Swaminathan 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
2737*82527734SSukumar Swaminathan 		}
2738fcf3ce44SJohn Forte 
2739fcf3ce44SJohn Forte 		if (verbose) {
2740fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->prog_id;
2741fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2742291a2b48SSukumar Swaminathan 			    "Wakeup:      prog_id=%08x %08x", wd[0], wd[1]);
2743fcf3ce44SJohn Forte 
2744fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id;
2745fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2746291a2b48SSukumar Swaminathan 			    "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]);
2747fcf3ce44SJohn Forte 
2748fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli1_prog_id;
2749fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2750291a2b48SSukumar Swaminathan 			    "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]);
2751fcf3ce44SJohn Forte 
2752fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli2_prog_id;
2753fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2754291a2b48SSukumar Swaminathan 			    "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]);
2755fcf3ce44SJohn Forte 
2756fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli3_prog_id;
2757fcf3ce44SJohn Forte 			if (wd[0] || wd[1]) {
2758291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2759291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
2760291a2b48SSukumar Swaminathan 				    "Wakeup: sli3_prog_id=%08x %08x", wd[0],
2761291a2b48SSukumar Swaminathan 				    wd[1]);
2762fcf3ce44SJohn Forte 			}
2763291a2b48SSukumar Swaminathan 
2764fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli4_prog_id;
2765fcf3ce44SJohn Forte 			if (wd[0] || wd[1]) {
2766291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2767291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
2768291a2b48SSukumar Swaminathan 				    "Wakeup: sli4_prog_id=%08x %08x", wd[0],
2769291a2b48SSukumar Swaminathan 				    wd[1]);
2770fcf3ce44SJohn Forte 			}
2771291a2b48SSukumar Swaminathan 
2772fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id;
2773fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2774291a2b48SSukumar Swaminathan 			    "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]);
2775fcf3ce44SJohn Forte 
2776fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2777fcf3ce44SJohn Forte 			    "Wakeup: pci_cfg_rsvd=%x",
2778fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_rsvd);
2779fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2780fcf3ce44SJohn Forte 			    "Wakeup:  use_hdw_def=%x",
2781fcf3ce44SJohn Forte 			    WakeUpParms->use_hdw_def);
2782fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2783fcf3ce44SJohn Forte 			    "Wakeup:  pci_cfg_sel=%x",
2784fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_sel);
2785fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2786fcf3ce44SJohn Forte 			    "Wakeup:   cfg_lookup=%x",
2787fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_lookup_sel);
2788fcf3ce44SJohn Forte 		}
2789fcf3ce44SJohn Forte 	}
2790fcf3ce44SJohn Forte 
2791fcf3ce44SJohn Forte done:
2792fcf3ce44SJohn Forte 
2793fcf3ce44SJohn Forte 	if (mbox) {
2794fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2795fcf3ce44SJohn Forte 	}
2796291a2b48SSukumar Swaminathan 
2797fcf3ce44SJohn Forte 	return (rval);
2798fcf3ce44SJohn Forte 
2799*82527734SSukumar Swaminathan } /* emlxs_read_wakeup_parms() */
2800fcf3ce44SJohn Forte 
2801fcf3ce44SJohn Forte 
2802fcf3ce44SJohn Forte static uint32_t
2803291a2b48SSukumar Swaminathan emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
2804fcf3ce44SJohn Forte {
2805fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2806fcf3ce44SJohn Forte 	LOAD_ENTRY *LoadEntry;
2807fcf3ce44SJohn Forte 	uint32_t *Uptr;
2808fcf3ce44SJohn Forte 	uint32_t CurEntryAddr;
2809fcf3ce44SJohn Forte 	MAILBOXQ *mbox = NULL;
2810fcf3ce44SJohn Forte 	MAILBOX *mb;
2811fcf3ce44SJohn Forte 
2812fcf3ce44SJohn Forte 	bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
2813fcf3ce44SJohn Forte 
2814291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2815291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2816fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2817fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2818fcf3ce44SJohn Forte 
2819fcf3ce44SJohn Forte 		return (1);
2820fcf3ce44SJohn Forte 	}
2821291a2b48SSukumar Swaminathan 
2822fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2823fcf3ce44SJohn Forte 
2824*82527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
2825fcf3ce44SJohn Forte 
2826*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2827fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2828fcf3ce44SJohn Forte 		    "Unable to get load list: Mailbox cmd=%x status=%x",
2829fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
2830fcf3ce44SJohn Forte 
2831fcf3ce44SJohn Forte 		goto done;
2832fcf3ce44SJohn Forte 	}
2833291a2b48SSukumar Swaminathan 
2834*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2835*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
2836*82527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
2837*82527734SSukumar Swaminathan 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
2838*82527734SSukumar Swaminathan 	} else {
2839*82527734SSukumar Swaminathan 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
2840*82527734SSukumar Swaminathan 	}
2841fcf3ce44SJohn Forte 
2842fcf3ce44SJohn Forte 	LoadList->head = Uptr[0];
2843fcf3ce44SJohn Forte 	LoadList->tail = Uptr[1];
2844fcf3ce44SJohn Forte 
2845fcf3ce44SJohn Forte 	CurEntryAddr = LoadList->head;
2846fcf3ce44SJohn Forte 
2847fcf3ce44SJohn Forte 	while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
2848fcf3ce44SJohn Forte 	    (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
2849fcf3ce44SJohn Forte 		LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
2850fcf3ce44SJohn Forte 		LoadList->entry_cnt++;
2851fcf3ce44SJohn Forte 
2852*82527734SSukumar Swaminathan 		emlxs_format_dump(hba, mbox,
2853291a2b48SSukumar Swaminathan 		    DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
2854fcf3ce44SJohn Forte 
2855*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2856291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
2857fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2858291a2b48SSukumar Swaminathan 			    "Unable to get load list (%d): Mailbox cmd=%x "
2859291a2b48SSukumar Swaminathan 			    "status=%x", LoadList->entry_cnt, mb->mbxCommand,
2860291a2b48SSukumar Swaminathan 			    mb->mbxStatus);
2861fcf3ce44SJohn Forte 
2862fcf3ce44SJohn Forte 			goto done;
2863fcf3ce44SJohn Forte 		}
2864291a2b48SSukumar Swaminathan 
2865*82527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2866*82527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
2867*82527734SSukumar Swaminathan 			    0, hba->sli.sli4.dump_region.size,
2868*82527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
2869*82527734SSukumar Swaminathan 			Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
2870*82527734SSukumar Swaminathan 		} else {
2871*82527734SSukumar Swaminathan 			Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
2872*82527734SSukumar Swaminathan 		}
2873fcf3ce44SJohn Forte 
2874fcf3ce44SJohn Forte 		LoadEntry->next = Uptr[0];
2875fcf3ce44SJohn Forte 		LoadEntry->prev = Uptr[1];
2876fcf3ce44SJohn Forte 		LoadEntry->start_adr = Uptr[2];
2877fcf3ce44SJohn Forte 		LoadEntry->len = Uptr[3];
2878fcf3ce44SJohn Forte 		LoadEntry->un.wd[0] = Uptr[4];
2879fcf3ce44SJohn Forte 		LoadEntry->un.wd[1] = Uptr[5];
2880fcf3ce44SJohn Forte 
2881fcf3ce44SJohn Forte 		/* update next current load entry address */
2882fcf3ce44SJohn Forte 		CurEntryAddr = LoadEntry->next;
2883fcf3ce44SJohn Forte 
2884fcf3ce44SJohn Forte 	}	/* end of while (not end of list) */
2885fcf3ce44SJohn Forte 
2886fcf3ce44SJohn Forte done:
2887fcf3ce44SJohn Forte 
2888fcf3ce44SJohn Forte 	if (mbox) {
2889fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2890fcf3ce44SJohn Forte 	}
2891291a2b48SSukumar Swaminathan 
2892fcf3ce44SJohn Forte 	return (0);
2893fcf3ce44SJohn Forte 
2894*82527734SSukumar Swaminathan } /* emlxs_read_load_list() */
2895fcf3ce44SJohn Forte 
2896fcf3ce44SJohn Forte 
2897fcf3ce44SJohn Forte static uint32_t
2898fcf3ce44SJohn Forte emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize)
2899fcf3ce44SJohn Forte {
2900fcf3ce44SJohn Forte 	uint32_t Version;
2901fcf3ce44SJohn Forte 
2902fcf3ce44SJohn Forte 	if (BufferSize < (SLI_VERSION_LOC + 4))
2903fcf3ce44SJohn Forte 		return (0xffffffff);
2904fcf3ce44SJohn Forte 
2905fcf3ce44SJohn Forte 	Buffer += SLI_VERSION_LOC;
2906fcf3ce44SJohn Forte 	Version = *((uint32_t *)Buffer);
2907fcf3ce44SJohn Forte 
2908fcf3ce44SJohn Forte 	return (Version);
2909fcf3ce44SJohn Forte 
2910*82527734SSukumar Swaminathan } /* emlxs_get_abs_image_type() */
2911fcf3ce44SJohn Forte 
2912fcf3ce44SJohn Forte 
2913fcf3ce44SJohn Forte static uint32_t
2914fcf3ce44SJohn Forte emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer,
2915fcf3ce44SJohn Forte     uint32_t BufferSize, PAIF_HDR AifHeader)
2916fcf3ce44SJohn Forte {
2917fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2918fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
2919fcf3ce44SJohn Forte 	uint32_t NextImage;
2920fcf3ce44SJohn Forte 	uint32_t i;
2921fcf3ce44SJohn Forte 	uint8_t *Sptr;
2922fcf3ce44SJohn Forte 	uint8_t *Dptr;
2923fcf3ce44SJohn Forte 	uint32_t HwId = 0xffffffff;
2924fcf3ce44SJohn Forte 
2925fcf3ce44SJohn Forte 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
2926fcf3ce44SJohn Forte 
2927fcf3ce44SJohn Forte 	while (BufferSize > NextImage) {
2928fcf3ce44SJohn Forte 		Sptr = (uint8_t *)&Buffer[NextImage];
2929fcf3ce44SJohn Forte 		Dptr = (uint8_t *)&ImageHdr;
2930fcf3ce44SJohn Forte 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
2931fcf3ce44SJohn Forte 			Dptr[i] = Sptr[i];
2932fcf3ce44SJohn Forte 		}
2933fcf3ce44SJohn Forte 
2934fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff)
2935fcf3ce44SJohn Forte 			break;
2936fcf3ce44SJohn Forte 
2937fcf3ce44SJohn Forte 		switch (ImageHdr.Id.Type) {
2938fcf3ce44SJohn Forte 		case 6:
2939fcf3ce44SJohn Forte 		case 7:
2940fcf3ce44SJohn Forte 			if (HwId == 0xffffffff) {
2941fcf3ce44SJohn Forte 				HwId = ImageHdr.Id.Id;
2942fcf3ce44SJohn Forte 			}
2943291a2b48SSukumar Swaminathan 
2944fcf3ce44SJohn Forte 			if (HwId != ImageHdr.Id.Id) {
2945291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
2946291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
2947291a2b48SSukumar Swaminathan 				    "Invalid hardware id. %x %x", HwId,
2948291a2b48SSukumar Swaminathan 				    ImageHdr.Id.Id);
2949fcf3ce44SJohn Forte 			}
2950fcf3ce44SJohn Forte 			break;
2951fcf3ce44SJohn Forte 		}
2952fcf3ce44SJohn Forte 
2953fcf3ce44SJohn Forte 		NextImage += ImageHdr.BlockSize;
2954fcf3ce44SJohn Forte 	}
2955fcf3ce44SJohn Forte 
2956fcf3ce44SJohn Forte 	return (HwId);
2957fcf3ce44SJohn Forte 
2958*82527734SSukumar Swaminathan } /* emlxs_get_dwc_image_type() */
2959fcf3ce44SJohn Forte 
2960fcf3ce44SJohn Forte 
2961fcf3ce44SJohn Forte static int
2962291a2b48SSukumar Swaminathan emlxs_build_parms(caddr_t Buffer,
2963291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS AbsWakeUpParms,
2964fcf3ce44SJohn Forte     uint32_t BufferSize, PAIF_HDR AifHeader, int32_t DwcFile)
2965fcf3ce44SJohn Forte {
2966fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
2967fcf3ce44SJohn Forte 	uint32_t NextImage;
2968fcf3ce44SJohn Forte 	uint32_t i;
2969fcf3ce44SJohn Forte 	int32_t ChangeParams = FALSE;
2970fcf3ce44SJohn Forte 	caddr_t Sptr;
2971fcf3ce44SJohn Forte 	caddr_t Dptr;
2972fcf3ce44SJohn Forte 
2973fcf3ce44SJohn Forte 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
2974fcf3ce44SJohn Forte 
2975fcf3ce44SJohn Forte 	if (!DwcFile && ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
2976fcf3ce44SJohn Forte 		return (FALSE);
2977fcf3ce44SJohn Forte 	}
2978291a2b48SSukumar Swaminathan 
2979fcf3ce44SJohn Forte 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
2980fcf3ce44SJohn Forte 
2981fcf3ce44SJohn Forte 	while (BufferSize > NextImage) {
2982fcf3ce44SJohn Forte 		Sptr = &Buffer[NextImage];
2983fcf3ce44SJohn Forte 		Dptr = (caddr_t)&ImageHdr;
2984fcf3ce44SJohn Forte 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
2985fcf3ce44SJohn Forte 			Dptr[i] = Sptr[i];
2986fcf3ce44SJohn Forte 		}
2987fcf3ce44SJohn Forte 
2988fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff)
2989fcf3ce44SJohn Forte 			break;
2990fcf3ce44SJohn Forte 
2991fcf3ce44SJohn Forte 		switch (ImageHdr.Id.Type) {
2992fcf3ce44SJohn Forte 		case TEST_PROGRAM:
2993fcf3ce44SJohn Forte 			break;
2994fcf3ce44SJohn Forte 		case FUNC_FIRMWARE:
2995fcf3ce44SJohn Forte 			AbsWakeUpParms->prog_id = ImageHdr.Id;
2996fcf3ce44SJohn Forte 			ChangeParams = TRUE;
2997fcf3ce44SJohn Forte 			break;
2998fcf3ce44SJohn Forte 		case BOOT_BIOS:
2999fcf3ce44SJohn Forte 			AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
3000fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3001fcf3ce44SJohn Forte 			break;
3002fcf3ce44SJohn Forte 		case SLI1_OVERLAY:
3003fcf3ce44SJohn Forte 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
3004fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3005fcf3ce44SJohn Forte 			break;
3006fcf3ce44SJohn Forte 		case SLI2_OVERLAY:
3007fcf3ce44SJohn Forte 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
3008fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3009fcf3ce44SJohn Forte 			break;
3010fcf3ce44SJohn Forte 		case SLI3_OVERLAY:
3011fcf3ce44SJohn Forte 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
3012fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3013fcf3ce44SJohn Forte 			break;
3014fcf3ce44SJohn Forte 		case SLI4_OVERLAY:
3015fcf3ce44SJohn Forte 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
3016fcf3ce44SJohn Forte 			ChangeParams = TRUE;
3017fcf3ce44SJohn Forte 			break;
3018fcf3ce44SJohn Forte 		default:
3019fcf3ce44SJohn Forte 			break;
3020fcf3ce44SJohn Forte 		}
3021fcf3ce44SJohn Forte 
3022fcf3ce44SJohn Forte 		NextImage += ImageHdr.BlockSize;
3023fcf3ce44SJohn Forte 	}
3024fcf3ce44SJohn Forte 
3025fcf3ce44SJohn Forte 	return (ChangeParams);
3026fcf3ce44SJohn Forte 
3027*82527734SSukumar Swaminathan } /* emlxs_build_parms() */
3028fcf3ce44SJohn Forte 
3029fcf3ce44SJohn Forte 
3030fcf3ce44SJohn Forte static uint32_t
3031fcf3ce44SJohn Forte emlxs_update_wakeup_parms(emlxs_hba_t *hba,
3032fcf3ce44SJohn Forte     PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
3033fcf3ce44SJohn Forte {
3034fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3035fcf3ce44SJohn Forte 	MAILBOX *mb;
3036fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
3037fcf3ce44SJohn Forte 	uint32_t rval = 0;
3038fcf3ce44SJohn Forte 
3039291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3040291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3041fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3042fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3043fcf3ce44SJohn Forte 
3044fcf3ce44SJohn Forte 		return (1);
3045fcf3ce44SJohn Forte 	}
3046291a2b48SSukumar Swaminathan 
3047fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3048fcf3ce44SJohn Forte 
3049fcf3ce44SJohn Forte 	WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
3050fcf3ce44SJohn Forte 	WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
3051fcf3ce44SJohn Forte 	WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
3052fcf3ce44SJohn Forte 	WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
3053fcf3ce44SJohn Forte 	WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
3054fcf3ce44SJohn Forte 	WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
3055fcf3ce44SJohn Forte 
3056*82527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
3057fcf3ce44SJohn Forte 
3058*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3059fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3060291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
3061291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
3062fcf3ce44SJohn Forte 
3063fcf3ce44SJohn Forte 		rval = 1;
3064fcf3ce44SJohn Forte 	}
3065291a2b48SSukumar Swaminathan 
3066fcf3ce44SJohn Forte 	if (mbox) {
3067fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3068fcf3ce44SJohn Forte 	}
3069291a2b48SSukumar Swaminathan 
3070fcf3ce44SJohn Forte 	return (rval);
3071fcf3ce44SJohn Forte 
3072*82527734SSukumar Swaminathan } /* emlxs_update_wakeup_parms() */
3073fcf3ce44SJohn Forte 
3074fcf3ce44SJohn Forte 
3075fcf3ce44SJohn Forte static uint32_t
3076291a2b48SSukumar Swaminathan emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
3077291a2b48SSukumar Swaminathan     uint32_t type, char *file_type)
3078fcf3ce44SJohn Forte {
3079fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3080fcf3ce44SJohn Forte 
3081fcf3ce44SJohn Forte 	/* Create the version label */
3082fcf3ce44SJohn Forte 	emlxs_decode_version(file->version, file->label);
3083fcf3ce44SJohn Forte 
3084fcf3ce44SJohn Forte 	/* Process the DWC type */
3085fcf3ce44SJohn Forte 	switch (type) {
3086fcf3ce44SJohn Forte 	case TEST_PROGRAM:
3087fcf3ce44SJohn Forte 
3088fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3089291a2b48SSukumar Swaminathan 		    "%s: TEST: offset=%08x  version=%08x, %s", file_type,
3090291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3091fcf3ce44SJohn Forte 
3092fcf3ce44SJohn Forte 		break;
3093fcf3ce44SJohn Forte 
3094fcf3ce44SJohn Forte 	case BOOT_BIOS:
3095fcf3ce44SJohn Forte 
3096fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3097291a2b48SSukumar Swaminathan 		    "%s: BOOT: offset=%08x  version=%08x, %s", file_type,
3098291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3099fcf3ce44SJohn Forte 
3100fcf3ce44SJohn Forte 		if (!emlxs_bios_check(hba, id)) {
3101fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3102fcf3ce44SJohn Forte 			    "BOOT Check: Image not compatible with %s. id=%02x",
3103fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3104fcf3ce44SJohn Forte 
3105fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3106fcf3ce44SJohn Forte 		}
3107291a2b48SSukumar Swaminathan 
3108fcf3ce44SJohn Forte 		break;
3109fcf3ce44SJohn Forte 
3110fcf3ce44SJohn Forte 	case FUNC_FIRMWARE:	/* Stub */
3111fcf3ce44SJohn Forte 
3112fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3113291a2b48SSukumar Swaminathan 		    "%s: STUB: offset=%08x  version=%08x, %s", file_type,
3114291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3115fcf3ce44SJohn Forte 
3116fcf3ce44SJohn Forte 		if (!emlxs_stub_check(hba, id)) {
3117fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3118fcf3ce44SJohn Forte 			    "STUB Check: Image not compatible with %s. id=%02x",
3119fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3120fcf3ce44SJohn Forte 
3121fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3122fcf3ce44SJohn Forte 		}
3123291a2b48SSukumar Swaminathan 
3124fcf3ce44SJohn Forte 		break;
3125fcf3ce44SJohn Forte 
3126fcf3ce44SJohn Forte 	case SLI1_OVERLAY:
3127fcf3ce44SJohn Forte 
3128fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3129291a2b48SSukumar Swaminathan 		    "%s: SLI1: offset=%08x  version=%08x, %s", file_type,
3130291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3131fcf3ce44SJohn Forte 
3132fcf3ce44SJohn Forte 		if (!emlxs_sli1_check(hba, id)) {
3133fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3134fcf3ce44SJohn Forte 			    "SLI1 Check: Image not compatible with %s. id=%02x",
3135fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3136fcf3ce44SJohn Forte 
3137fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3138fcf3ce44SJohn Forte 		}
3139291a2b48SSukumar Swaminathan 
3140fcf3ce44SJohn Forte 		break;
3141fcf3ce44SJohn Forte 
3142fcf3ce44SJohn Forte 	case SLI2_OVERLAY:
3143fcf3ce44SJohn Forte 
3144fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3145291a2b48SSukumar Swaminathan 		    "%s: SLI2: offset=%08x  version=%08x, %s", file_type,
3146291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3147fcf3ce44SJohn Forte 
3148fcf3ce44SJohn Forte 		if (!emlxs_sli2_check(hba, id)) {
3149fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3150fcf3ce44SJohn Forte 			    "SLI2 Check: Image not compatible with %s. id=%02x",
3151fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3152fcf3ce44SJohn Forte 
3153fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3154fcf3ce44SJohn Forte 		}
3155291a2b48SSukumar Swaminathan 
3156fcf3ce44SJohn Forte 		break;
3157fcf3ce44SJohn Forte 
3158fcf3ce44SJohn Forte 	case SLI3_OVERLAY:
3159fcf3ce44SJohn Forte 
3160fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3161291a2b48SSukumar Swaminathan 		    "%s: SLI3: offset=%08x  version=%08x, %s", file_type,
3162291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3163fcf3ce44SJohn Forte 
3164fcf3ce44SJohn Forte 		if (!emlxs_sli3_check(hba, id)) {
3165fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3166fcf3ce44SJohn Forte 			    "SLI3 Check: Image not compatible with %s. id=%02x",
3167fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3168fcf3ce44SJohn Forte 
3169fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3170fcf3ce44SJohn Forte 		}
3171291a2b48SSukumar Swaminathan 
3172fcf3ce44SJohn Forte 		break;
3173fcf3ce44SJohn Forte 
3174fcf3ce44SJohn Forte 	case SLI4_OVERLAY:
3175fcf3ce44SJohn Forte 
3176fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3177291a2b48SSukumar Swaminathan 		    "%s: SLI4: offset=%08x  version=%08x, %s", file_type,
3178291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3179fcf3ce44SJohn Forte 
3180fcf3ce44SJohn Forte 		if (!emlxs_sli4_check(hba, id)) {
3181fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3182fcf3ce44SJohn Forte 			    "SLI4 Check: Image not compatible with %s. id=%02x",
3183fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3184fcf3ce44SJohn Forte 
3185fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3186fcf3ce44SJohn Forte 		}
3187291a2b48SSukumar Swaminathan 
3188fcf3ce44SJohn Forte 		break;
3189fcf3ce44SJohn Forte 
3190fcf3ce44SJohn Forte 	case SBUS_FCODE:
3191fcf3ce44SJohn Forte 
3192fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3193fcf3ce44SJohn Forte 		    "%s: SBUS FCODE: offset=%08x  version=%08x, %s",
3194291a2b48SSukumar Swaminathan 		    file_type, file->offset, file->version, file->label);
3195fcf3ce44SJohn Forte 
3196fcf3ce44SJohn Forte 		if (!emlxs_sbus_fcode_check(hba, id)) {
3197fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3198fcf3ce44SJohn Forte 			    "SBUS FCODE Check: Image not compatible with %s. "
3199291a2b48SSukumar Swaminathan 			    "id=%02x", hba->model_info.model, id);
3200fcf3ce44SJohn Forte 
3201fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3202fcf3ce44SJohn Forte 		}
3203291a2b48SSukumar Swaminathan 
3204fcf3ce44SJohn Forte 		break;
3205fcf3ce44SJohn Forte 
3206fcf3ce44SJohn Forte 	case KERNEL_CODE:
3207fcf3ce44SJohn Forte 
3208fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3209291a2b48SSukumar Swaminathan 		    "%s: KERN: offset=%08x  version=%08x, %s", file_type,
3210291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
3211fcf3ce44SJohn Forte 
3212fcf3ce44SJohn Forte 		if (!emlxs_kern_check(hba, id)) {
3213fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3214fcf3ce44SJohn Forte 			    "KERN Check: Image not compatible with %s. id=%02x",
3215fcf3ce44SJohn Forte 			    hba->model_info.model, id);
3216fcf3ce44SJohn Forte 
3217fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
3218fcf3ce44SJohn Forte 		}
3219291a2b48SSukumar Swaminathan 
3220fcf3ce44SJohn Forte 		break;
3221fcf3ce44SJohn Forte 
3222fcf3ce44SJohn Forte 	default:
3223fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3224291a2b48SSukumar Swaminathan 		    "%s: Image type not supported. type=%x", file_type, type);
3225fcf3ce44SJohn Forte 
3226fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
3227fcf3ce44SJohn Forte 	}
3228fcf3ce44SJohn Forte 
3229fcf3ce44SJohn Forte 	return (0);
3230fcf3ce44SJohn Forte 
3231*82527734SSukumar Swaminathan } /* emlxs_validate_version() */
3232fcf3ce44SJohn Forte 
3233fcf3ce44SJohn Forte 
3234fcf3ce44SJohn Forte static uint32_t
3235fcf3ce44SJohn Forte emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
3236fcf3ce44SJohn Forte     emlxs_fw_image_t *image)
3237fcf3ce44SJohn Forte {
3238fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3239fcf3ce44SJohn Forte 	uint32_t ImageType;
3240fcf3ce44SJohn Forte 	AIF_HDR AifHdr;
3241fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
3242fcf3ce44SJohn Forte 	uint32_t NextImage;
3243fcf3ce44SJohn Forte 	uint32_t FileType;
3244fcf3ce44SJohn Forte 	uint32_t FileLen = 0;
3245fcf3ce44SJohn Forte 	uint32_t TotalLen = 0;
3246fcf3ce44SJohn Forte 	uint32_t *CkSumEnd;
3247fcf3ce44SJohn Forte 	uint32_t id;
3248fcf3ce44SJohn Forte 	uint32_t type;
3249fcf3ce44SJohn Forte 	uint32_t ver;
3250fcf3ce44SJohn Forte 	uint32_t ImageLength;
3251fcf3ce44SJohn Forte 	uint32_t BufferSize;
3252fcf3ce44SJohn Forte 	uint32_t rval = 0;
3253fcf3ce44SJohn Forte 	caddr_t bptr;
3254fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
3255fcf3ce44SJohn Forte 
3256fcf3ce44SJohn Forte 	vpd = &VPD;
3257fcf3ce44SJohn Forte 
3258fcf3ce44SJohn Forte 	/* Get image type */
3259fcf3ce44SJohn Forte 	ImageType = *((uint32_t *)Buffer);
3260fcf3ce44SJohn Forte 
3261fcf3ce44SJohn Forte 	/* Pegasus and beyond adapters */
3262fcf3ce44SJohn Forte 	if ((ImageType == NOP_IMAGE_TYPE) &&
3263fcf3ce44SJohn Forte 	    !(hba->model_info.chip &
3264fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
3265fcf3ce44SJohn Forte 		bptr = Buffer;
3266fcf3ce44SJohn Forte 		TotalLen = sizeof (uint32_t);
3267fcf3ce44SJohn Forte 
3268fcf3ce44SJohn Forte 		while (TotalLen < Size) {
3269fcf3ce44SJohn Forte 			if (Size < sizeof (AIF_HDR)) {
3270291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3271291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
3272fcf3ce44SJohn Forte 				    "Invalid image header length: 0x%x < 0x%x",
3273fcf3ce44SJohn Forte 				    Size, sizeof (AIF_HDR));
3274fcf3ce44SJohn Forte 
3275fcf3ce44SJohn Forte 				return (EMLXS_IMAGE_BAD);
3276fcf3ce44SJohn Forte 			}
3277291a2b48SSukumar Swaminathan 
3278fcf3ce44SJohn Forte 			bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
3279fcf3ce44SJohn Forte 			emlxs_disp_aif_header(hba, &AifHdr);
3280fcf3ce44SJohn Forte 
3281fcf3ce44SJohn Forte 			ImageLength = AifHdr.RoSize;
3282fcf3ce44SJohn Forte 
3283fcf3ce44SJohn Forte 			/* Validate checksum */
3284291a2b48SSukumar Swaminathan 			CkSumEnd =
3285291a2b48SSukumar Swaminathan 			    (uint32_t *)(bptr + ImageLength +
3286291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR));
3287fcf3ce44SJohn Forte 			if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
3288291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3289291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
3290fcf3ce44SJohn Forte 				    "Invalid checksum found.");
3291fcf3ce44SJohn Forte 
3292fcf3ce44SJohn Forte 				return (EMLXS_IMAGE_BAD);
3293fcf3ce44SJohn Forte 			}
3294291a2b48SSukumar Swaminathan 
3295fcf3ce44SJohn Forte 			FileType = AifHdr.ZinitBr;
3296fcf3ce44SJohn Forte 			switch (FileType) {
3297fcf3ce44SJohn Forte 			case FILE_TYPE_AWC:
3298291a2b48SSukumar Swaminathan 				image->awc.offset =
3299291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
3300291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
3301fcf3ce44SJohn Forte 				image->awc.version = AifHdr.AVersion;
3302fcf3ce44SJohn Forte 				image->awc.revcomp = 0;
3303fcf3ce44SJohn Forte 
3304fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3305fcf3ce44SJohn Forte 				type = emlxs_type_check(
3306fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
3307fcf3ce44SJohn Forte 
3308fcf3ce44SJohn Forte 				/* Validate the file version */
3309fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
3310fcf3ce44SJohn Forte 				    &image->awc, id, type, "AWC file"))) {
3311fcf3ce44SJohn Forte 					return (rval);
3312fcf3ce44SJohn Forte 				}
3313291a2b48SSukumar Swaminathan 
3314fcf3ce44SJohn Forte 				break;
3315fcf3ce44SJohn Forte 
3316fcf3ce44SJohn Forte 			case FILE_TYPE_BWC:
3317291a2b48SSukumar Swaminathan 				image->bwc.offset =
3318291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
3319291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
3320fcf3ce44SJohn Forte 				image->bwc.version = AifHdr.AVersion;
3321fcf3ce44SJohn Forte 				image->bwc.revcomp = 0;
3322fcf3ce44SJohn Forte 
3323fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3324fcf3ce44SJohn Forte 				type = emlxs_type_check(
3325fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
3326fcf3ce44SJohn Forte 
3327fcf3ce44SJohn Forte 				/* Validate the file version */
3328fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
3329fcf3ce44SJohn Forte 				    &image->bwc, id, type, "BWC file"))) {
3330fcf3ce44SJohn Forte 					return (rval);
3331fcf3ce44SJohn Forte 				}
3332291a2b48SSukumar Swaminathan 
3333fcf3ce44SJohn Forte 				break;
3334fcf3ce44SJohn Forte 
3335fcf3ce44SJohn Forte 			case FILE_TYPE_DWC:
3336291a2b48SSukumar Swaminathan 				image->dwc.offset =
3337291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
3338291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
3339fcf3ce44SJohn Forte 				image->dwc.version = AifHdr.AVersion;
3340fcf3ce44SJohn Forte 				image->dwc.revcomp = 0;
3341fcf3ce44SJohn Forte 
3342fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3343fcf3ce44SJohn Forte 				type = emlxs_type_check(
3344fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
3345fcf3ce44SJohn Forte 
3346fcf3ce44SJohn Forte 				/* Validate the file version */
3347fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
3348fcf3ce44SJohn Forte 				    &image->dwc, id, type, "DWC file"))) {
3349fcf3ce44SJohn Forte 					return (rval);
3350fcf3ce44SJohn Forte 				}
3351291a2b48SSukumar Swaminathan 
3352fcf3ce44SJohn Forte 				/* Scan for program types */
3353fcf3ce44SJohn Forte 				NextImage = sizeof (AIF_HDR) + 4;
3354fcf3ce44SJohn Forte 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
3355fcf3ce44SJohn Forte 
3356fcf3ce44SJohn Forte 				while (BufferSize > NextImage) {
3357fcf3ce44SJohn Forte 					bcopy(&bptr[NextImage], &ImageHdr,
3358fcf3ce44SJohn Forte 					    sizeof (IMAGE_HDR));
3359291a2b48SSukumar Swaminathan 					emlxs_dump_image_header(hba,
3360291a2b48SSukumar Swaminathan 					    &ImageHdr);
3361fcf3ce44SJohn Forte 
3362fcf3ce44SJohn Forte 					/* Validate block size */
3363fcf3ce44SJohn Forte 					if (ImageHdr.BlockSize == 0xffffffff) {
3364fcf3ce44SJohn Forte 						break;
3365fcf3ce44SJohn Forte 					}
3366291a2b48SSukumar Swaminathan 
3367fcf3ce44SJohn Forte 					type = emlxs_type_check(
3368fcf3ce44SJohn Forte 					    ImageHdr.Id.Type);
3369fcf3ce44SJohn Forte 
3370fcf3ce44SJohn Forte 					/* Calculate the program offset */
3371291a2b48SSukumar Swaminathan 					image->prog[type].offset =
3372291a2b48SSukumar Swaminathan 					    (uint32_t)((uintptr_t)
3373291a2b48SSukumar Swaminathan 					    &bptr[NextImage] -
3374fcf3ce44SJohn Forte 					    (uintptr_t)Buffer);
3375fcf3ce44SJohn Forte 
3376fcf3ce44SJohn Forte 					/* Acquire the versions */
3377fcf3ce44SJohn Forte 					image->prog[type].version =
3378fcf3ce44SJohn Forte 					    (ImageHdr.Id.Type << 24) |
3379fcf3ce44SJohn Forte 					    (ImageHdr.Id.Id << 16) |
3380fcf3ce44SJohn Forte 					    (ImageHdr.Id.Ver << 8) |
3381fcf3ce44SJohn Forte 					    ImageHdr.Id.Rev;
3382fcf3ce44SJohn Forte 
3383fcf3ce44SJohn Forte 					image->prog[type].revcomp =
3384fcf3ce44SJohn Forte 					    ImageHdr.Id.un.revcomp;
3385fcf3ce44SJohn Forte 
3386fcf3ce44SJohn Forte 					/* Validate the file version */
3387fcf3ce44SJohn Forte 					if ((rval = emlxs_validate_version(hba,
3388fcf3ce44SJohn Forte 					    &image->prog[type], ImageHdr.Id.Id,
3389fcf3ce44SJohn Forte 					    type, "DWC prog"))) {
3390fcf3ce44SJohn Forte 						return (rval);
3391fcf3ce44SJohn Forte 					}
3392291a2b48SSukumar Swaminathan 
3393fcf3ce44SJohn Forte 					NextImage += ImageHdr.BlockSize;
3394fcf3ce44SJohn Forte 
3395*82527734SSukumar Swaminathan 				}	/* while () */
3396fcf3ce44SJohn Forte 
3397fcf3ce44SJohn Forte 				break;
3398fcf3ce44SJohn Forte 			}
3399fcf3ce44SJohn Forte 
3400291a2b48SSukumar Swaminathan 			FileLen =
3401291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR) + ImageLength +
3402fcf3ce44SJohn Forte 			    sizeof (uint32_t);
3403fcf3ce44SJohn Forte 			TotalLen += FileLen;
3404fcf3ce44SJohn Forte 			bptr += FileLen;
3405fcf3ce44SJohn Forte 		}
3406fcf3ce44SJohn Forte 	}
3407291a2b48SSukumar Swaminathan 
3408fcf3ce44SJohn Forte 	/* Pre-pegasus adapters */
3409fcf3ce44SJohn Forte 
3410fcf3ce44SJohn Forte 	else if (ImageType == NOP_IMAGE_TYPE) {
3411fcf3ce44SJohn Forte 		if (Size < sizeof (AIF_HDR)) {
3412fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3413291a2b48SSukumar Swaminathan 			    "Invalid image header length: 0x%x < 0x%x", Size,
3414291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR));
3415fcf3ce44SJohn Forte 
3416fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3417fcf3ce44SJohn Forte 		}
3418291a2b48SSukumar Swaminathan 
3419fcf3ce44SJohn Forte 		bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
3420fcf3ce44SJohn Forte 		emlxs_disp_aif_header(hba, &AifHdr);
3421fcf3ce44SJohn Forte 
3422fcf3ce44SJohn Forte 		ImageLength = AifHdr.RoSize + AifHdr.RwSize;
3423fcf3ce44SJohn Forte 
3424fcf3ce44SJohn Forte 		if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
3425fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3426291a2b48SSukumar Swaminathan 			    "Image length incorrect: 0x%x != 0x%x", Size,
3427291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR) + ImageLength +
3428291a2b48SSukumar Swaminathan 			    sizeof (uint32_t));
3429fcf3ce44SJohn Forte 
3430fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3431fcf3ce44SJohn Forte 		}
3432291a2b48SSukumar Swaminathan 
3433fcf3ce44SJohn Forte 		if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
3434fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3435fcf3ce44SJohn Forte 			    "Invalid imageBase value %x != 0x20000",
3436fcf3ce44SJohn Forte 			    AifHdr.ImageBase);
3437fcf3ce44SJohn Forte 
3438fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3439fcf3ce44SJohn Forte 		}
3440291a2b48SSukumar Swaminathan 
3441291a2b48SSukumar Swaminathan 		CkSumEnd =
3442291a2b48SSukumar Swaminathan 		    (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
3443fcf3ce44SJohn Forte 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
3444fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3445fcf3ce44SJohn Forte 			    "Invalid checksum found.");
3446fcf3ce44SJohn Forte 
3447fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3448fcf3ce44SJohn Forte 		}
3449291a2b48SSukumar Swaminathan 
3450fcf3ce44SJohn Forte 		image->dwc.offset = 0;
3451fcf3ce44SJohn Forte 		image->dwc.version = AifHdr.AVersion;
3452fcf3ce44SJohn Forte 		image->dwc.revcomp = 0;
3453fcf3ce44SJohn Forte 
3454fcf3ce44SJohn Forte 		id = (AifHdr.AVersion & 0x00ff0000) >> 16;
3455fcf3ce44SJohn Forte 		type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
3456fcf3ce44SJohn Forte 
3457fcf3ce44SJohn Forte 		/* Validate the file version */
3458291a2b48SSukumar Swaminathan 		if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
3459291a2b48SSukumar Swaminathan 		    "DWC file"))) {
3460fcf3ce44SJohn Forte 			return (rval);
3461fcf3ce44SJohn Forte 		}
3462291a2b48SSukumar Swaminathan 
3463fcf3ce44SJohn Forte 		NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
3464fcf3ce44SJohn Forte 		while (Size > NextImage) {
3465fcf3ce44SJohn Forte 			bcopy(&Buffer[NextImage], &ImageHdr,
3466fcf3ce44SJohn Forte 			    sizeof (IMAGE_HDR));
3467fcf3ce44SJohn Forte 			emlxs_dump_image_header(hba, &ImageHdr);
3468fcf3ce44SJohn Forte 
3469fcf3ce44SJohn Forte 			/* Validate block size */
3470fcf3ce44SJohn Forte 			if (ImageHdr.BlockSize == 0xffffffff) {
3471fcf3ce44SJohn Forte 				break;
3472fcf3ce44SJohn Forte 			}
3473291a2b48SSukumar Swaminathan 
3474fcf3ce44SJohn Forte 			type = emlxs_type_check(ImageHdr.Id.Type);
3475fcf3ce44SJohn Forte 
3476fcf3ce44SJohn Forte 			/* Calculate the program offset */
3477fcf3ce44SJohn Forte 			image->prog[type].offset = NextImage;
3478fcf3ce44SJohn Forte 
3479fcf3ce44SJohn Forte 			/* Acquire the versions */
3480291a2b48SSukumar Swaminathan 			image->prog[type].version =
3481291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Type << 24) |
3482291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Id << 16) |
3483291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Ver << 8) |
3484fcf3ce44SJohn Forte 			    ImageHdr.Id.Rev;
3485fcf3ce44SJohn Forte 
3486fcf3ce44SJohn Forte 			image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
3487fcf3ce44SJohn Forte 
3488fcf3ce44SJohn Forte 			/* Validate the file version */
3489fcf3ce44SJohn Forte 			if ((rval = emlxs_validate_version(hba,
3490291a2b48SSukumar Swaminathan 			    &image->prog[type], ImageHdr.Id.Id, type,
3491291a2b48SSukumar Swaminathan 			    "DWC prog"))) {
3492fcf3ce44SJohn Forte 				return (rval);
3493fcf3ce44SJohn Forte 			}
3494291a2b48SSukumar Swaminathan 
3495fcf3ce44SJohn Forte 			NextImage += ImageHdr.BlockSize;
3496fcf3ce44SJohn Forte 		}
3497fcf3ce44SJohn Forte 	} else {
3498fcf3ce44SJohn Forte 		/* Precheck image size */
3499fcf3ce44SJohn Forte 		if (Size < sizeof (IMAGE_HDR)) {
3500fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3501291a2b48SSukumar Swaminathan 			    "Invalid image header length: 0x%x < 0x%x", Size,
3502291a2b48SSukumar Swaminathan 			    sizeof (IMAGE_HDR));
3503fcf3ce44SJohn Forte 
3504fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3505fcf3ce44SJohn Forte 		}
3506291a2b48SSukumar Swaminathan 
3507fcf3ce44SJohn Forte 		bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
3508fcf3ce44SJohn Forte 		emlxs_dump_image_header(hba, &ImageHdr);
3509fcf3ce44SJohn Forte 
3510fcf3ce44SJohn Forte 		/* Validate block size */
3511fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff) {
3512fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3513fcf3ce44SJohn Forte 			    "Invalid block size.");
3514fcf3ce44SJohn Forte 
3515fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3516fcf3ce44SJohn Forte 		}
3517291a2b48SSukumar Swaminathan 
3518fcf3ce44SJohn Forte 		ImageLength = ImageHdr.BlockSize;
3519fcf3ce44SJohn Forte 
3520fcf3ce44SJohn Forte 		/* Validate image length */
3521fcf3ce44SJohn Forte 		if (Size != ImageLength) {
3522fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3523291a2b48SSukumar Swaminathan 			    "Invalid image length: 0x%x != 0x%x", Size,
3524291a2b48SSukumar Swaminathan 			    ImageLength);
3525fcf3ce44SJohn Forte 
3526fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3527fcf3ce44SJohn Forte 		}
3528291a2b48SSukumar Swaminathan 
3529fcf3ce44SJohn Forte 		/* Validate Checksum */
3530291a2b48SSukumar Swaminathan 		CkSumEnd =
3531291a2b48SSukumar Swaminathan 		    (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
3532291a2b48SSukumar Swaminathan 		    1;
3533fcf3ce44SJohn Forte 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
3534fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3535fcf3ce44SJohn Forte 			    "Invalid checksum found.");
3536fcf3ce44SJohn Forte 
3537fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
3538fcf3ce44SJohn Forte 		}
3539291a2b48SSukumar Swaminathan 
3540fcf3ce44SJohn Forte 		type = emlxs_type_check(ImageHdr.Id.Type);
3541fcf3ce44SJohn Forte 
3542fcf3ce44SJohn Forte 		/* Calculate the program offset */
3543fcf3ce44SJohn Forte 		image->prog[type].offset = 0;
3544fcf3ce44SJohn Forte 
3545fcf3ce44SJohn Forte 		/* Acquire the versions */
3546291a2b48SSukumar Swaminathan 		image->prog[type].version =
3547291a2b48SSukumar Swaminathan 		    (ImageHdr.Id.Type << 24) | (ImageHdr.Id.
3548291a2b48SSukumar Swaminathan 		    Id << 16) | (ImageHdr.Id.Ver << 8) | ImageHdr.Id.Rev;
3549fcf3ce44SJohn Forte 
3550fcf3ce44SJohn Forte 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
3551fcf3ce44SJohn Forte 
3552fcf3ce44SJohn Forte 		/* Validate the file version */
3553fcf3ce44SJohn Forte 		if ((rval = emlxs_validate_version(hba, &image->prog[type],
3554fcf3ce44SJohn Forte 		    ImageHdr.Id.Id, type, "DWC file"))) {
3555fcf3ce44SJohn Forte 			return (rval);
3556fcf3ce44SJohn Forte 		}
3557fcf3ce44SJohn Forte 	}
3558fcf3ce44SJohn Forte 
3559fcf3ce44SJohn Forte 	/*
3560291a2b48SSukumar Swaminathan 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
3561291a2b48SSukumar Swaminathan 	 * image file is greater than version 3.8
3562fcf3ce44SJohn Forte 	 */
3563fcf3ce44SJohn Forte 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
3564fcf3ce44SJohn Forte 		if (image->prog[SLI2_OVERLAY].version != 0) {
3565fcf3ce44SJohn Forte 			ver = (image->prog[SLI2_OVERLAY].version &
3566fcf3ce44SJohn Forte 			    0x0000ff00) >> 8;
3567fcf3ce44SJohn Forte 
3568fcf3ce44SJohn Forte 			if ((((ver & 0xf0) == 0x30) &&
3569fcf3ce44SJohn Forte 			    ((ver & 0x0f) >= 0x08)) ||
3570fcf3ce44SJohn Forte 			    ((ver & 0xf0) > 0x30)) {
3571fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
3572fcf3ce44SJohn Forte 				    &emlxs_image_incompat_msg,
3573291a2b48SSukumar Swaminathan 				    "ASIC Check: Image requires DragonFly "
3574291a2b48SSukumar Swaminathan 				    "V2 ASIC");
3575fcf3ce44SJohn Forte 
3576fcf3ce44SJohn Forte 				return (EMLXS_IMAGE_INCOMPATIBLE);
3577fcf3ce44SJohn Forte 			}
3578fcf3ce44SJohn Forte 		}
3579fcf3ce44SJohn Forte 	}
3580291a2b48SSukumar Swaminathan 
3581fcf3ce44SJohn Forte 	return (0);
3582fcf3ce44SJohn Forte 
3583*82527734SSukumar Swaminathan } /* emlxs_validate_image() */
3584fcf3ce44SJohn Forte 
3585fcf3ce44SJohn Forte 
3586fcf3ce44SJohn Forte static uint32_t
3587fcf3ce44SJohn Forte emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
3588fcf3ce44SJohn Forte {
3589fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3590fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
3591fcf3ce44SJohn Forte 	MAILBOX *mb;
3592fcf3ce44SJohn Forte 	uint32_t next_address;
3593fcf3ce44SJohn Forte 	uint32_t rval = 0;
3594fcf3ce44SJohn Forte 
3595fcf3ce44SJohn Forte 	if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
3596fcf3ce44SJohn Forte 		return (1);
3597fcf3ce44SJohn Forte 	}
3598291a2b48SSukumar Swaminathan 
3599291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3600291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3601fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3602fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3603fcf3ce44SJohn Forte 
3604fcf3ce44SJohn Forte 		return (1);
3605fcf3ce44SJohn Forte 	}
3606291a2b48SSukumar Swaminathan 
3607fcf3ce44SJohn Forte 	bzero(mbox, sizeof (MAILBOXQ));
3608fcf3ce44SJohn Forte 
3609fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3610fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_LOAD_EXP_ROM;
3611fcf3ce44SJohn Forte 	mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
3612fcf3ce44SJohn Forte 	mb->un.varLdExpRom.progress = 0;
3613fcf3ce44SJohn Forte 	mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
3614*82527734SSukumar Swaminathan 	mbox->mbox_cmpl = NULL;
3615fcf3ce44SJohn Forte 
3616*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3617fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3618fcf3ce44SJohn Forte 		    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
3619fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
3620fcf3ce44SJohn Forte 
3621fcf3ce44SJohn Forte 		rval = 1;
3622fcf3ce44SJohn Forte 
3623fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
3624fcf3ce44SJohn Forte 	}
3625291a2b48SSukumar Swaminathan 
3626fcf3ce44SJohn Forte 	if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
3627fcf3ce44SJohn Forte 		(void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
3628fcf3ce44SJohn Forte 
3629fcf3ce44SJohn Forte 		rval = 1;
3630fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
3631fcf3ce44SJohn Forte 	}
3632291a2b48SSukumar Swaminathan 
3633fcf3ce44SJohn Forte 	if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
3634fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3635fcf3ce44SJohn Forte 		    "Invalid exp ROM progress. progress=%x",
3636fcf3ce44SJohn Forte 		    mb->un.varLdExpRom.progress);
3637fcf3ce44SJohn Forte 
3638fcf3ce44SJohn Forte 		rval = 1;
3639fcf3ce44SJohn Forte 
3640fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
3641fcf3ce44SJohn Forte 	}
3642291a2b48SSukumar Swaminathan 
3643fcf3ce44SJohn Forte 	/*
3644fcf3ce44SJohn Forte 	 * continue Erase
3645fcf3ce44SJohn Forte 	 */
3646fcf3ce44SJohn Forte 	while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
3647fcf3ce44SJohn Forte 
3648fcf3ce44SJohn Forte 		next_address = mb->un.varLdExpRom.dl_to_adr;
3649fcf3ce44SJohn Forte 
3650fcf3ce44SJohn Forte 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3651fcf3ce44SJohn Forte 
3652fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
3653fcf3ce44SJohn Forte 		mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
3654fcf3ce44SJohn Forte 		mb->un.varLdExpRom.dl_to_adr = next_address;
3655fcf3ce44SJohn Forte 		mb->un.varLdExpRom.progress = 0;
3656fcf3ce44SJohn Forte 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
3657*82527734SSukumar Swaminathan 		mbox->mbox_cmpl = NULL;
3658fcf3ce44SJohn Forte 
3659*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3660291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
3661fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3662fcf3ce44SJohn Forte 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
3663fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
3664fcf3ce44SJohn Forte 
3665fcf3ce44SJohn Forte 			rval = 1;
3666fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
3667fcf3ce44SJohn Forte 		}
3668291a2b48SSukumar Swaminathan 
3669fcf3ce44SJohn Forte 	}
3670fcf3ce44SJohn Forte 
3671fcf3ce44SJohn Forte 	while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
3672fcf3ce44SJohn Forte 		next_address = mb->un.varLdExpRom.dl_to_adr;
3673fcf3ce44SJohn Forte 
3674fcf3ce44SJohn Forte 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3675fcf3ce44SJohn Forte 
3676fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
3677fcf3ce44SJohn Forte 		mb->un.varLdExpRom.step = EROM_CMD_COPY;
3678fcf3ce44SJohn Forte 		mb->un.varLdExpRom.dl_to_adr = next_address;
3679fcf3ce44SJohn Forte 		mb->un.varLdExpRom.progress = 0;
3680fcf3ce44SJohn Forte 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
3681*82527734SSukumar Swaminathan 		mbox->mbox_cmpl = NULL;
3682fcf3ce44SJohn Forte 
3683*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3684291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
3685fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3686fcf3ce44SJohn Forte 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
3687fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
3688fcf3ce44SJohn Forte 
3689fcf3ce44SJohn Forte 			rval = 1;
3690fcf3ce44SJohn Forte 
3691fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
3692fcf3ce44SJohn Forte 		}
3693fcf3ce44SJohn Forte 	}
3694fcf3ce44SJohn Forte 
3695fcf3ce44SJohn Forte 	rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
3696fcf3ce44SJohn Forte 
3697fcf3ce44SJohn Forte SLI_DOWNLOAD_EXIT:
3698fcf3ce44SJohn Forte 
3699fcf3ce44SJohn Forte 	if (mbox) {
3700fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3701fcf3ce44SJohn Forte 	}
3702291a2b48SSukumar Swaminathan 
3703fcf3ce44SJohn Forte 	return (rval);
3704fcf3ce44SJohn Forte 
3705*82527734SSukumar Swaminathan } /* emlxs_update_exp_rom() */
3706fcf3ce44SJohn Forte 
3707fcf3ce44SJohn Forte 
3708fcf3ce44SJohn Forte /*
3709fcf3ce44SJohn Forte  *
3710fcf3ce44SJohn Forte  * FUNCTION NAME: emlxs_start_abs_download_2mb
3711fcf3ce44SJohn Forte  *
3712fcf3ce44SJohn Forte  * DESCRIPTION: Perform absolute download for 2 MB flash.  A incoming
3713fcf3ce44SJohn Forte  *              buffer may consist of more than 1 file.  This function
3714fcf3ce44SJohn Forte  *              will parse the buffer to find all the files.
3715fcf3ce44SJohn Forte  *
3716fcf3ce44SJohn Forte  *
3717fcf3ce44SJohn Forte  * PARAMETERS:
3718fcf3ce44SJohn Forte  *
3719fcf3ce44SJohn Forte  *
3720fcf3ce44SJohn Forte  * RETURNS:
3721fcf3ce44SJohn Forte  *
3722fcf3ce44SJohn Forte  */
3723fcf3ce44SJohn Forte /* ARGSUSED */
3724fcf3ce44SJohn Forte static uint32_t
3725fcf3ce44SJohn Forte emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
3726fcf3ce44SJohn Forte     uint32_t offline, emlxs_fw_image_t *fw_image)
3727fcf3ce44SJohn Forte {
3728fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3729fcf3ce44SJohn Forte 	caddr_t AwcBuffer = NULL;
3730fcf3ce44SJohn Forte 	caddr_t BwcBuffer = NULL;
3731fcf3ce44SJohn Forte 	caddr_t DwcBuffer = NULL;
3732fcf3ce44SJohn Forte 	AIF_HDR *AwcAifHdr;
3733fcf3ce44SJohn Forte 	AIF_HDR *BwcAifHdr;
3734fcf3ce44SJohn Forte 	AIF_HDR *DwcAifHdr;
3735fcf3ce44SJohn Forte 	uint32_t BWCflag;
3736fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
3737fcf3ce44SJohn Forte 	uint32_t i;
3738fcf3ce44SJohn Forte 	uint32_t count;
3739fcf3ce44SJohn Forte 	uint32_t extType = 0;
3740fcf3ce44SJohn Forte 	uint32_t rval = 0;
3741fcf3ce44SJohn Forte 
3742fcf3ce44SJohn Forte 	vpd = &VPD;
3743fcf3ce44SJohn Forte 
3744fcf3ce44SJohn Forte 	/* Check for AWC file */
3745fcf3ce44SJohn Forte 	if (fw_image->awc.version) {
3746fcf3ce44SJohn Forte 		AwcBuffer = buffer + fw_image->awc.offset;
3747291a2b48SSukumar Swaminathan 		AwcAifHdr = (AIF_HDR *)AwcBuffer;
3748fcf3ce44SJohn Forte 	}
3749291a2b48SSukumar Swaminathan 
3750fcf3ce44SJohn Forte 	/* Check for BWC file */
3751fcf3ce44SJohn Forte 	if (fw_image->bwc.version) {
3752fcf3ce44SJohn Forte 		extType = BWCext;
3753fcf3ce44SJohn Forte 		BwcBuffer = buffer + fw_image->bwc.offset;
3754291a2b48SSukumar Swaminathan 		BwcAifHdr = (AIF_HDR *)BwcBuffer;
3755fcf3ce44SJohn Forte 	}
3756291a2b48SSukumar Swaminathan 
3757fcf3ce44SJohn Forte 	/* Check for DWC file */
3758fcf3ce44SJohn Forte 	if (fw_image->dwc.version) {
3759fcf3ce44SJohn Forte 		extType = DWCext;
3760fcf3ce44SJohn Forte 		DwcBuffer = buffer + fw_image->dwc.offset;
3761291a2b48SSukumar Swaminathan 		DwcAifHdr = (AIF_HDR *)DwcBuffer;
3762fcf3ce44SJohn Forte 	}
3763291a2b48SSukumar Swaminathan 
3764fcf3ce44SJohn Forte 	/* Check for program files */
3765fcf3ce44SJohn Forte 	count = 0;
3766fcf3ce44SJohn Forte 	for (i = 0; i < MAX_PROG_TYPES; i++) {
3767fcf3ce44SJohn Forte 		if (fw_image->prog[i].version) {
3768fcf3ce44SJohn Forte 			count++;
3769fcf3ce44SJohn Forte 		}
3770fcf3ce44SJohn Forte 	}
3771fcf3ce44SJohn Forte 
3772fcf3ce44SJohn Forte 	if (count > 1) {
3773fcf3ce44SJohn Forte 		extType = ALLext;
3774fcf3ce44SJohn Forte 
3775fcf3ce44SJohn Forte 		if (fw_image->bwc.version) {
3776fcf3ce44SJohn Forte 			BWCflag = ALL_WITH_BWC;
3777fcf3ce44SJohn Forte 		} else {
3778fcf3ce44SJohn Forte 			BWCflag = ALL_WITHOUT_BWC;
3779fcf3ce44SJohn Forte 		}
3780fcf3ce44SJohn Forte 	} else {
3781fcf3ce44SJohn Forte 		BWCflag = NO_ALL;
3782fcf3ce44SJohn Forte 	}
3783fcf3ce44SJohn Forte 
3784fcf3ce44SJohn Forte 	/* If nothing to download then quit now */
3785fcf3ce44SJohn Forte 	if (!AwcBuffer && !DwcBuffer && !BwcBuffer) {
3786fcf3ce44SJohn Forte 		return (0);
3787fcf3ce44SJohn Forte 	}
3788291a2b48SSukumar Swaminathan 
3789fcf3ce44SJohn Forte 	/*
3790fcf3ce44SJohn Forte 	 * Everything checks out, now to just do it
3791fcf3ce44SJohn Forte 	 */
3792fcf3ce44SJohn Forte 	if (offline) {
3793fcf3ce44SJohn Forte 		if (emlxs_offline(hba) != FC_SUCCESS) {
3794fcf3ce44SJohn Forte 			return (EMLXS_OFFLINE_FAILED);
3795fcf3ce44SJohn Forte 		}
3796291a2b48SSukumar Swaminathan 
3797*82527734SSukumar Swaminathan 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
3798fcf3ce44SJohn Forte 			return (EMLXS_OFFLINE_FAILED);
3799fcf3ce44SJohn Forte 		}
3800fcf3ce44SJohn Forte 	}
3801291a2b48SSukumar Swaminathan 
3802fcf3ce44SJohn Forte 	if (AwcBuffer) {
3803fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3804291a2b48SSukumar Swaminathan 		    "AWC file: KERN: old=%s  new=%s ", vpd->postKernName,
3805291a2b48SSukumar Swaminathan 		    fw_image->awc.label);
3806fcf3ce44SJohn Forte 
3807291a2b48SSukumar Swaminathan 		rval = emlxs_proc_abs_2mb(hba,
3808291a2b48SSukumar Swaminathan 		    AwcAifHdr, AwcBuffer, FILE_TYPE_AWC, BWCflag, extType);
3809fcf3ce44SJohn Forte 
3810fcf3ce44SJohn Forte 		if (rval) {
3811fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_2MB_EXIT;
3812fcf3ce44SJohn Forte 		}
3813fcf3ce44SJohn Forte 	}
3814291a2b48SSukumar Swaminathan 
3815fcf3ce44SJohn Forte 	if (DwcBuffer) {
3816fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3817fcf3ce44SJohn Forte 		    "DWC file: TEST:             new=%s ",
3818fcf3ce44SJohn Forte 		    fw_image->prog[TEST_PROGRAM].label);
3819fcf3ce44SJohn Forte 
3820fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3821291a2b48SSukumar Swaminathan 		    "DWC file: STUB: old=%s  new=%s ", vpd->opFwName,
3822291a2b48SSukumar Swaminathan 		    fw_image->prog[FUNC_FIRMWARE].label);
3823fcf3ce44SJohn Forte 
3824fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3825291a2b48SSukumar Swaminathan 		    "DWC file: SLI1: old=%s  new=%s ", vpd->sli1FwName,
3826291a2b48SSukumar Swaminathan 		    fw_image->prog[SLI1_OVERLAY].label);
3827fcf3ce44SJohn Forte 
3828fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3829291a2b48SSukumar Swaminathan 		    "DWC file: SLI2: old=%s  new=%s ", vpd->sli2FwName,
3830291a2b48SSukumar Swaminathan 		    fw_image->prog[SLI2_OVERLAY].label);
3831fcf3ce44SJohn Forte 
3832fcf3ce44SJohn Forte 		if (vpd->sli3FwRev || fw_image->prog[SLI3_OVERLAY].version) {
3833fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3834fcf3ce44SJohn Forte 			    "DWC file: SLI3: old=%s  new=%s ",
3835fcf3ce44SJohn Forte 			    vpd->sli3FwName,
3836fcf3ce44SJohn Forte 			    fw_image->prog[SLI3_OVERLAY].label);
3837fcf3ce44SJohn Forte 		}
3838291a2b48SSukumar Swaminathan 
3839fcf3ce44SJohn Forte 		if (vpd->sli4FwRev || fw_image->prog[SLI4_OVERLAY].version) {
3840fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3841fcf3ce44SJohn Forte 			    "DWC file: SLI4: old=%s  new=%s ",
3842fcf3ce44SJohn Forte 			    vpd->sli4FwName,
3843fcf3ce44SJohn Forte 			    fw_image->prog[SLI4_OVERLAY].label);
3844fcf3ce44SJohn Forte 		}
3845291a2b48SSukumar Swaminathan 
3846291a2b48SSukumar Swaminathan 		rval = emlxs_proc_abs_2mb(hba,
3847291a2b48SSukumar Swaminathan 		    DwcAifHdr, DwcBuffer, FILE_TYPE_DWC, BWCflag, extType);
3848fcf3ce44SJohn Forte 
3849fcf3ce44SJohn Forte 		if (rval) {
3850fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_2MB_EXIT;
3851fcf3ce44SJohn Forte 		}
3852fcf3ce44SJohn Forte 	}
3853291a2b48SSukumar Swaminathan 
3854fcf3ce44SJohn Forte 	if (BwcBuffer) {
3855fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3856291a2b48SSukumar Swaminathan 		    "BWC file: BOOT: old=%s  new=%s ", vpd->fcode_version,
3857291a2b48SSukumar Swaminathan 		    fw_image->bwc.label);
3858fcf3ce44SJohn Forte 
3859291a2b48SSukumar Swaminathan 		rval = emlxs_proc_abs_2mb(hba,
3860291a2b48SSukumar Swaminathan 		    BwcAifHdr, BwcBuffer, FILE_TYPE_BWC, BWCflag, extType);
3861fcf3ce44SJohn Forte 	}
3862291a2b48SSukumar Swaminathan 
3863fcf3ce44SJohn Forte SLI_DOWNLOAD_2MB_EXIT:
3864fcf3ce44SJohn Forte 
3865fcf3ce44SJohn Forte 	if (offline) {
3866fcf3ce44SJohn Forte 		(void) emlxs_online(hba);
3867fcf3ce44SJohn Forte 	}
3868291a2b48SSukumar Swaminathan 
3869fcf3ce44SJohn Forte 	return (rval);
3870fcf3ce44SJohn Forte 
3871*82527734SSukumar Swaminathan } /* emlxs_start_abs_download_2mb() */
3872fcf3ce44SJohn Forte 
3873fcf3ce44SJohn Forte 
3874fcf3ce44SJohn Forte /*
3875fcf3ce44SJohn Forte  *
3876fcf3ce44SJohn Forte  * FUNCTION NAME: emlxs_proc_abs_2mb
3877fcf3ce44SJohn Forte  *
3878fcf3ce44SJohn Forte  * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
3879fcf3ce44SJohn Forte  *              the port and download the file with sliIssueMbCommand()
3880fcf3ce44SJohn Forte  *
3881fcf3ce44SJohn Forte  *
3882fcf3ce44SJohn Forte  * PARAMETERS:
3883fcf3ce44SJohn Forte  *
3884fcf3ce44SJohn Forte  *
3885fcf3ce44SJohn Forte  * RETURNS:
3886fcf3ce44SJohn Forte  *
3887fcf3ce44SJohn Forte  */
3888fcf3ce44SJohn Forte static uint32_t
3889291a2b48SSukumar Swaminathan emlxs_proc_abs_2mb(emlxs_hba_t *hba,
3890291a2b48SSukumar Swaminathan     PAIF_HDR AifHdr,
3891291a2b48SSukumar Swaminathan     caddr_t EntireBuffer,
3892fcf3ce44SJohn Forte     uint32_t FileType, uint32_t BWCflag, uint32_t extType)
3893fcf3ce44SJohn Forte {
3894fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3895fcf3ce44SJohn Forte 	caddr_t Buffer = NULL;
3896fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
3897fcf3ce44SJohn Forte 	uint32_t *Src;
3898fcf3ce44SJohn Forte 	uint32_t *Dst;
3899fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
3900fcf3ce44SJohn Forte 	MAILBOX *mb;
3901fcf3ce44SJohn Forte 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
3902fcf3ce44SJohn Forte 	uint32_t rval = 0;
3903fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
3904fcf3ce44SJohn Forte 	uint32_t DlToAddr = AifHdr->ImageBase;
3905fcf3ce44SJohn Forte 	uint32_t DlCount;
3906fcf3ce44SJohn Forte 	WAKE_UP_PARMS AbsWakeUpParms;
3907fcf3ce44SJohn Forte 	uint32_t i;
3908fcf3ce44SJohn Forte 	uint32_t NextAddr;
3909fcf3ce44SJohn Forte 	uint32_t EraseByteCount;
3910fcf3ce44SJohn Forte 	uint32_t AreaId;
3911fcf3ce44SJohn Forte 	uint32_t RspProgress = 0;
3912fcf3ce44SJohn Forte 	uint32_t numBootImage = 0;
3913fcf3ce44SJohn Forte 	uint32_t ParamsChg = 0;
3914fcf3ce44SJohn Forte 	uint32_t BufferSize;
3915fcf3ce44SJohn Forte 
3916291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
3917291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3918fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3919fcf3ce44SJohn Forte 		    "%x: Unable to allocate data buffer.", FileType);
3920fcf3ce44SJohn Forte 
3921fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_FAILED);
3922fcf3ce44SJohn Forte 	}
3923291a2b48SSukumar Swaminathan 
3924fcf3ce44SJohn Forte 	bzero(DataBuffer, sizeof (DL_SLIM_SEG_BYTE_COUNT));
3925fcf3ce44SJohn Forte 
3926291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3927291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3928fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3929fcf3ce44SJohn Forte 		    "%x: Unable to allocate mailbox buffer.", FileType);
3930fcf3ce44SJohn Forte 
3931fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
3932fcf3ce44SJohn Forte 
3933fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_FAILED);
3934fcf3ce44SJohn Forte 	}
3935291a2b48SSukumar Swaminathan 
3936fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3937fcf3ce44SJohn Forte 
3938fcf3ce44SJohn Forte 	BufferSize = DlByteCount + sizeof (AIF_HDR) + sizeof (uint32_t);
3939fcf3ce44SJohn Forte 	Buffer = EntireBuffer + sizeof (AIF_HDR);
3940fcf3ce44SJohn Forte 
3941fcf3ce44SJohn Forte 	switch (FileType) {
3942fcf3ce44SJohn Forte 	case FILE_TYPE_AWC:
3943fcf3ce44SJohn Forte 		break;
3944fcf3ce44SJohn Forte 
3945fcf3ce44SJohn Forte 	case FILE_TYPE_BWC:
3946291a2b48SSukumar Swaminathan 		ParamsChg = emlxs_build_parms_2mb_bwc(hba,
3947291a2b48SSukumar Swaminathan 		    AifHdr, extType, &AbsWakeUpParms);
3948fcf3ce44SJohn Forte 
3949fcf3ce44SJohn Forte 		if (ParamsChg == FALSE) {
3950fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3951fcf3ce44SJohn Forte 			    "BWC build parms failed.");
3952fcf3ce44SJohn Forte 
3953fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
3954fcf3ce44SJohn Forte 
3955fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
3956fcf3ce44SJohn Forte 		}
3957fcf3ce44SJohn Forte 		break;
3958fcf3ce44SJohn Forte 
3959fcf3ce44SJohn Forte 	case FILE_TYPE_DWC:
3960291a2b48SSukumar Swaminathan 		ParamsChg = emlxs_build_parms_2mb_dwc(hba,
3961291a2b48SSukumar Swaminathan 		    Buffer,
3962291a2b48SSukumar Swaminathan 		    BufferSize,
3963291a2b48SSukumar Swaminathan 		    AifHdr, &AbsWakeUpParms, BWCflag, extType, &numBootImage);
3964fcf3ce44SJohn Forte 
3965fcf3ce44SJohn Forte 		if (ParamsChg == FALSE) {
3966fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3967fcf3ce44SJohn Forte 			    "DWC build parms failed.");
3968fcf3ce44SJohn Forte 
3969fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
3970fcf3ce44SJohn Forte 
3971fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
3972fcf3ce44SJohn Forte 		}
3973fcf3ce44SJohn Forte 		break;
3974fcf3ce44SJohn Forte 
3975fcf3ce44SJohn Forte 	default:
3976fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3977fcf3ce44SJohn Forte 		    "Invalid file type: %x", FileType);
3978fcf3ce44SJohn Forte 
3979fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_BAD;
3980fcf3ce44SJohn Forte 
3981fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
3982fcf3ce44SJohn Forte 
3983fcf3ce44SJohn Forte 	}
3984fcf3ce44SJohn Forte 
3985fcf3ce44SJohn Forte 	EraseByteCount = AifHdr->Area_Size;
3986fcf3ce44SJohn Forte 	AreaId = AifHdr->Area_ID;
3987fcf3ce44SJohn Forte 
3988*82527734SSukumar Swaminathan 	emlxs_format_load_area_cmd(mbox,
3989291a2b48SSukumar Swaminathan 	    DlToAddr,
3990291a2b48SSukumar Swaminathan 	    EraseByteCount,
3991291a2b48SSukumar Swaminathan 	    ERASE_FLASH,
3992fcf3ce44SJohn Forte 	    0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
3993fcf3ce44SJohn Forte 
3994*82527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3995fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3996fcf3ce44SJohn Forte 		    "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
3997fcf3ce44SJohn Forte 		    FileType, mb->mbxCommand, mb->mbxStatus);
3998fcf3ce44SJohn Forte 
3999fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_FAILED;
4000fcf3ce44SJohn Forte 
4001fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
4002fcf3ce44SJohn Forte 	}
4003291a2b48SSukumar Swaminathan 
4004fcf3ce44SJohn Forte 	while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
4005fcf3ce44SJohn Forte 		NextAddr = mb->un.varLdArea.dl_to_adr;
4006fcf3ce44SJohn Forte 
4007*82527734SSukumar Swaminathan 		emlxs_format_load_area_cmd(mbox,
4008291a2b48SSukumar Swaminathan 		    NextAddr,
4009291a2b48SSukumar Swaminathan 		    EraseByteCount,
4010291a2b48SSukumar Swaminathan 		    ERASE_FLASH,
4011291a2b48SSukumar Swaminathan 		    0,
4012291a2b48SSukumar Swaminathan 		    DL_FROM_SLIM_OFFSET,
4013291a2b48SSukumar Swaminathan 		    AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
4014fcf3ce44SJohn Forte 
4015*82527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4016291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
4017fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4018291a2b48SSukumar Swaminathan 			    "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
4019291a2b48SSukumar Swaminathan 			    "status=%x", FileType, mb->mbxCommand,
4020291a2b48SSukumar Swaminathan 			    mb->mbxStatus);
4021fcf3ce44SJohn Forte 
4022fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
4023fcf3ce44SJohn Forte 
4024fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
4025fcf3ce44SJohn Forte 		}
4026fcf3ce44SJohn Forte 	}
4027fcf3ce44SJohn Forte 
4028fcf3ce44SJohn Forte 	while (DlByteCount) {
4029fcf3ce44SJohn Forte 		if (DlByteCount >= SegSize)
4030fcf3ce44SJohn Forte 			DlCount = SegSize;
4031fcf3ce44SJohn Forte 		else
4032fcf3ce44SJohn Forte 			DlCount = DlByteCount;
4033fcf3ce44SJohn Forte 
4034fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
4035fcf3ce44SJohn Forte 
4036fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
4037fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
4038fcf3ce44SJohn Forte 
4039fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
4040fcf3ce44SJohn Forte 			*Dst = *Src;
4041fcf3ce44SJohn Forte 			Dst++;
4042fcf3ce44SJohn Forte 			Src++;
4043fcf3ce44SJohn Forte 		}
4044fcf3ce44SJohn Forte 
4045fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
4046*82527734SSukumar Swaminathan 		    (volatile uint32_t *)((volatile char *)
4047*82527734SSukumar Swaminathan 		    hba->sli.sli3.slim_addr + sizeof (MAILBOX)),
4048*82527734SSukumar Swaminathan 		    (DlCount / sizeof (uint32_t)));
4049fcf3ce44SJohn Forte 
4050fcf3ce44SJohn Forte 		if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
4051*82527734SSukumar Swaminathan 			emlxs_format_load_area_cmd(mbox,
4052291a2b48SSukumar Swaminathan 			    DlToAddr,
4053291a2b48SSukumar Swaminathan 			    DlCount,
4054291a2b48SSukumar Swaminathan 			    PROGRAM_FLASH,
4055291a2b48SSukumar Swaminathan 			    (DlByteCount) ? 0 : 1,
4056291a2b48SSukumar Swaminathan 			    DL_FROM_SLIM_OFFSET,
4057291a2b48SSukumar Swaminathan 			    AreaId,
4058291a2b48SSukumar Swaminathan 			    MBX_LOAD_AREA,
4059fcf3ce44SJohn Forte 			    (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
4060fcf3ce44SJohn Forte 
4061*82527734SSukumar Swaminathan 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4062fcf3ce44SJohn Forte 			    MBX_SUCCESS) {
4063fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
4064fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
4065291a2b48SSukumar Swaminathan 				    "%x: Could not program 2MB Flash: Mailbox "
4066291a2b48SSukumar Swaminathan 				    "cmd=%x status=%x", FileType,
4067291a2b48SSukumar Swaminathan 				    mb->mbxCommand, mb->mbxStatus);
4068fcf3ce44SJohn Forte 
4069fcf3ce44SJohn Forte 				rval = EMLXS_IMAGE_FAILED;
4070fcf3ce44SJohn Forte 
4071fcf3ce44SJohn Forte 				goto EXIT_ABS_DOWNLOAD;
4072fcf3ce44SJohn Forte 			}
4073fcf3ce44SJohn Forte 		}
4074291a2b48SSukumar Swaminathan 
4075fcf3ce44SJohn Forte 		RspProgress = mb->un.varLdArea.progress;
4076fcf3ce44SJohn Forte 
4077fcf3ce44SJohn Forte 		Buffer += DlCount;
4078fcf3ce44SJohn Forte 		DlToAddr += DlCount;
4079fcf3ce44SJohn Forte 	}
4080fcf3ce44SJohn Forte 
40814baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
4082*82527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
40834baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
40844baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
40854baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
40864baa2c25SSukumar Swaminathan 
40874baa2c25SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
40884baa2c25SSukumar Swaminathan 
40894baa2c25SSukumar Swaminathan 		goto EXIT_ABS_DOWNLOAD;
40904baa2c25SSukumar Swaminathan 	}
40914baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
40924baa2c25SSukumar Swaminathan 
4093fcf3ce44SJohn Forte 	if (RspProgress != RSP_DOWNLOAD_DONE) {
4094fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4095291a2b48SSukumar Swaminathan 		    "%x: Failed download response received. %x", FileType,
4096291a2b48SSukumar Swaminathan 		    RspProgress);
4097fcf3ce44SJohn Forte 
4098fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_FAILED;
4099fcf3ce44SJohn Forte 
4100fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
4101fcf3ce44SJohn Forte 	}
4102291a2b48SSukumar Swaminathan 
4103fcf3ce44SJohn Forte 	if (ParamsChg) {
4104fcf3ce44SJohn Forte 		if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
4105fcf3ce44SJohn Forte 		    &AbsWakeUpParms)) {
4106fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4107fcf3ce44SJohn Forte 			    "%x: Unable to update parms.", FileType);
4108fcf3ce44SJohn Forte 
4109fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
4110fcf3ce44SJohn Forte 		}
4111fcf3ce44SJohn Forte 	}
4112291a2b48SSukumar Swaminathan 
4113fcf3ce44SJohn Forte EXIT_ABS_DOWNLOAD:
4114fcf3ce44SJohn Forte 
4115fcf3ce44SJohn Forte 	if (DataBuffer) {
4116fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4117fcf3ce44SJohn Forte 	}
4118291a2b48SSukumar Swaminathan 
4119fcf3ce44SJohn Forte 	if (mbox) {
4120fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
4121fcf3ce44SJohn Forte 	}
4122291a2b48SSukumar Swaminathan 
4123fcf3ce44SJohn Forte 	return (rval);
4124fcf3ce44SJohn Forte 
4125*82527734SSukumar Swaminathan } /* emlxs_proc_abs_2mb() */
4126fcf3ce44SJohn Forte 
4127fcf3ce44SJohn Forte 
4128fcf3ce44SJohn Forte static void
4129*82527734SSukumar Swaminathan emlxs_format_load_area_cmd(MAILBOXQ * mbq,
4130291a2b48SSukumar Swaminathan     uint32_t Base,
4131291a2b48SSukumar Swaminathan     uint32_t DlByteCount,
4132291a2b48SSukumar Swaminathan     uint32_t Function,
4133291a2b48SSukumar Swaminathan     uint32_t Complete,
4134291a2b48SSukumar Swaminathan     uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
4135fcf3ce44SJohn Forte {
4136*82527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
4137*82527734SSukumar Swaminathan 
4138fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
4139fcf3ce44SJohn Forte 
4140fcf3ce44SJohn Forte 	mb->mbxCommand = MbxCmd;
4141fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
4142fcf3ce44SJohn Forte 	mb->un.varLdArea.update_flash = 1;
4143fcf3ce44SJohn Forte 	mb->un.varLdArea.erase_or_prog = Function;
4144fcf3ce44SJohn Forte 	mb->un.varLdArea.dl_to_adr = Base;
4145fcf3ce44SJohn Forte 	mb->un.varLdArea.dl_len = DlByteCount;
4146fcf3ce44SJohn Forte 	mb->un.varLdArea.load_cmplt = Complete;
4147fcf3ce44SJohn Forte 	mb->un.varLdArea.method = DL_FROM_SLIM;
4148fcf3ce44SJohn Forte 	mb->un.varLdArea.area_id = AreaId;
4149fcf3ce44SJohn Forte 	mb->un.varLdArea.step = StepCmd;
4150fcf3ce44SJohn Forte 	mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
4151*82527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
4152fcf3ce44SJohn Forte 
4153*82527734SSukumar Swaminathan } /* emlxs_format_load_area_cmd() */
4154fcf3ce44SJohn Forte 
4155fcf3ce44SJohn Forte 
4156291a2b48SSukumar Swaminathan /* ARGSUSED */
4157fcf3ce44SJohn Forte static uint32_t
4158291a2b48SSukumar Swaminathan emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
4159291a2b48SSukumar Swaminathan     PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
4160fcf3ce44SJohn Forte {
4161fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4162fcf3ce44SJohn Forte 	uint32_t pId[2];
4163fcf3ce44SJohn Forte 	uint32_t returnStat;
4164fcf3ce44SJohn Forte 
4165fcf3ce44SJohn Forte 	/* Read wakeup paramters */
4166fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
4167fcf3ce44SJohn Forte 	    CFG_DATA_NO_REGION) {
4168fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4169fcf3ce44SJohn Forte 		    "Unable to get BWC parameters.");
4170fcf3ce44SJohn Forte 		return (FALSE);
4171fcf3ce44SJohn Forte 	}
4172291a2b48SSukumar Swaminathan 
4173fcf3ce44SJohn Forte 	pId[0] = AifHdr->AVersion;
4174fcf3ce44SJohn Forte 	pId[1] = 0;
4175fcf3ce44SJohn Forte 
4176fcf3ce44SJohn Forte 	if (extType == BWCext) {
4177fcf3ce44SJohn Forte 		AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4178fcf3ce44SJohn Forte 		AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4179fcf3ce44SJohn Forte 		AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4180fcf3ce44SJohn Forte 		AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4181291a2b48SSukumar Swaminathan 	}
4182291a2b48SSukumar Swaminathan 
4183291a2b48SSukumar Swaminathan 	else if (extType == ALLext) {
4184fcf3ce44SJohn Forte 		if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
4185fcf3ce44SJohn Forte 			/* case of EROM inactive */
4186fcf3ce44SJohn Forte 			AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4187fcf3ce44SJohn Forte 			AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4188fcf3ce44SJohn Forte 		} else {
4189fcf3ce44SJohn Forte 			/* case of EROM active */
4190fcf3ce44SJohn Forte 			if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
4191fcf3ce44SJohn Forte 				/* same ID */
4192fcf3ce44SJohn Forte 				AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4193fcf3ce44SJohn Forte 				AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4194fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4195fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4196fcf3ce44SJohn Forte 			} else {
4197fcf3ce44SJohn Forte 				/* different ID */
4198fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4199fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4200fcf3ce44SJohn Forte 
4201291a2b48SSukumar Swaminathan 				returnStat =
4202291a2b48SSukumar Swaminathan 				    emlxs_update_exp_rom(hba, AbsWakeUpParms);
4203fcf3ce44SJohn Forte 
4204fcf3ce44SJohn Forte 				if (returnStat) {
4205fcf3ce44SJohn Forte 					AbsWakeUpParms->u0.boot_bios_wd[0] =
4206fcf3ce44SJohn Forte 					    pId[0];
4207fcf3ce44SJohn Forte 					AbsWakeUpParms->u0.boot_bios_wd[1] =
4208fcf3ce44SJohn Forte 					    pId[1];
4209fcf3ce44SJohn Forte 				}
4210fcf3ce44SJohn Forte 			}
4211fcf3ce44SJohn Forte 		}
4212fcf3ce44SJohn Forte 	}
4213291a2b48SSukumar Swaminathan 
4214fcf3ce44SJohn Forte 	return (TRUE);
4215fcf3ce44SJohn Forte 
4216*82527734SSukumar Swaminathan } /* emlxs_build_parms_2mb_bwc() */
4217fcf3ce44SJohn Forte 
4218fcf3ce44SJohn Forte 
4219fcf3ce44SJohn Forte /* ARGSUSED */
4220fcf3ce44SJohn Forte static uint32_t
4221291a2b48SSukumar Swaminathan emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba,
4222291a2b48SSukumar Swaminathan     caddr_t Buffer,
4223291a2b48SSukumar Swaminathan     uint32_t BufferSize,
4224291a2b48SSukumar Swaminathan     PAIF_HDR AifHeader,
4225291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS AbsWakeUpParms,
4226291a2b48SSukumar Swaminathan     uint32_t BWCflag, uint32_t extType, uint32_t *numBootImage)
4227fcf3ce44SJohn Forte {
4228fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4229fcf3ce44SJohn Forte 	uint32_t NextImage;
4230fcf3ce44SJohn Forte 	uint32_t i;
4231fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
4232fcf3ce44SJohn Forte 	uint32_t *ptr1;
4233fcf3ce44SJohn Forte 	uint32_t *ptr2;
4234fcf3ce44SJohn Forte 	PROG_ID BootId[MAX_BOOTID];
4235fcf3ce44SJohn Forte 	uint32_t ChangeParams = FALSE;
4236fcf3ce44SJohn Forte 	WAKE_UP_PARMS WakeUpParms;
4237fcf3ce44SJohn Forte 	caddr_t Sptr;
4238fcf3ce44SJohn Forte 	caddr_t Dptr;
4239fcf3ce44SJohn Forte 
4240fcf3ce44SJohn Forte 	bzero(&BootId, (sizeof (PROG_ID)) * MAX_BOOTID);
4241fcf3ce44SJohn Forte 
4242fcf3ce44SJohn Forte 	/* Read wakeup paramters */
4243fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
4244fcf3ce44SJohn Forte 	    CFG_DATA_NO_REGION) {
4245fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4246fcf3ce44SJohn Forte 		    "Unable to get DWC parameters.");
4247fcf3ce44SJohn Forte 		return (FALSE);
4248fcf3ce44SJohn Forte 	}
4249291a2b48SSukumar Swaminathan 
4250fcf3ce44SJohn Forte 	bcopy((caddr_t)AbsWakeUpParms, (caddr_t)&WakeUpParms,
4251fcf3ce44SJohn Forte 	    sizeof (WAKE_UP_PARMS));
4252fcf3ce44SJohn Forte 
4253fcf3ce44SJohn Forte 	if (((BWCflag == ALL_WITHOUT_BWC) || (extType == DWCext)) &&
4254fcf3ce44SJohn Forte 	    (WakeUpParms.u0.boot_bios_wd[0])) {
4255fcf3ce44SJohn Forte 		*numBootImage = 0;
4256fcf3ce44SJohn Forte 	}
4257291a2b48SSukumar Swaminathan 
4258fcf3ce44SJohn Forte 	/* incoming buffer is without aif header */
4259fcf3ce44SJohn Forte 	NextImage = 0x84 - sizeof (AIF_HDR);
4260fcf3ce44SJohn Forte 	BufferSize -= (sizeof (AIF_HDR) + sizeof (uint32_t));
4261fcf3ce44SJohn Forte 
4262fcf3ce44SJohn Forte 	while (BufferSize > NextImage) {
4263fcf3ce44SJohn Forte 		Sptr = &Buffer[NextImage];
4264fcf3ce44SJohn Forte 		Dptr = (caddr_t)&ImageHdr;
4265fcf3ce44SJohn Forte 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
4266fcf3ce44SJohn Forte 			Dptr[i] = Sptr[i];
4267fcf3ce44SJohn Forte 		}
4268fcf3ce44SJohn Forte 
4269fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff) {
4270fcf3ce44SJohn Forte 			break;
4271fcf3ce44SJohn Forte 		}
4272291a2b48SSukumar Swaminathan 
4273fcf3ce44SJohn Forte 		switch (ImageHdr.Id.Type) {
4274fcf3ce44SJohn Forte 		case TEST_PROGRAM:
4275fcf3ce44SJohn Forte 			break;
4276fcf3ce44SJohn Forte 
4277fcf3ce44SJohn Forte 		case FUNC_FIRMWARE:
4278fcf3ce44SJohn Forte 			AbsWakeUpParms->prog_id = ImageHdr.Id;
4279fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4280fcf3ce44SJohn Forte 			break;
4281fcf3ce44SJohn Forte 
4282fcf3ce44SJohn Forte 		case BOOT_BIOS:
4283fcf3ce44SJohn Forte 			if (!WakeUpParms.u0.boot_bios_wd[0]) {
4284fcf3ce44SJohn Forte 				if (extType == DWCext) {
4285fcf3ce44SJohn Forte 					break;
4286fcf3ce44SJohn Forte 				} else if (BWCflag == ALL_WITHOUT_BWC) {
4287291a2b48SSukumar Swaminathan 					/* for possible future changes */
4288fcf3ce44SJohn Forte 					break;
4289fcf3ce44SJohn Forte 				}
4290fcf3ce44SJohn Forte 			}
4291fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4292fcf3ce44SJohn Forte 
4293fcf3ce44SJohn Forte 			if (*numBootImage < MAX_BOOTID) {
4294fcf3ce44SJohn Forte 				BootId[*numBootImage] = ImageHdr.Id;
4295fcf3ce44SJohn Forte 				(*numBootImage)++;
4296fcf3ce44SJohn Forte 			}
4297fcf3ce44SJohn Forte 			break;
4298fcf3ce44SJohn Forte 
4299fcf3ce44SJohn Forte 		case SLI1_OVERLAY:
4300fcf3ce44SJohn Forte 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
4301fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4302fcf3ce44SJohn Forte 			break;
4303fcf3ce44SJohn Forte 
4304fcf3ce44SJohn Forte 		case SLI2_OVERLAY:
4305fcf3ce44SJohn Forte 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
4306fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4307fcf3ce44SJohn Forte 			break;
4308fcf3ce44SJohn Forte 
4309fcf3ce44SJohn Forte 		case SLI3_OVERLAY:
4310fcf3ce44SJohn Forte 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
4311fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4312fcf3ce44SJohn Forte 			break;
4313fcf3ce44SJohn Forte 
4314fcf3ce44SJohn Forte 		case SLI4_OVERLAY:
4315fcf3ce44SJohn Forte 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
4316fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4317fcf3ce44SJohn Forte 			break;
4318fcf3ce44SJohn Forte 		}
4319fcf3ce44SJohn Forte 
4320fcf3ce44SJohn Forte 		NextImage += ImageHdr.BlockSize;
4321fcf3ce44SJohn Forte 	}
4322fcf3ce44SJohn Forte 
4323fcf3ce44SJohn Forte 	if ((ChangeParams) && ((BWCflag == ALL_WITHOUT_BWC) ||
4324fcf3ce44SJohn Forte 	    (extType == DWCext))) {
4325fcf3ce44SJohn Forte 
4326fcf3ce44SJohn Forte 		if (*numBootImage > 1) {
4327fcf3ce44SJohn Forte 			for (i = 0; i < *numBootImage; i++) {
4328291a2b48SSukumar Swaminathan 				ptr1 =
4329291a2b48SSukumar Swaminathan 				    (uint32_t *)&WakeUpParms.u0.
4330291a2b48SSukumar Swaminathan 				    boot_bios_id;
4331fcf3ce44SJohn Forte 				ptr2 = (uint32_t *)&BootId[i];
4332fcf3ce44SJohn Forte 
4333fcf3ce44SJohn Forte 				if (ptr1[0] == ptr2[0]) {
4334fcf3ce44SJohn Forte 					AbsWakeUpParms->u1.EROM_prog_id =
4335fcf3ce44SJohn Forte 					    BootId[i];
4336fcf3ce44SJohn Forte 					(void) emlxs_update_exp_rom(hba,
4337fcf3ce44SJohn Forte 					    AbsWakeUpParms);
4338fcf3ce44SJohn Forte 					break;
4339fcf3ce44SJohn Forte 				}
4340fcf3ce44SJohn Forte 			}
4341fcf3ce44SJohn Forte 		} else {
4342fcf3ce44SJohn Forte 			if (*numBootImage == 1) {
4343fcf3ce44SJohn Forte 				ptr2 = (uint32_t *)&BootId[0];
4344fcf3ce44SJohn Forte 
4345fcf3ce44SJohn Forte 				if (WakeUpParms.u0.boot_bios_wd[0] == ptr2[0]) {
4346fcf3ce44SJohn Forte 					AbsWakeUpParms->u1.EROM_prog_id =
4347fcf3ce44SJohn Forte 					    BootId[0];
4348fcf3ce44SJohn Forte 					(void) emlxs_update_exp_rom(hba,
4349fcf3ce44SJohn Forte 					    AbsWakeUpParms);
4350fcf3ce44SJohn Forte 				}
4351fcf3ce44SJohn Forte 			}
4352fcf3ce44SJohn Forte 		}
4353fcf3ce44SJohn Forte 	}
4354291a2b48SSukumar Swaminathan 
4355fcf3ce44SJohn Forte 	return (ChangeParams);
4356fcf3ce44SJohn Forte 
4357fcf3ce44SJohn Forte 
4358*82527734SSukumar Swaminathan } /* emlxs_build_parms_2mb_dwc() */
4359fcf3ce44SJohn Forte 
4360fcf3ce44SJohn Forte 
4361fcf3ce44SJohn Forte extern uint32_t
4362fcf3ce44SJohn Forte emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
4363fcf3ce44SJohn Forte     uint32_t *MaxIbusSize)
4364fcf3ce44SJohn Forte {
4365fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4366fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
4367fcf3ce44SJohn Forte 	MAILBOX *mb;
4368fcf3ce44SJohn Forte 	uint32_t *Uptr;
4369fcf3ce44SJohn Forte 	uint32_t rval = 0;
4370fcf3ce44SJohn Forte 
4371291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4372291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
4373fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4374fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
4375fcf3ce44SJohn Forte 
4376fcf3ce44SJohn Forte 		return (1);
4377fcf3ce44SJohn Forte 	}
4378291a2b48SSukumar Swaminathan 
4379fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
4380fcf3ce44SJohn Forte 
4381*82527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
4382fcf3ce44SJohn Forte 
4383*82527734SSukumar Swaminathan 	if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) !=
4384291a2b48SSukumar Swaminathan 	    MBX_SUCCESS) {
4385fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4386fcf3ce44SJohn Forte 		    "Unable to get SRAM size: Mailbox cmd=%x status=%x",
4387fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
4388fcf3ce44SJohn Forte 
4389fcf3ce44SJohn Forte 		rval = 1;
4390fcf3ce44SJohn Forte 
4391fcf3ce44SJohn Forte 		goto Exit_Function;
4392fcf3ce44SJohn Forte 	}
4393291a2b48SSukumar Swaminathan 
4394*82527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4395*82527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
4396*82527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
4397*82527734SSukumar Swaminathan 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
4398*82527734SSukumar Swaminathan 	} else {
4399*82527734SSukumar Swaminathan 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
4400*82527734SSukumar Swaminathan 	}
4401fcf3ce44SJohn Forte 
4402fcf3ce44SJohn Forte 	*MaxRbusSize = Uptr[0];
4403fcf3ce44SJohn Forte 	*MaxIbusSize = Uptr[1];
4404fcf3ce44SJohn Forte 
4405fcf3ce44SJohn Forte Exit_Function:
4406fcf3ce44SJohn Forte 
4407fcf3ce44SJohn Forte 	if (mbox) {
4408fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
4409fcf3ce44SJohn Forte 	}
4410291a2b48SSukumar Swaminathan 
4411fcf3ce44SJohn Forte 	return (rval);
4412fcf3ce44SJohn Forte 
4413*82527734SSukumar Swaminathan } /* emlxs_get_max_sram() */
4414fcf3ce44SJohn Forte 
4415fcf3ce44SJohn Forte 
4416fcf3ce44SJohn Forte static uint32_t
4417fcf3ce44SJohn Forte emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
4418fcf3ce44SJohn Forte {
4419fcf3ce44SJohn Forte 	uint8_t *ptr;
4420fcf3ce44SJohn Forte 	uint8_t ver;
4421fcf3ce44SJohn Forte 
4422fcf3ce44SJohn Forte 	ver = version & 0xff;
4423fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_FF;
4424fcf3ce44SJohn Forte 
4425fcf3ce44SJohn Forte 	while (*ptr) {
4426fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4427fcf3ce44SJohn Forte 			return (1);
4428fcf3ce44SJohn Forte 		}
4429fcf3ce44SJohn Forte 	}
4430fcf3ce44SJohn Forte 
4431fcf3ce44SJohn Forte 	return (0);
4432fcf3ce44SJohn Forte 
4433*82527734SSukumar Swaminathan } /* emlxs_kern_check() */
4434fcf3ce44SJohn Forte 
4435fcf3ce44SJohn Forte static uint32_t
4436fcf3ce44SJohn Forte emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
4437fcf3ce44SJohn Forte {
4438fcf3ce44SJohn Forte 	uint8_t *ptr;
4439fcf3ce44SJohn Forte 	uint8_t ver;
4440fcf3ce44SJohn Forte 
4441fcf3ce44SJohn Forte 	ver = version & 0xff;
4442fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_2;
4443fcf3ce44SJohn Forte 
4444fcf3ce44SJohn Forte 	while (*ptr) {
4445fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4446fcf3ce44SJohn Forte 			return (1);
4447fcf3ce44SJohn Forte 		}
4448fcf3ce44SJohn Forte 	}
4449fcf3ce44SJohn Forte 
4450fcf3ce44SJohn Forte 	return (0);
4451fcf3ce44SJohn Forte 
4452*82527734SSukumar Swaminathan } /* emlxs_stub_check() */
4453fcf3ce44SJohn Forte 
4454fcf3ce44SJohn Forte static uint32_t
4455fcf3ce44SJohn Forte emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
4456fcf3ce44SJohn Forte {
4457fcf3ce44SJohn Forte 	uint8_t *ptr;
4458fcf3ce44SJohn Forte 	uint8_t ver;
4459fcf3ce44SJohn Forte 
4460fcf3ce44SJohn Forte 	ver = version & 0xff;
4461fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_3;
4462fcf3ce44SJohn Forte 
4463fcf3ce44SJohn Forte 	while (*ptr) {
4464fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4465fcf3ce44SJohn Forte 			return (1);
4466fcf3ce44SJohn Forte 		}
4467fcf3ce44SJohn Forte 	}
4468fcf3ce44SJohn Forte 
4469fcf3ce44SJohn Forte 	return (0);
4470fcf3ce44SJohn Forte 
4471*82527734SSukumar Swaminathan } /* emlxs_bios_check() */
4472fcf3ce44SJohn Forte 
4473fcf3ce44SJohn Forte static uint32_t
4474fcf3ce44SJohn Forte emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
4475fcf3ce44SJohn Forte {
4476fcf3ce44SJohn Forte 	uint8_t *ptr;
4477fcf3ce44SJohn Forte 	uint8_t ver;
4478fcf3ce44SJohn Forte 
4479fcf3ce44SJohn Forte 	ver = version & 0xff;
4480fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_6;
4481fcf3ce44SJohn Forte 
4482fcf3ce44SJohn Forte 	while (*ptr) {
4483fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4484fcf3ce44SJohn Forte 			return (1);
4485fcf3ce44SJohn Forte 		}
4486fcf3ce44SJohn Forte 	}
4487fcf3ce44SJohn Forte 
4488fcf3ce44SJohn Forte 	return (0);
4489fcf3ce44SJohn Forte 
4490*82527734SSukumar Swaminathan } /* emlxs_sli1_check() */
4491fcf3ce44SJohn Forte 
4492fcf3ce44SJohn Forte static uint32_t
4493fcf3ce44SJohn Forte emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version)
4494fcf3ce44SJohn Forte {
4495fcf3ce44SJohn Forte 	uint8_t *ptr;
4496fcf3ce44SJohn Forte 	uint8_t ver;
4497fcf3ce44SJohn Forte 
4498fcf3ce44SJohn Forte 	ver = version & 0xff;
4499fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_7;
4500fcf3ce44SJohn Forte 
4501fcf3ce44SJohn Forte 	while (*ptr) {
4502fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4503fcf3ce44SJohn Forte 			return (1);
4504fcf3ce44SJohn Forte 		}
4505fcf3ce44SJohn Forte 	}
4506fcf3ce44SJohn Forte 
4507fcf3ce44SJohn Forte 	return (0);
4508fcf3ce44SJohn Forte 
4509*82527734SSukumar Swaminathan } /* emlxs_sli2_check() */
4510fcf3ce44SJohn Forte 
4511fcf3ce44SJohn Forte static uint32_t
4512fcf3ce44SJohn Forte emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
4513fcf3ce44SJohn Forte {
4514fcf3ce44SJohn Forte 	uint8_t *ptr;
4515fcf3ce44SJohn Forte 	uint8_t ver;
4516fcf3ce44SJohn Forte 
4517fcf3ce44SJohn Forte 	ver = version & 0xff;
4518fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_B;
4519fcf3ce44SJohn Forte 
4520fcf3ce44SJohn Forte 	while (*ptr) {
4521fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4522fcf3ce44SJohn Forte 			return (1);
4523fcf3ce44SJohn Forte 		}
4524fcf3ce44SJohn Forte 	}
4525fcf3ce44SJohn Forte 
4526fcf3ce44SJohn Forte 	return (0);
4527fcf3ce44SJohn Forte 
4528*82527734SSukumar Swaminathan } /* emlxs_sli3_check() */
4529fcf3ce44SJohn Forte 
4530fcf3ce44SJohn Forte 
4531fcf3ce44SJohn Forte static uint32_t
4532fcf3ce44SJohn Forte emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
4533fcf3ce44SJohn Forte {
4534fcf3ce44SJohn Forte 	uint8_t *ptr;
4535fcf3ce44SJohn Forte 	uint8_t ver;
4536fcf3ce44SJohn Forte 
4537fcf3ce44SJohn Forte 	ver = version & 0xff;
4538fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_E;
4539fcf3ce44SJohn Forte 
4540fcf3ce44SJohn Forte 	while (*ptr) {
4541fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4542fcf3ce44SJohn Forte 			return (1);
4543fcf3ce44SJohn Forte 		}
4544fcf3ce44SJohn Forte 	}
4545fcf3ce44SJohn Forte 
4546fcf3ce44SJohn Forte 	return (0);
4547fcf3ce44SJohn Forte 
4548*82527734SSukumar Swaminathan } /* emlxs_sli4_check() */
4549fcf3ce44SJohn Forte 
4550fcf3ce44SJohn Forte 
4551fcf3ce44SJohn Forte static uint32_t
4552fcf3ce44SJohn Forte emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
4553fcf3ce44SJohn Forte {
4554fcf3ce44SJohn Forte 	uint8_t *ptr;
4555fcf3ce44SJohn Forte 	uint8_t ver;
4556fcf3ce44SJohn Forte 
4557fcf3ce44SJohn Forte 	ver = version & 0xff;
4558fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_A;
4559fcf3ce44SJohn Forte 
4560fcf3ce44SJohn Forte 	while (*ptr) {
4561fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
4562fcf3ce44SJohn Forte 			return (1);
4563fcf3ce44SJohn Forte 		}
4564fcf3ce44SJohn Forte 	}
4565fcf3ce44SJohn Forte 
4566fcf3ce44SJohn Forte 	return (0);
4567fcf3ce44SJohn Forte 
4568*82527734SSukumar Swaminathan } /* emlxs_sbus_fcode_check() */
4569fcf3ce44SJohn Forte 
4570fcf3ce44SJohn Forte static uint32_t
4571fcf3ce44SJohn Forte emlxs_type_check(uint32_t type)
4572fcf3ce44SJohn Forte {
4573fcf3ce44SJohn Forte 	if (type == 0xff) {
4574fcf3ce44SJohn Forte 		return (KERNEL_CODE);
4575fcf3ce44SJohn Forte 	}
4576291a2b48SSukumar Swaminathan 
4577fcf3ce44SJohn Forte 	if (type >= MAX_PROG_TYPES) {
4578fcf3ce44SJohn Forte 		return (RESERVED_D);
4579fcf3ce44SJohn Forte 	}
4580291a2b48SSukumar Swaminathan 
4581fcf3ce44SJohn Forte 	return (type);
4582fcf3ce44SJohn Forte 
4583*82527734SSukumar Swaminathan } /* emlxs_type_check() */
4584fcf3ce44SJohn Forte 
4585fcf3ce44SJohn Forte 
4586fcf3ce44SJohn Forte 
4587291a2b48SSukumar Swaminathan extern int32_t
4588fcf3ce44SJohn Forte emlxs_boot_code_disable(emlxs_hba_t *hba)
4589fcf3ce44SJohn Forte {
4590fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4591fcf3ce44SJohn Forte 	PROG_ID Id;
4592fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
4593fcf3ce44SJohn Forte 
4594fcf3ce44SJohn Forte 	vpd = &VPD;
4595fcf3ce44SJohn Forte 
4596fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
4597fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4598fcf3ce44SJohn Forte 		    "emlxs_boot_code_disable: Unable to read wake up parms.");
4599fcf3ce44SJohn Forte 
4600291a2b48SSukumar Swaminathan 		return (FC_FAILURE);
4601fcf3ce44SJohn Forte 	}
4602291a2b48SSukumar Swaminathan 
4603fcf3ce44SJohn Forte 	/* Check if boot code is already disabled */
4604fcf3ce44SJohn Forte 	if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
4605fcf3ce44SJohn Forte 		return (FC_SUCCESS);
4606fcf3ce44SJohn Forte 	}
4607291a2b48SSukumar Swaminathan 
4608fcf3ce44SJohn Forte 	/* Make sure EROM entry has copy of boot bios entry */
4609fcf3ce44SJohn Forte 	if (!(hba->model_info.chip &
4610fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
4611fcf3ce44SJohn Forte 	    (hba->wakeup_parms.u0.boot_bios_wd[0] !=
4612fcf3ce44SJohn Forte 	    hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
4613fcf3ce44SJohn Forte 	    (hba->wakeup_parms.u0.boot_bios_wd[1] !=
4614fcf3ce44SJohn Forte 	    hba->wakeup_parms.u1.EROM_prog_wd[1])) {
4615fcf3ce44SJohn Forte 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
4616fcf3ce44SJohn Forte 		    &hba->wakeup_parms.u0.boot_bios_id, 1);
4617fcf3ce44SJohn Forte 	}
4618291a2b48SSukumar Swaminathan 
4619fcf3ce44SJohn Forte 	/* Update the bios id with a zero id */
4620fcf3ce44SJohn Forte 	/* Don't load the EROM this time */
4621fcf3ce44SJohn Forte 	bzero(&Id, sizeof (PROG_ID));
4622fcf3ce44SJohn Forte 	(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0);
4623fcf3ce44SJohn Forte 
4624fcf3ce44SJohn Forte 	/* Now read the parms again to verify */
4625fcf3ce44SJohn Forte 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
4626fcf3ce44SJohn Forte 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
4627fcf3ce44SJohn Forte 	    vpd->boot_version);
4628fcf3ce44SJohn Forte 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
4629fcf3ce44SJohn Forte 
4630fcf3ce44SJohn Forte 	/* Return the result */
4631291a2b48SSukumar Swaminathan 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
4632291a2b48SSukumar Swaminathan 	    FC_SUCCESS : FC_FAILURE);
4633fcf3ce44SJohn Forte 
4634*82527734SSukumar Swaminathan } /* emlxs_boot_code_disable() */
4635fcf3ce44SJohn Forte 
4636fcf3ce44SJohn Forte 
4637291a2b48SSukumar Swaminathan extern int32_t
4638fcf3ce44SJohn Forte emlxs_boot_code_enable(emlxs_hba_t *hba)
4639fcf3ce44SJohn Forte {
4640fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4641fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
4642fcf3ce44SJohn Forte 	PROG_ID load_list[MAX_LOAD_ENTRY];
4643fcf3ce44SJohn Forte 	uint32_t i;
4644fcf3ce44SJohn Forte 
4645fcf3ce44SJohn Forte 	vpd = &VPD;
4646fcf3ce44SJohn Forte 
4647fcf3ce44SJohn Forte 	/* Read the wakeup parms */
4648fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
4649fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4650fcf3ce44SJohn Forte 		    "emlxs_boot_code_enable: Unable to read wake up parms.");
4651fcf3ce44SJohn Forte 
4652291a2b48SSukumar Swaminathan 		return (FC_FAILURE);
4653fcf3ce44SJohn Forte 	}
4654291a2b48SSukumar Swaminathan 
4655fcf3ce44SJohn Forte 	/* Check if boot code is already enabled */
4656fcf3ce44SJohn Forte 	if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
4657fcf3ce44SJohn Forte 		return (FC_SUCCESS);
4658fcf3ce44SJohn Forte 	}
4659291a2b48SSukumar Swaminathan 
4660fcf3ce44SJohn Forte 	if (!(hba->model_info.chip &
4661fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
4662fcf3ce44SJohn Forte 		if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) {
4663fcf3ce44SJohn Forte 			return (EMLXS_NO_BOOT_CODE);
4664fcf3ce44SJohn Forte 		}
4665291a2b48SSukumar Swaminathan 
4666fcf3ce44SJohn Forte 		/* Update the parms with the boot image id */
4667fcf3ce44SJohn Forte 		/* Don't load the EROM this time */
4668fcf3ce44SJohn Forte 		(void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
4669fcf3ce44SJohn Forte 		    &hba->wakeup_parms.u1.EROM_prog_id, 0);
4670fcf3ce44SJohn Forte 	} else {	/* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
4671291a2b48SSukumar Swaminathan 
4672fcf3ce44SJohn Forte 		if (emlxs_get_load_list(hba, load_list)) {
4673291a2b48SSukumar Swaminathan 			return (FC_FAILURE);
4674fcf3ce44SJohn Forte 		}
4675291a2b48SSukumar Swaminathan 
4676fcf3ce44SJohn Forte 		/* Scan load list for a boot image */
4677fcf3ce44SJohn Forte 		for (i = 0; i < MAX_LOAD_ENTRY; i++) {
4678fcf3ce44SJohn Forte 			if (load_list[i].Type == BOOT_BIOS) {
4679fcf3ce44SJohn Forte 				/* Update the parms with the boot image id */
4680fcf3ce44SJohn Forte 				/* Don't load the EROM this time */
4681fcf3ce44SJohn Forte 				(void) emlxs_update_boot_wakeup_parms(hba,
4682fcf3ce44SJohn Forte 				    &hba->wakeup_parms, &load_list[i], 0);
4683fcf3ce44SJohn Forte 
4684fcf3ce44SJohn Forte 				break;
4685fcf3ce44SJohn Forte 			}
4686fcf3ce44SJohn Forte 		}
4687fcf3ce44SJohn Forte 
4688fcf3ce44SJohn Forte 		if (i == MAX_LOAD_ENTRY) {
4689fcf3ce44SJohn Forte 			return (EMLXS_NO_BOOT_CODE);
4690fcf3ce44SJohn Forte 		}
4691fcf3ce44SJohn Forte 	}
4692fcf3ce44SJohn Forte 
4693fcf3ce44SJohn Forte 	/* Now read the parms again to verify */
4694fcf3ce44SJohn Forte 	(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
4695fcf3ce44SJohn Forte 	emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
4696fcf3ce44SJohn Forte 	    vpd->boot_version);
4697291a2b48SSukumar Swaminathan 	/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
4698fcf3ce44SJohn Forte 
4699fcf3ce44SJohn Forte 	/* return the result */
4700291a2b48SSukumar Swaminathan 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
4701291a2b48SSukumar Swaminathan 	    FC_SUCCESS : FC_FAILURE);
4702fcf3ce44SJohn Forte 
4703*82527734SSukumar Swaminathan } /* emlxs_boot_code_enable() */
4704fcf3ce44SJohn Forte 
4705fcf3ce44SJohn Forte 
4706fcf3ce44SJohn Forte 
4707291a2b48SSukumar Swaminathan extern int32_t
4708fcf3ce44SJohn Forte emlxs_boot_code_state(emlxs_hba_t *hba)
4709fcf3ce44SJohn Forte {
4710fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4711fcf3ce44SJohn Forte 
4712fcf3ce44SJohn Forte 	/* Read the wakeup parms */
4713fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
4714fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4715fcf3ce44SJohn Forte 		    "emlxs_boot_code_state: Unable to read wake up parms.");
4716fcf3ce44SJohn Forte 
4717291a2b48SSukumar Swaminathan 		return (FC_FAILURE);
4718fcf3ce44SJohn Forte 	}
4719291a2b48SSukumar Swaminathan 
4720fcf3ce44SJohn Forte 	/* return the result */
4721291a2b48SSukumar Swaminathan 	return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
4722291a2b48SSukumar Swaminathan 	    FC_SUCCESS : FC_FAILURE);
4723fcf3ce44SJohn Forte 
4724*82527734SSukumar Swaminathan } /* emlxs_boot_code_state() */
4725