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  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan #include <emlxs.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C);
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte #define	MAX_BOOTID	10
33fcf3ce44SJohn Forte 
34291a2b48SSukumar Swaminathan static uint32_t	emlxs_erase_fcode_flash(emlxs_hba_t *hba);
3582527734SSukumar Swaminathan 
36291a2b48SSukumar Swaminathan static uint32_t	emlxs_write_fcode_flash(emlxs_hba_t *hba,
37291a2b48SSukumar Swaminathan 			PIMAGE_HDR ImageHdr, caddr_t Buffer);
38fcf3ce44SJohn Forte 
39291a2b48SSukumar Swaminathan static int32_t	emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
406a573d82SSukumar Swaminathan 			uint32_t BufferSize, PAIF_HDR AifHeader);
41291a2b48SSukumar Swaminathan static uint32_t	emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
42291a2b48SSukumar Swaminathan 			uint32_t Size, emlxs_fw_image_t *fw_image);
4382527734SSukumar Swaminathan static void	emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq,
4482527734SSukumar Swaminathan 			uint32_t Type, uint32_t RegionId, uint32_t WordCnt,
4582527734SSukumar Swaminathan 			uint32_t BaseAddr);
46291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
476a573d82SSukumar Swaminathan 			caddr_t Buffer, uint32_t len,
486a573d82SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
49291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
50291a2b48SSukumar Swaminathan 			uint32_t len, uint32_t offline,
51291a2b48SSukumar Swaminathan 			emlxs_fw_image_t *fw_image);
526a573d82SSukumar Swaminathan static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba,
53291a2b48SSukumar Swaminathan 			caddr_t EntireBuffer, uint32_t FileType,
546a573d82SSukumar Swaminathan 			uint32_t extType);
5582527734SSukumar Swaminathan static void	emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base,
56291a2b48SSukumar Swaminathan 			uint32_t DlByteCount, uint32_t Function,
57291a2b48SSukumar Swaminathan 			uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
58291a2b48SSukumar Swaminathan 			uint8_t MbxCmd, uint32_t StepCmd);
59291a2b48SSukumar Swaminathan static uint32_t	emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
60291a2b48SSukumar Swaminathan 			uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
61291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_exp_rom(emlxs_hba_t *hba,
62291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
63291a2b48SSukumar Swaminathan extern uint32_t	emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
64291a2b48SSukumar Swaminathan 			uint32_t *MaxIbusSize);
6582527734SSukumar Swaminathan static void	emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base,
66291a2b48SSukumar Swaminathan 			uint32_t DlByteCount, uint32_t Function,
67291a2b48SSukumar Swaminathan 			uint32_t Complete, uint32_t BdeAddress,
686a573d82SSukumar Swaminathan 			uint32_t BdeSize, PROG_ID *ProgId, uint32_t keep);
6982527734SSukumar Swaminathan static void	emlxs_format_update_parms(MAILBOXQ *mbq,
70291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
7182527734SSukumar Swaminathan static void	emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
72291a2b48SSukumar Swaminathan 			uint32_t region_id, uint32_t size);
73291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_wakeup_parms(emlxs_hba_t *hba,
74291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS AbsWakeUpParms,
75291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms);
76291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba,
77291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id,
78291a2b48SSukumar Swaminathan 			uint32_t proc_erom);
79291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba,
80291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
81291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba,
82291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
83291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba,
84291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
85291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba,
86291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
87291a2b48SSukumar Swaminathan static uint32_t	emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba,
88291a2b48SSukumar Swaminathan 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
89291a2b48SSukumar Swaminathan static uint32_t	emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
90291a2b48SSukumar Swaminathan 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
916a573d82SSukumar Swaminathan 			uint32_t dwc_flag);
92291a2b48SSukumar Swaminathan static uint32_t	emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
93fcf3ce44SJohn Forte 
94291a2b48SSukumar Swaminathan static uint32_t	emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
9582527734SSukumar Swaminathan 
96291a2b48SSukumar Swaminathan static void	emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr);
9782527734SSukumar Swaminathan 
98291a2b48SSukumar Swaminathan static void	emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
9982527734SSukumar Swaminathan 
100a9800bebSGarrett D'Amore 
101291a2b48SSukumar Swaminathan static uint32_t	emlxs_type_check(uint32_t type);
10282527734SSukumar Swaminathan 
103291a2b48SSukumar Swaminathan static uint32_t	emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
10482527734SSukumar Swaminathan 
105291a2b48SSukumar Swaminathan static uint32_t	emlxs_stub_check(emlxs_hba_t *hba, uint32_t version);
10682527734SSukumar Swaminathan 
107291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version);
10882527734SSukumar Swaminathan 
109291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version);
11082527734SSukumar Swaminathan 
111291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version);
11282527734SSukumar Swaminathan 
113291a2b48SSukumar Swaminathan static uint32_t	emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version);
11482527734SSukumar Swaminathan 
115291a2b48SSukumar Swaminathan static uint32_t	emlxs_bios_check(emlxs_hba_t *hba, uint32_t version);
11682527734SSukumar Swaminathan 
117291a2b48SSukumar Swaminathan static uint32_t	emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version);
11882527734SSukumar Swaminathan 
119291a2b48SSukumar Swaminathan static uint32_t	emlxs_validate_version(emlxs_hba_t *hba,
120291a2b48SSukumar Swaminathan 			emlxs_fw_file_t *file, uint32_t id, uint32_t type,
121291a2b48SSukumar Swaminathan 			char *file_type);
122a9800bebSGarrett D'Amore static uint32_t emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
12382527734SSukumar Swaminathan 			uint32_t len, emlxs_be_fw_image_t *fw_image);
124a9800bebSGarrett D'Amore static uint32_t emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
125a9800bebSGarrett D'Amore 			uint32_t len, emlxs_be_fw_image_t *fw_image);
126a9800bebSGarrett D'Amore 
127a9800bebSGarrett D'Amore 
128*8f23e9faSHans Rosenfeld static int32_t emlxs_be_verify_phy(emlxs_hba_t *hba, emlxs_be_fw_file_t *file,
129*8f23e9faSHans Rosenfeld 			MAILBOXQ *mbq, MATCHMAP *mp);
130*8f23e9faSHans Rosenfeld static int32_t emlxs_be_verify_crc(emlxs_hba_t *hba,
13182527734SSukumar Swaminathan 			emlxs_be_fw_file_t *file,
13282527734SSukumar Swaminathan 			MAILBOXQ *mbq, MATCHMAP *mp);
133*8f23e9faSHans Rosenfeld static int32_t emlxs_be_flash_image(emlxs_hba_t *hba, caddr_t buffer,
13482527734SSukumar Swaminathan 			emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp);
135*8f23e9faSHans Rosenfeld static int32_t emlxs_be_fw_download(emlxs_hba_t *hba, caddr_t buffer,
13682527734SSukumar Swaminathan 			uint32_t len, uint32_t offline);
137*8f23e9faSHans Rosenfeld static int32_t emlxs_obj_fw_download(emlxs_hba_t *hba, caddr_t buffer,
138*8f23e9faSHans Rosenfeld 			uint32_t len, uint32_t offline);
139*8f23e9faSHans Rosenfeld static int32_t emlxs_obj_flash_image(emlxs_hba_t *hba, caddr_t buffer,
140*8f23e9faSHans Rosenfeld 			uint32_t size, MAILBOXQ *mbq, MATCHMAP *mp,
141*8f23e9faSHans Rosenfeld 			uint32_t *change_status);
142*8f23e9faSHans Rosenfeld static uint32_t emlxs_obj_validate_image(emlxs_hba_t *hba, caddr_t buffer,
143*8f23e9faSHans Rosenfeld 			uint32_t len, emlxs_obj_header_t *obj_hdr);
144a9800bebSGarrett D'Amore static uint32_t emlxs_be_version(caddr_t buffer, uint32_t size,
145a9800bebSGarrett D'Amore 			uint32_t *plus_flag);
1466a573d82SSukumar Swaminathan static uint32_t emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer,
1476a573d82SSukumar Swaminathan 			emlxs_fw_image_t *fw_image);
1486a573d82SSukumar Swaminathan static uint32_t emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId);
1496a573d82SSukumar Swaminathan 
1506a573d82SSukumar Swaminathan static void emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *image);
1516a573d82SSukumar Swaminathan 
1526a573d82SSukumar Swaminathan static uint32_t emlxs_clean_flash(emlxs_hba_t *hba,
1536a573d82SSukumar Swaminathan 			PWAKE_UP_PARMS OldWakeUpParms,
1546a573d82SSukumar Swaminathan 			PWAKE_UP_PARMS NewWakeUpParms);
1556a573d82SSukumar Swaminathan 
156291a2b48SSukumar Swaminathan /* ************************************************************************* */
157fcf3ce44SJohn Forte 
158fcf3ce44SJohn Forte extern int32_t
emlxs_fw_download(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline)159fcf3ce44SJohn Forte emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
160fcf3ce44SJohn Forte     uint32_t offline)
161fcf3ce44SJohn Forte {
162fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
163fcf3ce44SJohn Forte 	uint32_t *Uptr;
164fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
165fcf3ce44SJohn Forte 	AIF_HDR AifHdr;
166fcf3ce44SJohn Forte 	uint32_t ImageType;
167fcf3ce44SJohn Forte 	WAKE_UP_PARMS WakeUpParms;
168fcf3ce44SJohn Forte 	uint32_t rval = 0;
169fcf3ce44SJohn Forte 	emlxs_fw_image_t fw_image;
170fcf3ce44SJohn Forte 	uint32_t i;
171fcf3ce44SJohn Forte 
17282527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
173fcf3ce44SJohn Forte 	caddr_t local_buffer;
174fcf3ce44SJohn Forte 	uint32_t *bptr1;
175fcf3ce44SJohn Forte 	uint32_t *bptr2;
17682527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
17782527734SSukumar Swaminathan 
17882527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
179*8f23e9faSHans Rosenfeld 		if (hba->model_info.chip & EMLXS_BE_CHIPS) {
180*8f23e9faSHans Rosenfeld 			rval = emlxs_be_fw_download(hba, buffer, len, offline);
181*8f23e9faSHans Rosenfeld 		} else {
182*8f23e9faSHans Rosenfeld 			rval = emlxs_obj_fw_download(hba, buffer, len, offline);
183*8f23e9faSHans Rosenfeld 		}
18482527734SSukumar Swaminathan 		return (rval);
18582527734SSukumar Swaminathan 	}
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 	if (buffer == NULL || len == 0) {
188fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
189fcf3ce44SJohn Forte 	}
19082527734SSukumar Swaminathan 
19182527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
192fcf3ce44SJohn Forte 	/* We need to swap the image buffer before we start */
193fcf3ce44SJohn Forte 
194fcf3ce44SJohn Forte 	/*
195fcf3ce44SJohn Forte 	 * Use KM_SLEEP to allocate a temporary buffer
196fcf3ce44SJohn Forte 	 */
197fcf3ce44SJohn Forte 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 	/* Perform a 32 bit swap of the image */
200fcf3ce44SJohn Forte 	bptr1 = (uint32_t *)local_buffer;
201fcf3ce44SJohn Forte 	bptr2 = (uint32_t *)buffer;
202fcf3ce44SJohn Forte 	for (i = 0; i < (len / 4); i++) {
20382527734SSukumar Swaminathan 		*bptr1 = LE_SWAP32(*bptr2);
204fcf3ce44SJohn Forte 		bptr1++;
205fcf3ce44SJohn Forte 		bptr2++;
206fcf3ce44SJohn Forte 	}
207fcf3ce44SJohn Forte 
208fcf3ce44SJohn Forte 	/* Replace the original buffer */
209fcf3ce44SJohn Forte 	buffer = local_buffer;
21082527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
211fcf3ce44SJohn Forte 
212fcf3ce44SJohn Forte 	bzero(&fw_image, sizeof (emlxs_fw_image_t));
213fcf3ce44SJohn Forte 	for (i = 0; i < MAX_PROG_TYPES; i++) {
214*8f23e9faSHans Rosenfeld 		(void) strlcpy(fw_image.prog[i].label, "none",
215*8f23e9faSHans Rosenfeld 		    sizeof (fw_image.prog[i].label));
216fcf3ce44SJohn Forte 	}
217fcf3ce44SJohn Forte 
218fcf3ce44SJohn Forte 	/* Validate image */
219fcf3ce44SJohn Forte 	if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) {
220fcf3ce44SJohn Forte 		goto done;
221fcf3ce44SJohn Forte 	}
222291a2b48SSukumar Swaminathan 
2236a573d82SSukumar Swaminathan 	/* Verify image */
2246a573d82SSukumar Swaminathan 	emlxs_verify_image(hba, &fw_image);
2256a573d82SSukumar Swaminathan 
226fcf3ce44SJohn Forte 	/* Get image type */
227fcf3ce44SJohn Forte 	Uptr = (uint32_t *)buffer;
228fcf3ce44SJohn Forte 	ImageType = *Uptr;
229fcf3ce44SJohn Forte 
230fcf3ce44SJohn Forte 	/*
231291a2b48SSukumar Swaminathan 	 * Pegasus and beyond FW download is done differently
232291a2b48SSukumar Swaminathan 	 * for absolute download.
233fcf3ce44SJohn Forte 	 */
234fcf3ce44SJohn Forte 
235fcf3ce44SJohn Forte 	/* Check for absolute image */
236fcf3ce44SJohn Forte 	if ((ImageType == NOP_IMAGE_TYPE) &&
237fcf3ce44SJohn Forte 	    !(hba->model_info.chip &
238fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
239fcf3ce44SJohn Forte 		/*
240fcf3ce44SJohn Forte 		 * Because 2Mb flash download file format is different from
241fcf3ce44SJohn Forte 		 * 512k, it needs to be handled differently
242fcf3ce44SJohn Forte 		 */
243fcf3ce44SJohn Forte 		if (rval = emlxs_start_abs_download_2mb(hba, buffer, len,
244fcf3ce44SJohn Forte 		    offline, &fw_image)) {
245fcf3ce44SJohn Forte 			goto done;
246fcf3ce44SJohn Forte 		}
247291a2b48SSukumar Swaminathan 
248fcf3ce44SJohn Forte 		/* Offline already handled */
249fcf3ce44SJohn Forte 		offline = 0;
250fcf3ce44SJohn Forte 
251fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
252fcf3ce44SJohn Forte 	}
253291a2b48SSukumar Swaminathan 
254fcf3ce44SJohn Forte 	/* Pre-pegasus adapters only */
255fcf3ce44SJohn Forte 
2566a573d82SSukumar Swaminathan 	/* Initialize headers */
2576a573d82SSukumar Swaminathan 	if (ImageType == NOP_IMAGE_TYPE) {
258fcf3ce44SJohn Forte 		bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
259fcf3ce44SJohn Forte 		bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
2606a573d82SSukumar Swaminathan 	} else { /* PRG file */
261fcf3ce44SJohn Forte 		bzero((void *)&AifHdr, sizeof (AIF_HDR));
262fcf3ce44SJohn Forte 		bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
263fcf3ce44SJohn Forte 	}
264fcf3ce44SJohn Forte 
2656a573d82SSukumar Swaminathan 	/* Everything checks out, now to just do it */
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 	if (offline) {
268*8f23e9faSHans Rosenfeld 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
269fcf3ce44SJohn Forte 			offline = 0;
270fcf3ce44SJohn Forte 
271fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
272fcf3ce44SJohn Forte 			    "Unable to take adapter offline.");
273fcf3ce44SJohn Forte 
274fcf3ce44SJohn Forte 			rval = EMLXS_OFFLINE_FAILED;
275fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
276fcf3ce44SJohn Forte 		}
277291a2b48SSukumar Swaminathan 
27882527734SSukumar Swaminathan 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
279fcf3ce44SJohn Forte 			offline = 0;
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
282fcf3ce44SJohn Forte 			    "Unable to restart adapter.");
283fcf3ce44SJohn Forte 
284fcf3ce44SJohn Forte 			rval = EMLXS_OFFLINE_FAILED;
285fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
286fcf3ce44SJohn Forte 		}
287fcf3ce44SJohn Forte 	}
288291a2b48SSukumar Swaminathan 
2896a573d82SSukumar Swaminathan 	/* Pre-pegasus adapters */
2906a573d82SSukumar Swaminathan 
291fcf3ce44SJohn Forte 	if (ImageHdr.Id.Type == SBUS_FCODE) {
292fcf3ce44SJohn Forte 		/* Erase Flash */
293fcf3ce44SJohn Forte 		if (emlxs_erase_fcode_flash(hba)) {
294fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
295fcf3ce44SJohn Forte 			    "Unable to erase flash.");
296fcf3ce44SJohn Forte 
297fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
298fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
299fcf3ce44SJohn Forte 		}
300291a2b48SSukumar Swaminathan 
301fcf3ce44SJohn Forte 		/* Write FCODE */
302fcf3ce44SJohn Forte 		if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) {
303fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
304fcf3ce44SJohn Forte 			    "Unable to write flash.");
305fcf3ce44SJohn Forte 
306fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
307fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
308fcf3ce44SJohn Forte 		}
309291a2b48SSukumar Swaminathan 
3106a573d82SSukumar Swaminathan 		goto SLI_DOWNLOAD_EXIT;
3116a573d82SSukumar Swaminathan 	}
312fcf3ce44SJohn Forte 
3136a573d82SSukumar Swaminathan 	/* Pre-pegasus PCI adapters */
314291a2b48SSukumar Swaminathan 
3156a573d82SSukumar Swaminathan 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
3166a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3176a573d82SSukumar Swaminathan 		    "Unable to get parameters.");
318fcf3ce44SJohn Forte 
3196a573d82SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
320fcf3ce44SJohn Forte 
3216a573d82SSukumar Swaminathan 		goto SLI_DOWNLOAD_EXIT;
3226a573d82SSukumar Swaminathan 	}
323291a2b48SSukumar Swaminathan 
3246a573d82SSukumar Swaminathan 	if (ImageType == NOP_IMAGE_TYPE) {
3256a573d82SSukumar Swaminathan 		if (emlxs_start_abs_download(hba, &AifHdr,
3266a573d82SSukumar Swaminathan 		    buffer, len, &WakeUpParms)) {
3276a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3286a573d82SSukumar Swaminathan 			    &emlxs_download_failed_msg,
3296a573d82SSukumar Swaminathan 			    "Failed to program flash.");
330fcf3ce44SJohn Forte 
331fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
332fcf3ce44SJohn Forte 
333fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
334fcf3ce44SJohn Forte 		}
335291a2b48SSukumar Swaminathan 
3366a573d82SSukumar Swaminathan 	} else { /* Relative PRG file */
3376a573d82SSukumar Swaminathan 		if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
3386a573d82SSukumar Swaminathan 		    &WakeUpParms, 0)) {
3396a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3406a573d82SSukumar Swaminathan 			    &emlxs_download_failed_msg,
3416a573d82SSukumar Swaminathan 			    "Failed to program flash.");
342fcf3ce44SJohn Forte 
3436a573d82SSukumar Swaminathan 			rval = EMLXS_IMAGE_FAILED;
344fcf3ce44SJohn Forte 
3456a573d82SSukumar Swaminathan 			goto SLI_DOWNLOAD_EXIT;
346fcf3ce44SJohn Forte 		}
3476a573d82SSukumar Swaminathan 	}
348fcf3ce44SJohn Forte 
349fcf3ce44SJohn Forte SLI_DOWNLOAD_EXIT:
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte 	if (offline) {
352fcf3ce44SJohn Forte 		(void) emlxs_online(hba);
353fcf3ce44SJohn Forte 	}
354291a2b48SSukumar Swaminathan 
355fcf3ce44SJohn Forte 	if (rval == 0) {
356fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
357fcf3ce44SJohn Forte 		    "Status good.");
358fcf3ce44SJohn Forte 	}
359291a2b48SSukumar Swaminathan 
360fcf3ce44SJohn Forte done:
361fcf3ce44SJohn Forte 
36282527734SSukumar Swaminathan #ifdef EMLXS_LITTLE_ENDIAN
363fcf3ce44SJohn Forte 	/* Free the local buffer */
364fcf3ce44SJohn Forte 	kmem_free(local_buffer, len);
36582527734SSukumar Swaminathan #endif /* EMLXS_LITTLE_ENDIAN */
36682527734SSukumar Swaminathan 
36782527734SSukumar Swaminathan 	return (rval);
36882527734SSukumar Swaminathan 
36982527734SSukumar Swaminathan } /* emlxs_fw_download */
37082527734SSukumar Swaminathan 
37182527734SSukumar Swaminathan 
372a9800bebSGarrett D'Amore extern void
emlxs_memset(uint8_t * buffer,uint8_t value,uint32_t size)37382527734SSukumar Swaminathan emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size)
37482527734SSukumar Swaminathan {
37582527734SSukumar Swaminathan 	while (size--) {
37682527734SSukumar Swaminathan 		*buffer++ = value;
37782527734SSukumar Swaminathan 	}
37882527734SSukumar Swaminathan 
37982527734SSukumar Swaminathan } /* emlxs_memset () */
38082527734SSukumar Swaminathan 
38182527734SSukumar Swaminathan 
38282527734SSukumar Swaminathan static int32_t
emlxs_be_flash_image(emlxs_hba_t * hba,caddr_t buffer,emlxs_be_fw_file_t * file,MAILBOXQ * mbq,MATCHMAP * mp)383*8f23e9faSHans Rosenfeld emlxs_be_flash_image(emlxs_hba_t *hba, caddr_t buffer,
38482527734SSukumar Swaminathan     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
38582527734SSukumar Swaminathan {
38682527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
38782527734SSukumar Swaminathan 	uint8_t *image_ptr;
38882527734SSukumar Swaminathan 	uint32_t *wptr;
38982527734SSukumar Swaminathan 	uint8_t *payload;
39082527734SSukumar Swaminathan 	MAILBOX4 *mb;
39182527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
39282527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
39382527734SSukumar Swaminathan 	uint32_t	image_size;
39482527734SSukumar Swaminathan 	uint32_t	block_size;
39582527734SSukumar Swaminathan 	uint32_t	xfer_size;
39682527734SSukumar Swaminathan 	uint32_t	block_offset;
39782527734SSukumar Swaminathan 	uint32_t	count;
39882527734SSukumar Swaminathan 	uint32_t	rval = 0;
39982527734SSukumar Swaminathan 
40082527734SSukumar Swaminathan 	if (file->image_size == 0) {
40182527734SSukumar Swaminathan 		return (0);
40282527734SSukumar Swaminathan 	}
40382527734SSukumar Swaminathan 
40482527734SSukumar Swaminathan 	image_ptr  = (uint8_t *)buffer + file->image_offset;
40582527734SSukumar Swaminathan 	image_size = file->image_size;
40682527734SSukumar Swaminathan 	block_size = file->block_size;
40782527734SSukumar Swaminathan 	block_offset = 0;
40882527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
40982527734SSukumar Swaminathan 
41082527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
41182527734SSukumar Swaminathan 	    "%s: Downloading...", file->label);
41282527734SSukumar Swaminathan 
41382527734SSukumar Swaminathan 	while (block_size) {
41482527734SSukumar Swaminathan 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
41582527734SSukumar Swaminathan 		bzero((void *) mp->virt, mp->size);
41682527734SSukumar Swaminathan 
41782527734SSukumar Swaminathan 		xfer_size = min(BE_MAX_XFER_SIZE, block_size);
41882527734SSukumar Swaminathan 
41982527734SSukumar Swaminathan 		mb->un.varSLIConfig.be.embedded = 0;
420a9800bebSGarrett D'Amore 		mbq->nonembed = (void *)mp;
42182527734SSukumar Swaminathan 		mbq->mbox_cmpl = NULL;
42282527734SSukumar Swaminathan 
42382527734SSukumar Swaminathan 		mb->mbxCommand = MBX_SLI_CONFIG;
42482527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
42582527734SSukumar Swaminathan 
42682527734SSukumar Swaminathan 		hdr_req = (mbox_req_hdr_t *)mp->virt;
42782527734SSukumar Swaminathan 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
42882527734SSukumar Swaminathan 		hdr_req->opcode = COMMON_OPCODE_WRITE_FLASHROM;
42982527734SSukumar Swaminathan 		hdr_req->timeout = 0;
43082527734SSukumar Swaminathan 		hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
43182527734SSukumar Swaminathan 		    xfer_size;
43282527734SSukumar Swaminathan 
43382527734SSukumar Swaminathan 		flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
434*8f23e9faSHans Rosenfeld 
435*8f23e9faSHans Rosenfeld 		if (file->type == MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
436*8f23e9faSHans Rosenfeld 			flashrom->params.opcode = ((block_size == xfer_size)?
437*8f23e9faSHans Rosenfeld 			    MGMT_PHY_FLASHROM_OPCODE_FLASH:
438*8f23e9faSHans Rosenfeld 			    MGMT_PHY_FLASHROM_OPCODE_SAVE);
439*8f23e9faSHans Rosenfeld 			flashrom->params.optype = 0; /* ignored */
440*8f23e9faSHans Rosenfeld 		} else {
441*8f23e9faSHans Rosenfeld 			flashrom->params.opcode = ((block_size == xfer_size)?
442*8f23e9faSHans Rosenfeld 			    MGMT_FLASHROM_OPCODE_FLASH:
443*8f23e9faSHans Rosenfeld 			    MGMT_FLASHROM_OPCODE_SAVE);
444*8f23e9faSHans Rosenfeld 			flashrom->params.optype = file->type;
445*8f23e9faSHans Rosenfeld 		}
446*8f23e9faSHans Rosenfeld 
44782527734SSukumar Swaminathan 		flashrom->params.data_buffer_size = xfer_size;
44882527734SSukumar Swaminathan 		flashrom->params.offset = block_offset;
44982527734SSukumar Swaminathan 
45082527734SSukumar Swaminathan 		/* Build data buffer payload */
45182527734SSukumar Swaminathan 		payload = (uint8_t *)(&flashrom->params.data_buffer);
45282527734SSukumar Swaminathan 		emlxs_memset(payload, 0xff, xfer_size);
45382527734SSukumar Swaminathan 
45482527734SSukumar Swaminathan 		/* Copy remaining image into payload */
45582527734SSukumar Swaminathan 		if (image_size) {
45682527734SSukumar Swaminathan 			count = min(image_size, xfer_size);
45782527734SSukumar Swaminathan 			BE_SWAP32_BCOPY(image_ptr, payload, count);
45882527734SSukumar Swaminathan 			image_size -= count;
45982527734SSukumar Swaminathan 			image_ptr  += count;
46082527734SSukumar Swaminathan 		}
46182527734SSukumar Swaminathan 
462*8f23e9faSHans Rosenfeld 		if ((flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) ||
463*8f23e9faSHans Rosenfeld 		    (flashrom->params.opcode ==
464*8f23e9faSHans Rosenfeld 		    MGMT_PHY_FLASHROM_OPCODE_FLASH)) {
4656a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&payload[(xfer_size - 12)];
466a9800bebSGarrett D'Amore 
4676a573d82SSukumar Swaminathan 			wptr[0] = file->load_address;
4686a573d82SSukumar Swaminathan 			wptr[1] = file->image_size;
4696a573d82SSukumar Swaminathan 			wptr[2] = file->block_crc;
47082527734SSukumar Swaminathan 		}
47182527734SSukumar Swaminathan 
47282527734SSukumar Swaminathan 		/* Send write request */
47382527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
47482527734SSukumar Swaminathan 		    MBX_SUCCESS) {
47582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
47682527734SSukumar Swaminathan 			    "%s: Unable to download image. status=%x",
47782527734SSukumar Swaminathan 			    file->label, mb->mbxStatus);
47882527734SSukumar Swaminathan 			rval = EMLXS_IMAGE_FAILED;
47982527734SSukumar Swaminathan 			goto done;
48082527734SSukumar Swaminathan 		}
48182527734SSukumar Swaminathan 
48282527734SSukumar Swaminathan 		block_size -= xfer_size;
48382527734SSukumar Swaminathan 		block_offset += xfer_size;
48482527734SSukumar Swaminathan 	}
48582527734SSukumar Swaminathan 
48682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
48782527734SSukumar Swaminathan 	    "%s: Download complete.", file->label);
48882527734SSukumar Swaminathan done:
48982527734SSukumar Swaminathan 
49082527734SSukumar Swaminathan 	return (rval);
49182527734SSukumar Swaminathan 
492*8f23e9faSHans Rosenfeld } /* emlxs_be_flash_image() */
49382527734SSukumar Swaminathan 
49482527734SSukumar Swaminathan 
49582527734SSukumar Swaminathan 
49682527734SSukumar Swaminathan 
49782527734SSukumar Swaminathan static int32_t
emlxs_be_verify_crc(emlxs_hba_t * hba,emlxs_be_fw_file_t * file,MAILBOXQ * mbq,MATCHMAP * mp)498*8f23e9faSHans Rosenfeld emlxs_be_verify_crc(emlxs_hba_t *hba,
49982527734SSukumar Swaminathan     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
50082527734SSukumar Swaminathan {
50182527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
50282527734SSukumar Swaminathan 	uint32_t *wptr;
50382527734SSukumar Swaminathan 	uint8_t *payload;
50482527734SSukumar Swaminathan 	MAILBOX4 *mb;
50582527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
50682527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
50782527734SSukumar Swaminathan 	uint32_t	xfer_size;
50882527734SSukumar Swaminathan 	uint32_t	block_offset;
50982527734SSukumar Swaminathan 	uint32_t	rval = 0;
51082527734SSukumar Swaminathan 	uint32_t	value;
51182527734SSukumar Swaminathan 
512*8f23e9faSHans Rosenfeld 	if (file->type == MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
513*8f23e9faSHans Rosenfeld 		/* PHY Firmware can't be verified */
514*8f23e9faSHans Rosenfeld 		return (1);
515*8f23e9faSHans Rosenfeld 	}
516*8f23e9faSHans Rosenfeld 
51782527734SSukumar Swaminathan 	xfer_size = 8;
51882527734SSukumar Swaminathan 	block_offset = file->block_size - xfer_size;
51982527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
52082527734SSukumar Swaminathan 
52182527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
52282527734SSukumar Swaminathan 	    "%s: Verifying CRC...", file->label);
52382527734SSukumar Swaminathan 
52482527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
52582527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
52682527734SSukumar Swaminathan 
52782527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
528a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
52982527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
53082527734SSukumar Swaminathan 
53182527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
53282527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
53382527734SSukumar Swaminathan 
53482527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
53582527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
53682527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
53782527734SSukumar Swaminathan 	hdr_req->timeout = 0;
53882527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
53982527734SSukumar Swaminathan 	    xfer_size;
54082527734SSukumar Swaminathan 
54182527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
54282527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
54382527734SSukumar Swaminathan 	flashrom->params.optype = file->type;
54482527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
54582527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
54682527734SSukumar Swaminathan 
54782527734SSukumar Swaminathan 	/* Send read request */
54882527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
54982527734SSukumar Swaminathan 	    MBX_SUCCESS) {
55082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
55182527734SSukumar Swaminathan 		    "%s: Unable to read CRC. status=%x",
55282527734SSukumar Swaminathan 		    file->label, mb->mbxStatus);
55382527734SSukumar Swaminathan 
554a9800bebSGarrett D'Amore 		rval = 2;
55582527734SSukumar Swaminathan 		goto done;
55682527734SSukumar Swaminathan 	}
55782527734SSukumar Swaminathan 
55882527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
55982527734SSukumar Swaminathan 	wptr = (uint32_t *)(payload + xfer_size - 8);
56082527734SSukumar Swaminathan 
56182527734SSukumar Swaminathan 	/* Verify image size */
56282527734SSukumar Swaminathan 	value = *wptr++;
56382527734SSukumar Swaminathan 	if (value != file->image_size) {
56482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
56582527734SSukumar Swaminathan 		    "%s: Image size mismatch. %08x != %08x",
56682527734SSukumar Swaminathan 		    file->label, value, file->image_size);
56782527734SSukumar Swaminathan 
568a9800bebSGarrett D'Amore 		rval = 1;
56982527734SSukumar Swaminathan 		goto done;
57082527734SSukumar Swaminathan 	}
57182527734SSukumar Swaminathan 
57282527734SSukumar Swaminathan 	/* Verify block crc */
57382527734SSukumar Swaminathan 	value = *wptr;
57482527734SSukumar Swaminathan 	if (value != file->block_crc) {
57582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
57682527734SSukumar Swaminathan 		    "%s: CRC mismatch. %08x != %08x",
57782527734SSukumar Swaminathan 		    file->label, value, file->block_crc);
578a9800bebSGarrett D'Amore 		rval = 1;
57982527734SSukumar Swaminathan 	}
58082527734SSukumar Swaminathan 
58182527734SSukumar Swaminathan done:
58282527734SSukumar Swaminathan 
58382527734SSukumar Swaminathan 	if (rval == 0) {
58482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
58582527734SSukumar Swaminathan 		    "%s: CRC verified.", file->label);
58682527734SSukumar Swaminathan 	}
58782527734SSukumar Swaminathan 
58882527734SSukumar Swaminathan 	return (rval);
58982527734SSukumar Swaminathan 
590*8f23e9faSHans Rosenfeld } /* emlxs_be_verify_crc() */
591*8f23e9faSHans Rosenfeld 
592*8f23e9faSHans Rosenfeld 
593*8f23e9faSHans Rosenfeld static int32_t
emlxs_be_verify_phy(emlxs_hba_t * hba,emlxs_be_fw_file_t * file,MAILBOXQ * mbq,MATCHMAP * mp)594*8f23e9faSHans Rosenfeld emlxs_be_verify_phy(emlxs_hba_t *hba,
595*8f23e9faSHans Rosenfeld     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
596*8f23e9faSHans Rosenfeld {
597*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
598*8f23e9faSHans Rosenfeld 	MAILBOX4 *mb;
599*8f23e9faSHans Rosenfeld 	IOCTL_COMMON_GET_PHY_DETAILS *phy;
600*8f23e9faSHans Rosenfeld 	mbox_req_hdr_t	*hdr_req;
601*8f23e9faSHans Rosenfeld 	uint32_t	rval = 0;
602*8f23e9faSHans Rosenfeld 
603*8f23e9faSHans Rosenfeld 	if (file->type != MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
604*8f23e9faSHans Rosenfeld 		return (1);
605*8f23e9faSHans Rosenfeld 	}
606*8f23e9faSHans Rosenfeld 
607*8f23e9faSHans Rosenfeld 	mb = (MAILBOX4*)mbq;
608*8f23e9faSHans Rosenfeld 
609*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
610*8f23e9faSHans Rosenfeld 	    "%s: Getting PHY Details...", file->label);
611*8f23e9faSHans Rosenfeld 
612*8f23e9faSHans Rosenfeld 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
613*8f23e9faSHans Rosenfeld 	bzero((void *) mp->virt, mp->size);
614*8f23e9faSHans Rosenfeld 
615*8f23e9faSHans Rosenfeld 	mb->un.varSLIConfig.be.embedded = 0;
616*8f23e9faSHans Rosenfeld 	mbq->nonembed = (void *)mp;
617*8f23e9faSHans Rosenfeld 	mbq->mbox_cmpl = NULL;
618*8f23e9faSHans Rosenfeld 
619*8f23e9faSHans Rosenfeld 	mb->mbxCommand = MBX_SLI_CONFIG;
620*8f23e9faSHans Rosenfeld 	mb->mbxOwner = OWN_HOST;
621*8f23e9faSHans Rosenfeld 
622*8f23e9faSHans Rosenfeld 	hdr_req = (mbox_req_hdr_t *)mp->virt;
623*8f23e9faSHans Rosenfeld 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
624*8f23e9faSHans Rosenfeld 	hdr_req->opcode = COMMON_OPCODE_GET_PHY_DETAILS;
625*8f23e9faSHans Rosenfeld 	hdr_req->timeout = 0;
626*8f23e9faSHans Rosenfeld 	hdr_req->req_length = sizeof (IOCTL_COMMON_GET_PHY_DETAILS);
627*8f23e9faSHans Rosenfeld 
628*8f23e9faSHans Rosenfeld 	phy = (IOCTL_COMMON_GET_PHY_DETAILS *)(hdr_req + 1);
629*8f23e9faSHans Rosenfeld 
630*8f23e9faSHans Rosenfeld 	/* Send read request */
631*8f23e9faSHans Rosenfeld 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
632*8f23e9faSHans Rosenfeld 	    MBX_SUCCESS) {
633*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
634*8f23e9faSHans Rosenfeld 		    "%s: Unable to get PHY details. status=%x",
635*8f23e9faSHans Rosenfeld 		    file->label, mb->mbxStatus);
636*8f23e9faSHans Rosenfeld 
637*8f23e9faSHans Rosenfeld 		rval = 2;
638*8f23e9faSHans Rosenfeld 		goto done;
639*8f23e9faSHans Rosenfeld 	}
640*8f23e9faSHans Rosenfeld 
641*8f23e9faSHans Rosenfeld 	if ((phy->params.response.phy_type != PHY_TN_8022) ||
642*8f23e9faSHans Rosenfeld 	    (phy->params.response.interface_type != BASET_10GB_TYPE)) {
643*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
644*8f23e9faSHans Rosenfeld 		    "%s: PHY not applicable. %08x,%08x",
645*8f23e9faSHans Rosenfeld 		    file->label,
646*8f23e9faSHans Rosenfeld 		    phy->params.response.phy_type,
647*8f23e9faSHans Rosenfeld 		    phy->params.response.interface_type);
648*8f23e9faSHans Rosenfeld 
649*8f23e9faSHans Rosenfeld 		rval = 1;
650*8f23e9faSHans Rosenfeld 	}
651*8f23e9faSHans Rosenfeld 
652*8f23e9faSHans Rosenfeld done:
653*8f23e9faSHans Rosenfeld 
654*8f23e9faSHans Rosenfeld 	if (rval == 0) {
655*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
656*8f23e9faSHans Rosenfeld 		    "%s: PHY verified. %x,%x",
657*8f23e9faSHans Rosenfeld 		    file->label,
658*8f23e9faSHans Rosenfeld 		    phy->params.response.phy_type,
659*8f23e9faSHans Rosenfeld 		    phy->params.response.interface_type);
660*8f23e9faSHans Rosenfeld 	}
661*8f23e9faSHans Rosenfeld 
662*8f23e9faSHans Rosenfeld 	return (rval);
663*8f23e9faSHans Rosenfeld 
664*8f23e9faSHans Rosenfeld } /* emlxs_be_verify_phy() */
66582527734SSukumar Swaminathan 
66682527734SSukumar Swaminathan 
66782527734SSukumar Swaminathan extern int32_t
emlxs_be_read_fw_version(emlxs_hba_t * hba,emlxs_firmware_t * fw)668*8f23e9faSHans Rosenfeld emlxs_be_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw)
66982527734SSukumar Swaminathan {
67082527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
67182527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
67282527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
67382527734SSukumar Swaminathan 	MAILBOX4 *mb;
67482527734SSukumar Swaminathan 	uint32_t *wptr;
67582527734SSukumar Swaminathan 	uint8_t *payload;
67682527734SSukumar Swaminathan 	IOCTL_COMMON_FLASHROM *flashrom;
67782527734SSukumar Swaminathan 	mbox_req_hdr_t	*hdr_req;
67882527734SSukumar Swaminathan 	uint32_t	xfer_size;
67982527734SSukumar Swaminathan 	uint32_t	block_offset;
68082527734SSukumar Swaminathan 	uint32_t	rval = 0;
68182527734SSukumar Swaminathan 
68282527734SSukumar Swaminathan 	bzero((void *) fw, sizeof (emlxs_firmware_t));
68382527734SSukumar Swaminathan 
68482527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
68582527734SSukumar Swaminathan 	    KM_SLEEP)) == NULL) {
68682527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
68782527734SSukumar Swaminathan 		    "read_fw_version: Unable to allocate mailbox buffer.");
68882527734SSukumar Swaminathan 
68982527734SSukumar Swaminathan 		rval = 1;
69082527734SSukumar Swaminathan 		goto done;
69182527734SSukumar Swaminathan 	}
69282527734SSukumar Swaminathan 
69382527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
69482527734SSukumar Swaminathan 	    sizeof (IOCTL_COMMON_FLASHROM) + 32))) == NULL) {
69582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
69682527734SSukumar Swaminathan 		    "read_fw_version: Unable to allocate payload buffer.");
69782527734SSukumar Swaminathan 
69882527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
69982527734SSukumar Swaminathan 		goto done;
70082527734SSukumar Swaminathan 	}
70182527734SSukumar Swaminathan 
70282527734SSukumar Swaminathan 	mb = (MAILBOX4*)mbq;
70382527734SSukumar Swaminathan 
70482527734SSukumar Swaminathan 	/* Read CRC and size */
70582527734SSukumar Swaminathan 	xfer_size = 8;
70682527734SSukumar Swaminathan 	block_offset = 0x140000 - xfer_size;
70782527734SSukumar Swaminathan 
70882527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
70982527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
71082527734SSukumar Swaminathan 
71182527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
712a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
71382527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
71482527734SSukumar Swaminathan 
71582527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
71682527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
71782527734SSukumar Swaminathan 
71882527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
71982527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
72082527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
72182527734SSukumar Swaminathan 	hdr_req->timeout = 0;
72282527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
72382527734SSukumar Swaminathan 	    xfer_size;
72482527734SSukumar Swaminathan 
72582527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
72682527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
72782527734SSukumar Swaminathan 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
72882527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
72982527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
73082527734SSukumar Swaminathan 
73182527734SSukumar Swaminathan 	/* Send read request */
73282527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
73382527734SSukumar Swaminathan 	    MBX_SUCCESS) {
73482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
73582527734SSukumar Swaminathan 		    "read_fw_version: Unable to read CRC. status=%x",
73682527734SSukumar Swaminathan 		    mb->mbxStatus);
73782527734SSukumar Swaminathan 
73882527734SSukumar Swaminathan 		rval = 1;
73982527734SSukumar Swaminathan 		goto done;
74082527734SSukumar Swaminathan 	}
74182527734SSukumar Swaminathan 
74282527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
74382527734SSukumar Swaminathan 
74482527734SSukumar Swaminathan 	wptr = (uint32_t *)payload;
74582527734SSukumar Swaminathan 	fw->size = *wptr++; /* image size */
74682527734SSukumar Swaminathan 	fw->sli4 = *wptr;   /* block crc */
74782527734SSukumar Swaminathan 	fw->kern = *wptr;
74882527734SSukumar Swaminathan 	fw->stub = *wptr;
74982527734SSukumar Swaminathan 
75082527734SSukumar Swaminathan 	/* Read version label */
75182527734SSukumar Swaminathan 	xfer_size = 32;
75282527734SSukumar Swaminathan 	block_offset = 0x30;
75382527734SSukumar Swaminathan 
75482527734SSukumar Swaminathan 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
75582527734SSukumar Swaminathan 	bzero((void *) mp->virt, mp->size);
75682527734SSukumar Swaminathan 
75782527734SSukumar Swaminathan 	mb->un.varSLIConfig.be.embedded = 0;
758a9800bebSGarrett D'Amore 	mbq->nonembed = (void *)mp;
75982527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
76082527734SSukumar Swaminathan 
76182527734SSukumar Swaminathan 	mb->mbxCommand = MBX_SLI_CONFIG;
76282527734SSukumar Swaminathan 	mb->mbxOwner = OWN_HOST;
76382527734SSukumar Swaminathan 
76482527734SSukumar Swaminathan 	hdr_req = (mbox_req_hdr_t *)mp->virt;
76582527734SSukumar Swaminathan 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
76682527734SSukumar Swaminathan 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
76782527734SSukumar Swaminathan 	hdr_req->timeout = 0;
76882527734SSukumar Swaminathan 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
76982527734SSukumar Swaminathan 	    xfer_size;
77082527734SSukumar Swaminathan 
77182527734SSukumar Swaminathan 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
77282527734SSukumar Swaminathan 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
77382527734SSukumar Swaminathan 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
77482527734SSukumar Swaminathan 	flashrom->params.data_buffer_size = xfer_size;
77582527734SSukumar Swaminathan 	flashrom->params.offset = block_offset;
77682527734SSukumar Swaminathan 
77782527734SSukumar Swaminathan 	/* Send read request */
77882527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
77982527734SSukumar Swaminathan 	    MBX_SUCCESS) {
78082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
78182527734SSukumar Swaminathan 		    "read_fw_version: Unable to read version string. status=%x",
78282527734SSukumar Swaminathan 		    mb->mbxStatus);
78382527734SSukumar Swaminathan 
78482527734SSukumar Swaminathan 		rval = 1;
78582527734SSukumar Swaminathan 		goto done;
78682527734SSukumar Swaminathan 	}
78782527734SSukumar Swaminathan 
78882527734SSukumar Swaminathan 	payload = (uint8_t *)(&flashrom->params.data_buffer);
78982527734SSukumar Swaminathan 	BE_SWAP32_BCOPY(payload, (uint8_t *)fw->label, 32);
79082527734SSukumar Swaminathan 
79182527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
79282527734SSukumar Swaminathan 	    "FCOE FIRMWARE: size=%x version=%s (0x%08x)",
79382527734SSukumar Swaminathan 	    fw->size, fw->label, fw->sli4);
79482527734SSukumar Swaminathan 
79582527734SSukumar Swaminathan done:
79682527734SSukumar Swaminathan 
79782527734SSukumar Swaminathan 	if (mbq) {
798a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
79982527734SSukumar Swaminathan 	}
80082527734SSukumar Swaminathan 
80182527734SSukumar Swaminathan 	if (mp) {
802a9800bebSGarrett D'Amore 		emlxs_mem_buf_free(hba, mp);
80382527734SSukumar Swaminathan 	}
80482527734SSukumar Swaminathan 
80582527734SSukumar Swaminathan 	return (rval);
80682527734SSukumar Swaminathan 
807*8f23e9faSHans Rosenfeld } /* emlxs_be_read_fw_version() */
80882527734SSukumar Swaminathan 
80982527734SSukumar Swaminathan 
81082527734SSukumar Swaminathan static uint32_t
emlxs_be_version(caddr_t buffer,uint32_t size,uint32_t * plus_flag)811a9800bebSGarrett D'Amore emlxs_be_version(caddr_t buffer, uint32_t size, uint32_t *plus_flag)
812a9800bebSGarrett D'Amore {
813a9800bebSGarrett D'Amore 	emlxs_be2_ufi_header_t *ufi_hdr;
814a9800bebSGarrett D'Amore 	char signature[BE2_SIGNATURE_SIZE];
815a9800bebSGarrett D'Amore 	uint32_t be_version = 0;
816a9800bebSGarrett D'Amore 
817a9800bebSGarrett D'Amore 	if (size < sizeof (emlxs_be2_ufi_header_t)) {
818a9800bebSGarrett D'Amore 		return (0);
819a9800bebSGarrett D'Amore 	}
820a9800bebSGarrett D'Amore 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
821a9800bebSGarrett D'Amore 
822*8f23e9faSHans Rosenfeld 	(void) snprintf(signature, BE2_SIGNATURE_SIZE, "%s+", BE_SIGNATURE);
823a9800bebSGarrett D'Amore 
824a9800bebSGarrett D'Amore 	/* Check if this is a UFI image */
825a9800bebSGarrett D'Amore 	if (strncmp(signature, (char *)ufi_hdr->signature,
826a9800bebSGarrett D'Amore 	    strlen(BE_SIGNATURE)) != 0) {
827a9800bebSGarrett D'Amore 		return (0);
828a9800bebSGarrett D'Amore 	}
829a9800bebSGarrett D'Amore 
830a9800bebSGarrett D'Amore 	/* Check if this is a UFI plus image */
831a9800bebSGarrett D'Amore 	if (plus_flag) {
832a9800bebSGarrett D'Amore 		/* Check if this is a UFI plus image */
833a9800bebSGarrett D'Amore 		if (strncmp(signature, (char *)ufi_hdr->signature,
834a9800bebSGarrett D'Amore 		    strlen(BE_SIGNATURE)+1) == 0) {
835a9800bebSGarrett D'Amore 			*plus_flag = 1;
836a9800bebSGarrett D'Amore 		} else {
837a9800bebSGarrett D'Amore 			*plus_flag = 0;
838a9800bebSGarrett D'Amore 		}
839a9800bebSGarrett D'Amore 	}
840a9800bebSGarrett D'Amore 
841a9800bebSGarrett D'Amore 	if ((ufi_hdr->build[0] >= '1') && (ufi_hdr->build[0] <= '9')) {
842a9800bebSGarrett D'Amore 		be_version = ufi_hdr->build[0] - '0';
843a9800bebSGarrett D'Amore 	}
844a9800bebSGarrett D'Amore 
845a9800bebSGarrett D'Amore 	return (be_version);
846a9800bebSGarrett D'Amore 
847a9800bebSGarrett D'Amore } /* emlxs_be_version() */
848a9800bebSGarrett D'Amore 
849a9800bebSGarrett D'Amore 
850a9800bebSGarrett D'Amore static uint32_t
emlxs_be2_validate_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,emlxs_be_fw_image_t * fw_image)851a9800bebSGarrett D'Amore emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
85282527734SSukumar Swaminathan     uint32_t len, emlxs_be_fw_image_t *fw_image)
85382527734SSukumar Swaminathan {
85482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
855a9800bebSGarrett D'Amore 	emlxs_be2_ufi_header_t *ufi_hdr;
856a9800bebSGarrett D'Amore 	emlxs_be2_flash_dir_t *flash_dir;
857a9800bebSGarrett D'Amore 	emlxs_be2_flash_entry_t *entry;
85882527734SSukumar Swaminathan 	uint8_t *bptr;
85982527734SSukumar Swaminathan 	uint32_t *wptr;
86082527734SSukumar Swaminathan 	uint32_t i;
86182527734SSukumar Swaminathan 	uint32_t k;
86282527734SSukumar Swaminathan 	uint32_t mask;
86382527734SSukumar Swaminathan 	uint32_t value;
86482527734SSukumar Swaminathan 	uint32_t image_size;
86582527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file;
86682527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file2;
86782527734SSukumar Swaminathan 	uint32_t ufi_plus = 0;
868a9800bebSGarrett D'Amore 	uint32_t be_version = 0;
869a9800bebSGarrett D'Amore 	uint32_t found;
87082527734SSukumar Swaminathan 
87182527734SSukumar Swaminathan 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
87282527734SSukumar Swaminathan 
873a9800bebSGarrett D'Amore 	if (hba->model_info.chip != EMLXS_BE2_CHIP) {
87482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
87582527734SSukumar Swaminathan 		    "Invalid adapter model.");
87682527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
87782527734SSukumar Swaminathan 	}
87882527734SSukumar Swaminathan 
879a9800bebSGarrett D'Amore 	if (len < (sizeof (emlxs_be2_ufi_header_t) +
880a9800bebSGarrett D'Amore 	    sizeof (emlxs_be2_flash_dir_t))) {
88182527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
88282527734SSukumar Swaminathan 		    "Image too small. (%d < %d)",
883a9800bebSGarrett D'Amore 		    len, (sizeof (emlxs_be2_ufi_header_t) +
884a9800bebSGarrett D'Amore 		    sizeof (emlxs_be2_flash_dir_t)));
88582527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
88682527734SSukumar Swaminathan 	}
88782527734SSukumar Swaminathan 
888a9800bebSGarrett D'Amore 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
889a9800bebSGarrett D'Amore 
890a9800bebSGarrett D'Amore 	/* Check if this is a standard BE2 image */
891a9800bebSGarrett D'Amore 	if (be_version != 2) {
89282527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
89382527734SSukumar Swaminathan 		    "Invalid image provided.");
89482527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
89582527734SSukumar Swaminathan 	}
89682527734SSukumar Swaminathan 
897a9800bebSGarrett D'Amore 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
89882527734SSukumar Swaminathan 
89982527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
90082527734SSukumar Swaminathan 	/* Big Endian Swapping */
90182527734SSukumar Swaminathan 	/* Swap ufi header */
90282527734SSukumar Swaminathan 	ufi_hdr->checksum =
90382527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->checksum);
90482527734SSukumar Swaminathan 	ufi_hdr->antidote =
90582527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->antidote);
90682527734SSukumar Swaminathan 	ufi_hdr->controller.vendor_id =
90782527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.vendor_id);
90882527734SSukumar Swaminathan 	ufi_hdr->controller.device_id =
90982527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.device_id);
91082527734SSukumar Swaminathan 	ufi_hdr->controller.sub_vendor_id =
91182527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.sub_vendor_id);
91282527734SSukumar Swaminathan 	ufi_hdr->controller.sub_device_id =
91382527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->controller.sub_device_id);
91482527734SSukumar Swaminathan 	ufi_hdr->file_length =
91582527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->file_length);
91682527734SSukumar Swaminathan 	ufi_hdr->chunk_num =
91782527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->chunk_num);
91882527734SSukumar Swaminathan 	ufi_hdr->chunk_cnt =
91982527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->chunk_cnt);
92082527734SSukumar Swaminathan 	ufi_hdr->image_cnt =
92182527734SSukumar Swaminathan 	    SWAP32(ufi_hdr->image_cnt);
92282527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
92382527734SSukumar Swaminathan 
92482527734SSukumar Swaminathan 	if (len != ufi_hdr->file_length) {
92582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
92682527734SSukumar Swaminathan 		    "Invalid image size (%d != %d)",
92782527734SSukumar Swaminathan 		    len, ufi_hdr->file_length);
92882527734SSukumar Swaminathan 
92982527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
93082527734SSukumar Swaminathan 	}
93182527734SSukumar Swaminathan 
93282527734SSukumar Swaminathan 	/* Scan for flash dir signature */
93382527734SSukumar Swaminathan 	bptr = (uint8_t *)buffer;
93482527734SSukumar Swaminathan 	flash_dir = NULL;
93582527734SSukumar Swaminathan 	for (i = 0; i < len; i++, bptr++) {
93682527734SSukumar Swaminathan 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
93782527734SSukumar Swaminathan 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
938a9800bebSGarrett D'Amore 			flash_dir = (emlxs_be2_flash_dir_t *)bptr;
93982527734SSukumar Swaminathan 			break;
94082527734SSukumar Swaminathan 		}
94182527734SSukumar Swaminathan 	}
94282527734SSukumar Swaminathan 
94382527734SSukumar Swaminathan 	if (!flash_dir) {
94482527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
94582527734SSukumar Swaminathan 		    "Unable to find flash directory.");
94682527734SSukumar Swaminathan 
94782527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
94882527734SSukumar Swaminathan 	}
94982527734SSukumar Swaminathan 
95082527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
95182527734SSukumar Swaminathan 	/* Big Endian Swapping */
95282527734SSukumar Swaminathan 	/* Swap flash dir */
95382527734SSukumar Swaminathan 	flash_dir->header.format_rev =
95482527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.format_rev);
95582527734SSukumar Swaminathan 	flash_dir->header.checksum =
95682527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.checksum);
95782527734SSukumar Swaminathan 	flash_dir->header.antidote =
95882527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.antidote);
95982527734SSukumar Swaminathan 	flash_dir->header.build_num =
96082527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.build_num);
96182527734SSukumar Swaminathan 	flash_dir->header.active_entry_mask =
96282527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.active_entry_mask);
96382527734SSukumar Swaminathan 	flash_dir->header.valid_entry_mask =
96482527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.valid_entry_mask);
96582527734SSukumar Swaminathan 	flash_dir->header.orig_content_mask =
96682527734SSukumar Swaminathan 	    SWAP32(flash_dir->header.orig_content_mask);
96782527734SSukumar Swaminathan 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
96882527734SSukumar Swaminathan 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
96982527734SSukumar Swaminathan 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
97082527734SSukumar Swaminathan 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
97182527734SSukumar Swaminathan 	flash_dir->header.resv4 = SWAP32(flash_dir->header.resv4);
97282527734SSukumar Swaminathan 
97382527734SSukumar Swaminathan 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
97482527734SSukumar Swaminathan 		flash_dir->header.controller[i].vendor_id =
97582527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].vendor_id);
97682527734SSukumar Swaminathan 		flash_dir->header.controller[i].device_id =
97782527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].device_id);
97882527734SSukumar Swaminathan 		flash_dir->header.controller[i].sub_vendor_id =
97982527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
98082527734SSukumar Swaminathan 		flash_dir->header.controller[i].sub_device_id =
98182527734SSukumar Swaminathan 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
98282527734SSukumar Swaminathan 	}
98382527734SSukumar Swaminathan 
98482527734SSukumar Swaminathan 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++,  mask <<= 1) {
98582527734SSukumar Swaminathan 
98682527734SSukumar Swaminathan 		if (!(flash_dir->header.valid_entry_mask & mask)) {
98782527734SSukumar Swaminathan 			continue;
98882527734SSukumar Swaminathan 		}
98982527734SSukumar Swaminathan 
99082527734SSukumar Swaminathan 		entry = &flash_dir->entry[i];
991a9800bebSGarrett D'Amore 
992a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
993a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
994a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
99582527734SSukumar Swaminathan 			continue;
99682527734SSukumar Swaminathan 		}
99782527734SSukumar Swaminathan 
99882527734SSukumar Swaminathan 		flash_dir->entry[i].type =
99982527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].type);
100082527734SSukumar Swaminathan 		flash_dir->entry[i].offset =
100182527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].offset);
100282527734SSukumar Swaminathan 		flash_dir->entry[i].pad_size =
100382527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].pad_size);
100482527734SSukumar Swaminathan 		flash_dir->entry[i].image_size =
100582527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].image_size);
100682527734SSukumar Swaminathan 		flash_dir->entry[i].checksum =
100782527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].checksum);
100882527734SSukumar Swaminathan 		flash_dir->entry[i].entry_point =
100982527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].entry_point);
101082527734SSukumar Swaminathan 		flash_dir->entry[i].resv0 =
101182527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].resv0);
101282527734SSukumar Swaminathan 		flash_dir->entry[i].resv1 =
101382527734SSukumar Swaminathan 		    SWAP32(flash_dir->entry[i].resv1);
101482527734SSukumar Swaminathan 	}
101582527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
101682527734SSukumar Swaminathan 
1017a9800bebSGarrett D'Amore 	/* Verify adapter model */
1018a9800bebSGarrett D'Amore 	found = 0;
1019a9800bebSGarrett D'Amore 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1020a9800bebSGarrett D'Amore 		if (flash_dir->header.controller[i].device_id ==
1021a9800bebSGarrett D'Amore 		    hba->model_info.device_id) {
1022a9800bebSGarrett D'Amore 			found = 1;
1023a9800bebSGarrett D'Amore 		}
1024a9800bebSGarrett D'Amore 	}
1025a9800bebSGarrett D'Amore 
1026a9800bebSGarrett D'Amore 	if (!found) {
1027a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1028a9800bebSGarrett D'Amore 		    "Invalid adapter device id=0x%x.",
1029a9800bebSGarrett D'Amore 		    hba->model_info.device_id);
1030a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1031a9800bebSGarrett D'Amore 	}
1032a9800bebSGarrett D'Amore 
103382527734SSukumar Swaminathan 	/* Build fw_image table */
1034a9800bebSGarrett D'Amore 	fw_image->be_version = 2;
1035a9800bebSGarrett D'Amore 	fw_image->ufi_plus = ufi_plus;
103682527734SSukumar Swaminathan 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) {
103782527734SSukumar Swaminathan 
103882527734SSukumar Swaminathan 		if (!(flash_dir->header.valid_entry_mask & mask)) {
103982527734SSukumar Swaminathan 			continue;
104082527734SSukumar Swaminathan 		}
104182527734SSukumar Swaminathan 
104282527734SSukumar Swaminathan 		entry = &flash_dir->entry[i];
1043a9800bebSGarrett D'Amore 
1044a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
1045a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
1046a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
104782527734SSukumar Swaminathan 			continue;
104882527734SSukumar Swaminathan 		}
104982527734SSukumar Swaminathan 
105082527734SSukumar Swaminathan 		switch (entry->type) {
105182527734SSukumar Swaminathan 		case BE_FLASHTYPE_REDBOOT:
105282527734SSukumar Swaminathan 			file = &fw_image->file[REDBOOT_FLASHTYPE];
1053*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "REDBOOT",
1054*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
105582527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
105682527734SSukumar Swaminathan 			break;
105782527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_BIOS:
105882527734SSukumar Swaminathan 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1059*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "ISCSI BIOS",
1060*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
106182527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
106282527734SSukumar Swaminathan 			break;
106382527734SSukumar Swaminathan 		case BE_FLASHTYPE_PXE_BIOS:
106482527734SSukumar Swaminathan 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1065*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "PXE BIOS",
1066*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
106782527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
106882527734SSukumar Swaminathan 			break;
106982527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_BIOS:
107082527734SSukumar Swaminathan 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1071*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "FCOE BIOS",
1072*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
107382527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
107482527734SSukumar Swaminathan 			break;
107582527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
107682527734SSukumar Swaminathan 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1077*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "ISCSI FIRMWARE",
1078*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
107982527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
108082527734SSukumar Swaminathan 			break;
108182527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_FIRMWARE:
108282527734SSukumar Swaminathan 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1083*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "FCOE FIRMWARE",
1084*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
108582527734SSukumar Swaminathan 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
108682527734SSukumar Swaminathan 			break;
108782527734SSukumar Swaminathan 		case BE_FLASHTYPE_FCOE_BACKUP:
108882527734SSukumar Swaminathan 		case BE_FLASHTYPE_ISCSI_BACKUP:
108982527734SSukumar Swaminathan 			continue;
109082527734SSukumar Swaminathan 
109182527734SSukumar Swaminathan 		default:
109282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
109382527734SSukumar Swaminathan 			    "Unknown image type found.  type=%x",
109482527734SSukumar Swaminathan 			    entry->type);
109582527734SSukumar Swaminathan 			continue;
109682527734SSukumar Swaminathan 		}
109782527734SSukumar Swaminathan 
1098a9800bebSGarrett D'Amore 		file->be_version = fw_image->be_version;
1099a9800bebSGarrett D'Amore 		file->ufi_plus = fw_image->ufi_plus;
110082527734SSukumar Swaminathan 		file->image_size = entry->image_size;
110182527734SSukumar Swaminathan 		image_size = BE_SWAP32(entry->image_size);
110282527734SSukumar Swaminathan 
110382527734SSukumar Swaminathan 		if (ufi_plus) {
110482527734SSukumar Swaminathan 			file->image_offset = entry->offset;
110582527734SSukumar Swaminathan 			file->block_size   = entry->pad_size;
110682527734SSukumar Swaminathan 			file->block_crc    = entry->checksum;
11076a573d82SSukumar Swaminathan 			file->load_address = entry->entry_point;
1108a9800bebSGarrett D'Amore 
110982527734SSukumar Swaminathan 		} else {
111082527734SSukumar Swaminathan 			file->image_offset = entry->offset +
1111a9800bebSGarrett D'Amore 			    sizeof (emlxs_be2_ufi_header_t);
111282527734SSukumar Swaminathan 
111382527734SSukumar Swaminathan 			/* Get entry block size and crc */
111482527734SSukumar Swaminathan 			k = file->image_offset + file->image_size;
111582527734SSukumar Swaminathan 			k &= 0xFFFFFFFC;
111682527734SSukumar Swaminathan 
111782527734SSukumar Swaminathan 			wptr = (uint32_t *)(buffer +  k);
111882527734SSukumar Swaminathan 			for (; k < len; k += 4) {
111982527734SSukumar Swaminathan 				if (*wptr++ == image_size) {
112082527734SSukumar Swaminathan 					/* Calculate block_size */
112182527734SSukumar Swaminathan 					file->block_size = (k + 8) -
112282527734SSukumar Swaminathan 					    file->image_offset;
112382527734SSukumar Swaminathan 
11246a573d82SSukumar Swaminathan 					/* Read load_address */
11256a573d82SSukumar Swaminathan 					value = *(wptr - 2);
11266a573d82SSukumar Swaminathan 					file->load_address = BE_SWAP32(value);
11276a573d82SSukumar Swaminathan 
112882527734SSukumar Swaminathan 					/* Read block_crc */
112982527734SSukumar Swaminathan 					value = *wptr;
113082527734SSukumar Swaminathan 					file->block_crc = BE_SWAP32(value);
113182527734SSukumar Swaminathan 
113282527734SSukumar Swaminathan 					break;
113382527734SSukumar Swaminathan 				}
113482527734SSukumar Swaminathan 			}
113582527734SSukumar Swaminathan 
113682527734SSukumar Swaminathan 			if (k >= len) {
113782527734SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
113882527734SSukumar Swaminathan 				    "%s: End of block not found. offset=%x",
113982527734SSukumar Swaminathan 				    file->label, file->image_offset);
114082527734SSukumar Swaminathan 
114182527734SSukumar Swaminathan 				bzero(fw_image, sizeof (emlxs_be_fw_image_t));
114282527734SSukumar Swaminathan 				return (EMLXS_IMAGE_BAD);
114382527734SSukumar Swaminathan 			}
114482527734SSukumar Swaminathan 		}
114582527734SSukumar Swaminathan 
114682527734SSukumar Swaminathan 		/* Make sure image will fit in block specified */
11476a573d82SSukumar Swaminathan 		if (file->image_size + 12 > file->block_size) {
114882527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
114982527734SSukumar Swaminathan 			    "%s: Image too large for block. image=%x block=%x",
115082527734SSukumar Swaminathan 			    file->label, file->image_size, file->block_size);
115182527734SSukumar Swaminathan 
115282527734SSukumar Swaminathan 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
115382527734SSukumar Swaminathan 			return (EMLXS_IMAGE_BAD);
115482527734SSukumar Swaminathan 		}
115582527734SSukumar Swaminathan 
115682527734SSukumar Swaminathan 		/* Automatically create a backup file entry for firmware */
115782527734SSukumar Swaminathan 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
115882527734SSukumar Swaminathan 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1159a9800bebSGarrett D'Amore 
1160a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1161a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
116282527734SSukumar Swaminathan 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1163*8f23e9faSHans Rosenfeld 			(void) strlcpy(file2->label, "FCOE BACKUP",
1164*8f23e9faSHans Rosenfeld 			    sizeof (file2->label));
116582527734SSukumar Swaminathan 
116682527734SSukumar Swaminathan 			/* Save FCOE version info */
116782527734SSukumar Swaminathan 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1168a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
116982527734SSukumar Swaminathan 			    BE_VERSION_SIZE);
1170a9800bebSGarrett D'Amore 			fw_image->fcoe_version = file->block_crc;
117182527734SSukumar Swaminathan 
117282527734SSukumar Swaminathan 		} else if (file->type ==
117382527734SSukumar Swaminathan 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
117482527734SSukumar Swaminathan 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1175a9800bebSGarrett D'Amore 
1176a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1177a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
1178a9800bebSGarrett D'Amore 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1179*8f23e9faSHans Rosenfeld 			(void) strlcpy(file2->label, "ISCSI BACKUP",
1180*8f23e9faSHans Rosenfeld 			    sizeof (file2->label));
1181a9800bebSGarrett D'Amore 
1182a9800bebSGarrett D'Amore 			/* Save ISCSI version info */
1183a9800bebSGarrett D'Amore 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1184a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1185a9800bebSGarrett D'Amore 			    BE_VERSION_SIZE);
1186a9800bebSGarrett D'Amore 			fw_image->iscsi_version = file->block_crc;
1187a9800bebSGarrett D'Amore 		}
1188a9800bebSGarrett D'Amore 	}
1189a9800bebSGarrett D'Amore 
1190a9800bebSGarrett D'Amore 	if (fw_image->fcoe_version == 0) {
1191a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1192a9800bebSGarrett D'Amore 		    "Unable to find FCOE firmware component.");
1193a9800bebSGarrett D'Amore 
1194a9800bebSGarrett D'Amore 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1195a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1196a9800bebSGarrett D'Amore 	}
1197a9800bebSGarrett D'Amore 
1198a9800bebSGarrett D'Amore 	/* Display contents */
1199a9800bebSGarrett D'Amore 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1200a9800bebSGarrett D'Amore 	    "BE2 UFI Image: %08x, %s", fw_image->fcoe_version,
1201a9800bebSGarrett D'Amore 	    fw_image->fcoe_label);
1202a9800bebSGarrett D'Amore 
1203a9800bebSGarrett D'Amore 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1204a9800bebSGarrett D'Amore 		file = &fw_image->file[i];
1205a9800bebSGarrett D'Amore 
1206a9800bebSGarrett D'Amore 		if (file->image_size == 0) {
1207a9800bebSGarrett D'Amore 			continue;
1208a9800bebSGarrett D'Amore 		}
1209a9800bebSGarrett D'Amore 
1210a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1211a9800bebSGarrett D'Amore 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1212a9800bebSGarrett D'Amore 		    "load=%x",
1213a9800bebSGarrett D'Amore 		    file->label, file->be_version, (file->ufi_plus)?"+":"",
1214a9800bebSGarrett D'Amore 		    file->type, file->block_size, file->image_size,
1215a9800bebSGarrett D'Amore 		    file->image_offset, file->block_crc, file->load_address);
1216a9800bebSGarrett D'Amore 	}
1217a9800bebSGarrett D'Amore 
1218a9800bebSGarrett D'Amore 	return (0);
1219a9800bebSGarrett D'Amore 
1220a9800bebSGarrett D'Amore } /* emlxs_be2_validate_image() */
1221a9800bebSGarrett D'Amore 
1222a9800bebSGarrett D'Amore 
1223a9800bebSGarrett D'Amore static uint32_t
emlxs_be3_validate_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,emlxs_be_fw_image_t * fw_image)1224a9800bebSGarrett D'Amore emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
1225a9800bebSGarrett D'Amore     uint32_t len, emlxs_be_fw_image_t *fw_image)
1226a9800bebSGarrett D'Amore {
1227a9800bebSGarrett D'Amore 	emlxs_port_t *port = &PPORT;
1228a9800bebSGarrett D'Amore 	emlxs_be3_ufi_header_t *ufi_hdr;
1229a9800bebSGarrett D'Amore 	emlxs_be3_flash_dir_t *flash_dir;
1230a9800bebSGarrett D'Amore 	emlxs_be3_flash_entry_t *entry;
1231a9800bebSGarrett D'Amore 	emlxs_be3_image_header_t *flash_image_hdr;
1232a9800bebSGarrett D'Amore 	emlxs_be3_image_header_t *image_hdr;
1233a9800bebSGarrett D'Amore 	uint8_t *bptr;
1234a9800bebSGarrett D'Amore 	uint32_t *wptr;
1235a9800bebSGarrett D'Amore 	uint32_t i;
1236a9800bebSGarrett D'Amore 	uint32_t value;
1237a9800bebSGarrett D'Amore 	emlxs_be_fw_file_t *file;
1238a9800bebSGarrett D'Amore 	emlxs_be_fw_file_t *file2;
1239a9800bebSGarrett D'Amore 	uint32_t ufi_plus = 0;
1240a9800bebSGarrett D'Amore 	uint32_t be_version = 0;
1241a9800bebSGarrett D'Amore 	uint32_t found;
1242a9800bebSGarrett D'Amore 
1243a9800bebSGarrett D'Amore 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1244a9800bebSGarrett D'Amore 
1245a9800bebSGarrett D'Amore 	if (hba->model_info.chip != EMLXS_BE3_CHIP) {
1246a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1247a9800bebSGarrett D'Amore 		    "Invalid adapter model.");
1248a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1249a9800bebSGarrett D'Amore 	}
1250a9800bebSGarrett D'Amore 
1251a9800bebSGarrett D'Amore 	if (len < (sizeof (emlxs_be3_ufi_header_t) +
1252a9800bebSGarrett D'Amore 	    sizeof (emlxs_be3_flash_dir_t))) {
1253a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1254a9800bebSGarrett D'Amore 		    "Image too small. (%d < %d)",
1255a9800bebSGarrett D'Amore 		    len, (sizeof (emlxs_be3_ufi_header_t) +
1256a9800bebSGarrett D'Amore 		    sizeof (emlxs_be3_flash_dir_t)));
1257a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1258a9800bebSGarrett D'Amore 	}
1259a9800bebSGarrett D'Amore 
1260a9800bebSGarrett D'Amore 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
1261a9800bebSGarrett D'Amore 
1262a9800bebSGarrett D'Amore 	/* Check if this is a standard BE3 image */
1263a9800bebSGarrett D'Amore 	if (be_version != 3) {
1264a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1265a9800bebSGarrett D'Amore 		    "Invalid image provided.");
1266a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1267a9800bebSGarrett D'Amore 	}
1268a9800bebSGarrett D'Amore 
1269a9800bebSGarrett D'Amore 	ufi_hdr = (emlxs_be3_ufi_header_t *)buffer;
1270a9800bebSGarrett D'Amore 
1271a9800bebSGarrett D'Amore #ifdef EMLXS_BIG_ENDIAN
1272a9800bebSGarrett D'Amore 	/* Big Endian Swapping */
1273a9800bebSGarrett D'Amore 	/* Swap ufi header */
1274a9800bebSGarrett D'Amore 	ufi_hdr->ufi_version =
1275a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->ufi_version);
1276a9800bebSGarrett D'Amore 	ufi_hdr->file_length =
1277a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->file_length);
1278a9800bebSGarrett D'Amore 	ufi_hdr->checksum =
1279a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->checksum);
1280a9800bebSGarrett D'Amore 	ufi_hdr->antidote =
1281a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->antidote);
1282a9800bebSGarrett D'Amore 	ufi_hdr->image_cnt =
1283a9800bebSGarrett D'Amore 	    SWAP32(ufi_hdr->image_cnt);
1284a9800bebSGarrett D'Amore #endif /* EMLXS_BIG_ENDIAN */
1285a9800bebSGarrett D'Amore 
1286a9800bebSGarrett D'Amore 	if (len != ufi_hdr->file_length) {
1287a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1288a9800bebSGarrett D'Amore 		    "Invalid image size (%d != %d)",
1289a9800bebSGarrett D'Amore 		    len, ufi_hdr->file_length);
1290a9800bebSGarrett D'Amore 
1291a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1292a9800bebSGarrett D'Amore 	}
1293a9800bebSGarrett D'Amore 
1294a9800bebSGarrett D'Amore 	flash_image_hdr = NULL;
1295a9800bebSGarrett D'Amore 	image_hdr = (emlxs_be3_image_header_t *)(buffer +
1296a9800bebSGarrett D'Amore 	    sizeof (emlxs_be3_ufi_header_t));
1297a9800bebSGarrett D'Amore 	for (i = 0; i < ufi_hdr->image_cnt; i++, image_hdr++) {
1298a9800bebSGarrett D'Amore #ifdef EMLXS_BIG_ENDIAN
1299a9800bebSGarrett D'Amore 		image_hdr->id = SWAP32(image_hdr->id);
1300a9800bebSGarrett D'Amore 		image_hdr->offset = SWAP32(image_hdr->offset);
1301a9800bebSGarrett D'Amore 		image_hdr->length = SWAP32(image_hdr->length);
1302a9800bebSGarrett D'Amore 		image_hdr->checksum = SWAP32(image_hdr->checksum);
1303a9800bebSGarrett D'Amore #endif /* EMLXS_BIG_ENDIAN */
1304a9800bebSGarrett D'Amore 
1305a9800bebSGarrett D'Amore 		if (image_hdr->id == UFI_BE3_FLASH_ID) {
1306a9800bebSGarrett D'Amore 			flash_image_hdr = image_hdr;
1307a9800bebSGarrett D'Amore 		}
1308a9800bebSGarrett D'Amore 	}
1309a9800bebSGarrett D'Amore 
1310a9800bebSGarrett D'Amore 	if (!flash_image_hdr) {
1311a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1312a9800bebSGarrett D'Amore 		    "No flash image found.");
1313a9800bebSGarrett D'Amore 
1314a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1315a9800bebSGarrett D'Amore 	}
1316a9800bebSGarrett D'Amore 
1317a9800bebSGarrett D'Amore 	/* Scan for flash dir signature */
1318a9800bebSGarrett D'Amore 	bptr = (uint8_t *)buffer + flash_image_hdr->offset;
1319a9800bebSGarrett D'Amore 	flash_dir = NULL;
1320a9800bebSGarrett D'Amore 	for (i = 0; i < flash_image_hdr->length; i++, bptr++) {
1321a9800bebSGarrett D'Amore 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
1322a9800bebSGarrett D'Amore 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
1323a9800bebSGarrett D'Amore 			flash_dir = (emlxs_be3_flash_dir_t *)bptr;
1324a9800bebSGarrett D'Amore 			break;
1325a9800bebSGarrett D'Amore 		}
1326a9800bebSGarrett D'Amore 	}
1327a9800bebSGarrett D'Amore 
1328a9800bebSGarrett D'Amore 	if (!flash_dir) {
1329a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1330a9800bebSGarrett D'Amore 		    "Unable to find flash directory.");
1331a9800bebSGarrett D'Amore 
1332a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1333a9800bebSGarrett D'Amore 	}
1334a9800bebSGarrett D'Amore 
1335a9800bebSGarrett D'Amore #ifdef EMLXS_BIG_ENDIAN
1336a9800bebSGarrett D'Amore 	/* Big Endian Swapping */
1337a9800bebSGarrett D'Amore 	/* Swap flash dir */
1338a9800bebSGarrett D'Amore 	flash_dir->header.format_rev =
1339a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.format_rev);
1340a9800bebSGarrett D'Amore 	flash_dir->header.checksum =
1341a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.checksum);
1342a9800bebSGarrett D'Amore 	flash_dir->header.antidote =
1343a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.antidote);
1344a9800bebSGarrett D'Amore 	flash_dir->header.entry_count =
1345a9800bebSGarrett D'Amore 	    SWAP32(flash_dir->header.entry_count);
1346a9800bebSGarrett D'Amore 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
1347a9800bebSGarrett D'Amore 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
1348a9800bebSGarrett D'Amore 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
1349a9800bebSGarrett D'Amore 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
1350a9800bebSGarrett D'Amore 
1351a9800bebSGarrett D'Amore 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1352a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].vendor_id =
1353a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].vendor_id);
1354a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].device_id =
1355a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].device_id);
1356a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].sub_vendor_id =
1357a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
1358a9800bebSGarrett D'Amore 		flash_dir->header.controller[i].sub_device_id =
1359a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
1360a9800bebSGarrett D'Amore 	}
1361a9800bebSGarrett D'Amore 
1362a9800bebSGarrett D'Amore 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1363a9800bebSGarrett D'Amore 		entry = &flash_dir->entry[i];
1364a9800bebSGarrett D'Amore 
1365a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
1366a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
1367a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
1368a9800bebSGarrett D'Amore 			continue;
1369a9800bebSGarrett D'Amore 		}
1370a9800bebSGarrett D'Amore 
1371a9800bebSGarrett D'Amore 		flash_dir->entry[i].type =
1372a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].type);
1373a9800bebSGarrett D'Amore 		flash_dir->entry[i].offset =
1374a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].offset);
1375a9800bebSGarrett D'Amore 		flash_dir->entry[i].block_size =
1376a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].block_size);
1377a9800bebSGarrett D'Amore 		flash_dir->entry[i].image_size =
1378a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].image_size);
1379a9800bebSGarrett D'Amore 		flash_dir->entry[i].checksum =
1380a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].checksum);
1381a9800bebSGarrett D'Amore 		flash_dir->entry[i].entry_point =
1382a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].entry_point);
1383a9800bebSGarrett D'Amore 		flash_dir->entry[i].resv0 =
1384a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].resv0);
1385a9800bebSGarrett D'Amore 		flash_dir->entry[i].resv1 =
1386a9800bebSGarrett D'Amore 		    SWAP32(flash_dir->entry[i].resv1);
1387a9800bebSGarrett D'Amore 	}
1388a9800bebSGarrett D'Amore #endif /* EMLXS_BIG_ENDIAN */
1389a9800bebSGarrett D'Amore 
1390a9800bebSGarrett D'Amore 	/* Verify image checksum */
1391a9800bebSGarrett D'Amore 	if (flash_dir->header.checksum != flash_image_hdr->checksum) {
1392a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1393a9800bebSGarrett D'Amore 		    "Invalid flash directory checksum. (%x != %x)\n",
1394a9800bebSGarrett D'Amore 		    flash_dir->header.checksum, flash_image_hdr->checksum);
1395a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_BAD);
1396a9800bebSGarrett D'Amore 	}
1397a9800bebSGarrett D'Amore 
1398a9800bebSGarrett D'Amore 	/* Verify adapter model */
1399a9800bebSGarrett D'Amore 	found = 0;
1400a9800bebSGarrett D'Amore 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1401a9800bebSGarrett D'Amore 		if (flash_dir->header.controller[i].device_id ==
1402a9800bebSGarrett D'Amore 		    hba->model_info.device_id) {
1403a9800bebSGarrett D'Amore 			found = 1;
1404a9800bebSGarrett D'Amore 		}
1405a9800bebSGarrett D'Amore 	}
1406a9800bebSGarrett D'Amore 
1407a9800bebSGarrett D'Amore 	if (!found) {
1408a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1409a9800bebSGarrett D'Amore 		    "Invalid adapter device id=0x%x.",
1410a9800bebSGarrett D'Amore 		    hba->model_info.device_id);
1411a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1412a9800bebSGarrett D'Amore 	}
1413a9800bebSGarrett D'Amore 
1414a9800bebSGarrett D'Amore 	/* Build fw_image table */
1415a9800bebSGarrett D'Amore 	fw_image->be_version = 3;
1416a9800bebSGarrett D'Amore 	fw_image->ufi_plus = ufi_plus;
1417a9800bebSGarrett D'Amore 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1418a9800bebSGarrett D'Amore 		entry = &flash_dir->entry[i];
1419a9800bebSGarrett D'Amore 
1420a9800bebSGarrett D'Amore 		if ((entry->type == 0) ||
1421a9800bebSGarrett D'Amore 		    (entry->type == (uint32_t)-1) ||
1422a9800bebSGarrett D'Amore 		    (entry->image_size == 0)) {
1423a9800bebSGarrett D'Amore 			continue;
1424a9800bebSGarrett D'Amore 		}
1425a9800bebSGarrett D'Amore 
1426a9800bebSGarrett D'Amore 		switch (entry->type) {
1427a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_REDBOOT:
1428a9800bebSGarrett D'Amore 			file = &fw_image->file[REDBOOT_FLASHTYPE];
1429*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "REDBOOT",
1430*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1431a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
1432a9800bebSGarrett D'Amore 			break;
1433a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_ISCSI_BIOS:
1434a9800bebSGarrett D'Amore 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1435*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "ISCSI BIOS",
1436*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1437a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
1438a9800bebSGarrett D'Amore 			break;
1439a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_PXE_BIOS:
1440a9800bebSGarrett D'Amore 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1441*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "PXE BIOS",
1442*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1443a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
1444a9800bebSGarrett D'Amore 			break;
1445a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FCOE_BIOS:
1446a9800bebSGarrett D'Amore 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1447*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "FCOE BIOS",
1448*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1449a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
1450a9800bebSGarrett D'Amore 			break;
1451a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
1452a9800bebSGarrett D'Amore 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1453*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "ISCSI FIRMWARE",
1454*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1455a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
1456a9800bebSGarrett D'Amore 			break;
1457a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FCOE_FIRMWARE:
1458a9800bebSGarrett D'Amore 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1459*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "FCOE FIRMWARE",
1460*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1461a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
1462a9800bebSGarrett D'Amore 			break;
1463a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_NCSI_FIRMWARE:
1464a9800bebSGarrett D'Amore 			file = &fw_image->file[NCSI_FIRMWARE_FLASHTYPE];
1465*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "NCSI FIRMWARE",
1466*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1467a9800bebSGarrett D'Amore 			file->type = MGMT_FLASHROM_OPTYPE_NCSI_FIRMWARE;
1468a9800bebSGarrett D'Amore 			break;
1469a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FLASH_ISM:
1470a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_FCOE_BACKUP:
1471a9800bebSGarrett D'Amore 		case BE_FLASHTYPE_ISCSI_BACKUP:
1472a9800bebSGarrett D'Amore 			continue;
1473*8f23e9faSHans Rosenfeld 		case BE_FLASHTYPE_PHY_FIRMWARE:
1474*8f23e9faSHans Rosenfeld 			file = &fw_image->file[PHY_FIRMWARE_FLASHTYPE];
1475*8f23e9faSHans Rosenfeld 			(void) strlcpy(file->label, "PHY FIRMWARE",
1476*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1477*8f23e9faSHans Rosenfeld 			file->type = MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE;
1478*8f23e9faSHans Rosenfeld 			break;
1479a9800bebSGarrett D'Amore 
1480a9800bebSGarrett D'Amore 		default:
1481a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1482a9800bebSGarrett D'Amore 			    "Unknown image type found.  type=%x",
1483a9800bebSGarrett D'Amore 			    entry->type);
1484a9800bebSGarrett D'Amore 			continue;
1485a9800bebSGarrett D'Amore 		}
1486a9800bebSGarrett D'Amore 
1487a9800bebSGarrett D'Amore 		file->be_version = fw_image->be_version;
1488a9800bebSGarrett D'Amore 		file->ufi_plus = fw_image->ufi_plus;
1489a9800bebSGarrett D'Amore 		file->image_size = entry->image_size;
1490a9800bebSGarrett D'Amore 
1491a9800bebSGarrett D'Amore 		if (ufi_plus) {
1492a9800bebSGarrett D'Amore 			file->image_offset = entry->offset;
1493a9800bebSGarrett D'Amore 			file->block_size   = entry->block_size;
1494a9800bebSGarrett D'Amore 			file->block_crc    = entry->checksum;
1495a9800bebSGarrett D'Amore 			file->load_address = entry->entry_point;
1496a9800bebSGarrett D'Amore 		} else {
1497a9800bebSGarrett D'Amore 			file->image_offset = entry->offset +
1498a9800bebSGarrett D'Amore 			    flash_image_hdr->offset;
1499a9800bebSGarrett D'Amore 			file->block_size   = entry->block_size;
1500a9800bebSGarrett D'Amore 
1501a9800bebSGarrett D'Amore 			wptr = (uint32_t *)(buffer +  file->image_offset +
1502a9800bebSGarrett D'Amore 			    file->block_size);
1503a9800bebSGarrett D'Amore 
1504a9800bebSGarrett D'Amore 			/* Read load address */
1505a9800bebSGarrett D'Amore 			value = *(wptr - 3);
1506a9800bebSGarrett D'Amore 			file->load_address = BE_SWAP32(value);
1507a9800bebSGarrett D'Amore 
1508a9800bebSGarrett D'Amore 			/* Read block_crc */
1509a9800bebSGarrett D'Amore 			value = *(wptr - 1);
1510a9800bebSGarrett D'Amore 			file->block_crc = BE_SWAP32(value);
1511a9800bebSGarrett D'Amore 		}
1512a9800bebSGarrett D'Amore 
1513a9800bebSGarrett D'Amore 		/* Make sure image will fit in block specified */
1514a9800bebSGarrett D'Amore 		if (file->image_size + 12 > file->block_size) {
1515a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1516a9800bebSGarrett D'Amore 			    "%s: Image too large for block. image=%x block=%x",
1517a9800bebSGarrett D'Amore 			    file->label, file->image_size, file->block_size);
1518a9800bebSGarrett D'Amore 
1519a9800bebSGarrett D'Amore 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1520a9800bebSGarrett D'Amore 			return (EMLXS_IMAGE_BAD);
1521a9800bebSGarrett D'Amore 		}
1522a9800bebSGarrett D'Amore 
1523a9800bebSGarrett D'Amore 		/* Automatically create a backup file entry for firmware */
1524a9800bebSGarrett D'Amore 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1525a9800bebSGarrett D'Amore 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1526a9800bebSGarrett D'Amore 
1527a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1528a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
1529a9800bebSGarrett D'Amore 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1530*8f23e9faSHans Rosenfeld 			(void) strlcpy(file2->label, "FCOE BACKUP",
1531*8f23e9faSHans Rosenfeld 			    sizeof (file2->label));
1532a9800bebSGarrett D'Amore 
1533a9800bebSGarrett D'Amore 			/* Save FCOE version info */
1534a9800bebSGarrett D'Amore 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1535a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
1536a9800bebSGarrett D'Amore 			    BE_VERSION_SIZE);
1537a9800bebSGarrett D'Amore 			fw_image->fcoe_version = file->block_crc;
1538a9800bebSGarrett D'Amore 
1539a9800bebSGarrett D'Amore 		} else if (file->type ==
1540a9800bebSGarrett D'Amore 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1541a9800bebSGarrett D'Amore 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1542a9800bebSGarrett D'Amore 
1543a9800bebSGarrett D'Amore 			bcopy((uint8_t *)file, (uint8_t *)file2,
1544a9800bebSGarrett D'Amore 			    sizeof (emlxs_be_fw_file_t));
154582527734SSukumar Swaminathan 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1546*8f23e9faSHans Rosenfeld 			(void) strlcpy(file2->label, "ISCSI BACKUP",
1547*8f23e9faSHans Rosenfeld 			    sizeof (file->label));
1548a9800bebSGarrett D'Amore 
1549a9800bebSGarrett D'Amore 			/* Save ISCSI version info */
1550a9800bebSGarrett D'Amore 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1551a9800bebSGarrett D'Amore 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1552a9800bebSGarrett D'Amore 			    BE_VERSION_SIZE);
1553a9800bebSGarrett D'Amore 			fw_image->iscsi_version = file->block_crc;
155482527734SSukumar Swaminathan 		}
155582527734SSukumar Swaminathan 	}
155682527734SSukumar Swaminathan 
1557a9800bebSGarrett D'Amore 	if (fw_image->fcoe_version == 0) {
155882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
155982527734SSukumar Swaminathan 		    "Unable to find FCOE firmware component.");
156082527734SSukumar Swaminathan 
156182527734SSukumar Swaminathan 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
156282527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
156382527734SSukumar Swaminathan 	}
156482527734SSukumar Swaminathan 
156582527734SSukumar Swaminathan 	/* Display contents */
156682527734SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1567a9800bebSGarrett D'Amore 	    "BE3 UFI Image: %08x, %s", fw_image->fcoe_version,
1568a9800bebSGarrett D'Amore 	    fw_image->fcoe_label);
156982527734SSukumar Swaminathan 
157082527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
157182527734SSukumar Swaminathan 		file = &fw_image->file[i];
157282527734SSukumar Swaminathan 
157382527734SSukumar Swaminathan 		if (file->image_size == 0) {
157482527734SSukumar Swaminathan 			continue;
157582527734SSukumar Swaminathan 		}
157682527734SSukumar Swaminathan 
157782527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1578a9800bebSGarrett D'Amore 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1579a9800bebSGarrett D'Amore 		    "load=%x",
1580a9800bebSGarrett D'Amore 		    file->label, file->be_version, (file->ufi_plus)? "+":"",
1581a9800bebSGarrett D'Amore 		    file->type, file->block_size, file->image_size,
1582a9800bebSGarrett D'Amore 		    file->image_offset, file->block_crc, file->load_address);
158382527734SSukumar Swaminathan 	}
158482527734SSukumar Swaminathan 
158582527734SSukumar Swaminathan 	return (0);
158682527734SSukumar Swaminathan 
1587a9800bebSGarrett D'Amore } /* emlxs_be3_validate_image() */
158882527734SSukumar Swaminathan 
158982527734SSukumar Swaminathan 
159082527734SSukumar Swaminathan static int32_t
emlxs_be_fw_download(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline)1591*8f23e9faSHans Rosenfeld emlxs_be_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
159282527734SSukumar Swaminathan     uint32_t offline)
159382527734SSukumar Swaminathan {
159482527734SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
159582527734SSukumar Swaminathan 	uint32_t i;
159682527734SSukumar Swaminathan 	uint32_t update = 0;
159782527734SSukumar Swaminathan 	uint32_t rval = 0;
159882527734SSukumar Swaminathan 	MAILBOXQ *mbq = NULL;
159982527734SSukumar Swaminathan 	MATCHMAP *mp = NULL;
160082527734SSukumar Swaminathan 	emlxs_be_fw_image_t fw_image;
160182527734SSukumar Swaminathan 	emlxs_be_fw_file_t *file;
1602a9800bebSGarrett D'Amore 	uint32_t be_version;
160382527734SSukumar Swaminathan 
160482527734SSukumar Swaminathan 	/* For now we will not take the driver offline during a download */
160582527734SSukumar Swaminathan 	offline = 0;
160682527734SSukumar Swaminathan 
160782527734SSukumar Swaminathan 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
160882527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
160982527734SSukumar Swaminathan 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
161082527734SSukumar Swaminathan 		return (EMLXS_IMAGE_INCOMPATIBLE);
161182527734SSukumar Swaminathan 	}
161282527734SSukumar Swaminathan 
1613*8f23e9faSHans Rosenfeld 	if (!(hba->model_info.chip & EMLXS_BE_CHIPS)) {
1614*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1615*8f23e9faSHans Rosenfeld 		    "Invalid adapter model. chip=%x", hba->model_info.chip);
1616*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
1617*8f23e9faSHans Rosenfeld 	}
1618*8f23e9faSHans Rosenfeld 
161982527734SSukumar Swaminathan 	if (buffer == NULL || len == 0) {
162082527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
162182527734SSukumar Swaminathan 		    "Empty buffer provided. buf=%p size=%d", buffer, len);
162282527734SSukumar Swaminathan 		return (EMLXS_IMAGE_BAD);
162382527734SSukumar Swaminathan 	}
162482527734SSukumar Swaminathan 
1625a9800bebSGarrett D'Amore 	be_version = emlxs_be_version(buffer, len, 0);
1626a9800bebSGarrett D'Amore 
1627a9800bebSGarrett D'Amore 	switch (be_version) {
1628a9800bebSGarrett D'Amore 	case 0:
1629a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1630a9800bebSGarrett D'Amore 		    "Invalid image provided. Non-UFI format.");
1631a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
1632a9800bebSGarrett D'Amore 	case 2:
1633a9800bebSGarrett D'Amore 		rval = emlxs_be2_validate_image(hba, buffer, len, &fw_image);
1634a9800bebSGarrett D'Amore 		if (rval) {
1635a9800bebSGarrett D'Amore 			return (rval);
1636a9800bebSGarrett D'Amore 		}
1637a9800bebSGarrett D'Amore 		break;
1638a9800bebSGarrett D'Amore 	case 3:
1639a9800bebSGarrett D'Amore 		rval = emlxs_be3_validate_image(hba, buffer, len, &fw_image);
1640a9800bebSGarrett D'Amore 		if (rval) {
1641a9800bebSGarrett D'Amore 			return (rval);
1642a9800bebSGarrett D'Amore 		}
1643a9800bebSGarrett D'Amore 		break;
1644a9800bebSGarrett D'Amore 	default:
1645a9800bebSGarrett D'Amore 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1646a9800bebSGarrett D'Amore 		    "Invalid image provided. Unknown BE version. (%x)",
1647a9800bebSGarrett D'Amore 		    be_version);
1648a9800bebSGarrett D'Amore 		return (EMLXS_IMAGE_INCOMPATIBLE);
164982527734SSukumar Swaminathan 	}
165082527734SSukumar Swaminathan 
165182527734SSukumar Swaminathan 	/* Allocate resources */
165282527734SSukumar Swaminathan 
165382527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
165482527734SSukumar Swaminathan 	    KM_SLEEP)) == NULL) {
165582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
165682527734SSukumar Swaminathan 		    "Unable to allocate mailbox buffer.");
165782527734SSukumar Swaminathan 
165882527734SSukumar Swaminathan 		offline = 0;
165982527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
166082527734SSukumar Swaminathan 		goto done;
166182527734SSukumar Swaminathan 	}
166282527734SSukumar Swaminathan 
166382527734SSukumar Swaminathan 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
166482527734SSukumar Swaminathan 	    sizeof (IOCTL_COMMON_FLASHROM) + BE_MAX_XFER_SIZE))) == NULL) {
166582527734SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
166682527734SSukumar Swaminathan 		    "Unable to allocate flash buffer.");
166782527734SSukumar Swaminathan 
166882527734SSukumar Swaminathan 		offline = 0;
166982527734SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
167082527734SSukumar Swaminathan 		goto done;
167182527734SSukumar Swaminathan 	}
167282527734SSukumar Swaminathan 
167382527734SSukumar Swaminathan 	/* Check if update is required */
167482527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
167582527734SSukumar Swaminathan 		file = &fw_image.file[i];
167682527734SSukumar Swaminathan 
167782527734SSukumar Swaminathan 		if (file->image_size == 0) {
167882527734SSukumar Swaminathan 			continue;
167982527734SSukumar Swaminathan 		}
168082527734SSukumar Swaminathan 
1681*8f23e9faSHans Rosenfeld 		if (file->type == MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
1682*8f23e9faSHans Rosenfeld 			rval = emlxs_be_verify_phy(hba, file, mbq, mp);
1683fcf3ce44SJohn Forte 
1684*8f23e9faSHans Rosenfeld 			if (rval != 0) {
1685*8f23e9faSHans Rosenfeld 				/* Do not update */
1686*8f23e9faSHans Rosenfeld 				file->image_size = 0;
1687*8f23e9faSHans Rosenfeld 				continue;
1688*8f23e9faSHans Rosenfeld 			}
1689*8f23e9faSHans Rosenfeld 		} else {
1690*8f23e9faSHans Rosenfeld 			rval = emlxs_be_verify_crc(hba, file, mbq, mp);
1691*8f23e9faSHans Rosenfeld 			if (rval == 0) {
1692*8f23e9faSHans Rosenfeld 				/* Do not update */
1693*8f23e9faSHans Rosenfeld 				file->image_size = 0;
1694*8f23e9faSHans Rosenfeld 				continue;
1695*8f23e9faSHans Rosenfeld 			}
169682527734SSukumar Swaminathan 		}
169782527734SSukumar Swaminathan 
169882527734SSukumar Swaminathan 		update++;
169982527734SSukumar Swaminathan 	}
170082527734SSukumar Swaminathan 
170182527734SSukumar Swaminathan 	if (!update) {
170282527734SSukumar Swaminathan 		offline = 0;
1703a9800bebSGarrett D'Amore 		rval = 0;
170482527734SSukumar Swaminathan 		goto done;
170582527734SSukumar Swaminathan 	}
170682527734SSukumar Swaminathan 
170782527734SSukumar Swaminathan 	/*
170882527734SSukumar Swaminathan 	 * Everything checks out, now to just do it
170982527734SSukumar Swaminathan 	 */
171082527734SSukumar Swaminathan 	if (offline) {
1711*8f23e9faSHans Rosenfeld 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
171282527734SSukumar Swaminathan 
171382527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
171482527734SSukumar Swaminathan 			    "Unable to take adapter offline.");
171582527734SSukumar Swaminathan 
171682527734SSukumar Swaminathan 			offline = 0;
171782527734SSukumar Swaminathan 			rval = EMLXS_OFFLINE_FAILED;
171882527734SSukumar Swaminathan 			goto done;
171982527734SSukumar Swaminathan 		}
172082527734SSukumar Swaminathan 	}
172182527734SSukumar Swaminathan 
172282527734SSukumar Swaminathan 	/* Download entries which require update */
172382527734SSukumar Swaminathan 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
172482527734SSukumar Swaminathan 		file = &fw_image.file[i];
172582527734SSukumar Swaminathan 
172682527734SSukumar Swaminathan 		if (file->image_size == 0) {
172782527734SSukumar Swaminathan 			continue;
172882527734SSukumar Swaminathan 		}
172982527734SSukumar Swaminathan 
1730*8f23e9faSHans Rosenfeld 		rval = emlxs_be_flash_image(hba, buffer, file, mbq, mp);
173182527734SSukumar Swaminathan 
173282527734SSukumar Swaminathan 		if (rval != 0) {
173382527734SSukumar Swaminathan 			goto done;
173482527734SSukumar Swaminathan 		}
173582527734SSukumar Swaminathan 	}
173682527734SSukumar Swaminathan 
173782527734SSukumar Swaminathan done:
173882527734SSukumar Swaminathan 	if (mbq) {
1739a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
174082527734SSukumar Swaminathan 	}
174182527734SSukumar Swaminathan 
174282527734SSukumar Swaminathan 	if (mp) {
1743a9800bebSGarrett D'Amore 		emlxs_mem_buf_free(hba, mp);
174482527734SSukumar Swaminathan 	}
174582527734SSukumar Swaminathan 
174682527734SSukumar Swaminathan 	if (offline) {
174782527734SSukumar Swaminathan 		(void) emlxs_online(hba);
174882527734SSukumar Swaminathan 	}
174982527734SSukumar Swaminathan 
175082527734SSukumar Swaminathan 	if (rval == 0) {
175182527734SSukumar Swaminathan 		if (update) {
175282527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
175382527734SSukumar Swaminathan 			    "Status good.");
175482527734SSukumar Swaminathan 
175582527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
1756*8f23e9faSHans Rosenfeld 			    "The new firmware will not be activated until "
1757*8f23e9faSHans Rosenfeld 			    "the adapter is power cycled: %s",
1758a9800bebSGarrett D'Amore 			    fw_image.fcoe_label);
175982527734SSukumar Swaminathan 
176082527734SSukumar Swaminathan 		} else {
176182527734SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
176282527734SSukumar Swaminathan 			    "No firmware update required.");
176382527734SSukumar Swaminathan 		}
176482527734SSukumar Swaminathan 	}
176582527734SSukumar Swaminathan 
176682527734SSukumar Swaminathan 	return (rval);
176782527734SSukumar Swaminathan 
1768*8f23e9faSHans Rosenfeld } /* emlxs_be_fw_download() */
1769*8f23e9faSHans Rosenfeld 
1770*8f23e9faSHans Rosenfeld 
1771*8f23e9faSHans Rosenfeld static int32_t
emlxs_obj_flash_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t size,MAILBOXQ * mbq,MATCHMAP * mp,uint32_t * change_status)1772*8f23e9faSHans Rosenfeld emlxs_obj_flash_image(emlxs_hba_t *hba, caddr_t buffer, uint32_t size,
1773*8f23e9faSHans Rosenfeld     MAILBOXQ *mbq, MATCHMAP *mp, uint32_t *change_status)
1774*8f23e9faSHans Rosenfeld {
1775*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
1776*8f23e9faSHans Rosenfeld 	uint8_t *image_ptr;
1777*8f23e9faSHans Rosenfeld 	MAILBOX4 *mb;
1778*8f23e9faSHans Rosenfeld 	mbox_req_hdr_t	*hdr_req;
1779*8f23e9faSHans Rosenfeld 	mbox_rsp_hdr_t	*hdr_rsp;
1780*8f23e9faSHans Rosenfeld 	uint32_t	image_size;
1781*8f23e9faSHans Rosenfeld 	uint32_t	xfer_size;
1782*8f23e9faSHans Rosenfeld 	uint32_t	image_offset;
1783*8f23e9faSHans Rosenfeld 	uint32_t	rval = 0;
1784*8f23e9faSHans Rosenfeld 	IOCTL_COMMON_WRITE_OBJECT *write_obj;
1785*8f23e9faSHans Rosenfeld 	uint32_t 	cstatus = 0;
1786*8f23e9faSHans Rosenfeld 
1787*8f23e9faSHans Rosenfeld 	if (!buffer || size == 0) {
1788*8f23e9faSHans Rosenfeld 		return (0);
1789*8f23e9faSHans Rosenfeld 	}
1790*8f23e9faSHans Rosenfeld 
1791*8f23e9faSHans Rosenfeld 	image_ptr  = (uint8_t *)buffer;
1792*8f23e9faSHans Rosenfeld 	image_size = size;
1793*8f23e9faSHans Rosenfeld 	image_offset = 0;
1794*8f23e9faSHans Rosenfeld 	mb = (MAILBOX4*)mbq;
1795*8f23e9faSHans Rosenfeld 
1796*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1797*8f23e9faSHans Rosenfeld 	    "OBJ File: Downloading...");
1798*8f23e9faSHans Rosenfeld 
1799*8f23e9faSHans Rosenfeld 	while (image_size) {
1800*8f23e9faSHans Rosenfeld 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1801*8f23e9faSHans Rosenfeld 		bzero((void *) mp->virt, mp->size);
1802*8f23e9faSHans Rosenfeld 
1803*8f23e9faSHans Rosenfeld 		xfer_size = min(OBJ_MAX_XFER_SIZE, image_size);
1804*8f23e9faSHans Rosenfeld 
1805*8f23e9faSHans Rosenfeld 		mb->un.varSLIConfig.be.embedded = 1;
1806*8f23e9faSHans Rosenfeld 		mbq->nonembed  = NULL;
1807*8f23e9faSHans Rosenfeld 		mbq->mbox_cmpl = NULL;
1808*8f23e9faSHans Rosenfeld 
1809*8f23e9faSHans Rosenfeld 		mb->mbxCommand = MBX_SLI_CONFIG;
1810*8f23e9faSHans Rosenfeld 		mb->mbxOwner = OWN_HOST;
1811*8f23e9faSHans Rosenfeld 
1812*8f23e9faSHans Rosenfeld 		hdr_req = (mbox_req_hdr_t *)
1813*8f23e9faSHans Rosenfeld 		    &mb->un.varSLIConfig.be.un_hdr.hdr_req;
1814*8f23e9faSHans Rosenfeld 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
1815*8f23e9faSHans Rosenfeld 		hdr_req->opcode = COMMON_OPCODE_WRITE_OBJ;
1816*8f23e9faSHans Rosenfeld 		hdr_req->timeout = 0;
1817*8f23e9faSHans Rosenfeld 
1818*8f23e9faSHans Rosenfeld 		write_obj = (IOCTL_COMMON_WRITE_OBJECT *)(hdr_req + 1);
1819*8f23e9faSHans Rosenfeld 		write_obj->params.request.EOF =
1820*8f23e9faSHans Rosenfeld 		    ((xfer_size == image_size)? 1:0);
1821*8f23e9faSHans Rosenfeld 		write_obj->params.request.desired_write_length = xfer_size;
1822*8f23e9faSHans Rosenfeld 		write_obj->params.request.write_offset = image_offset;
1823*8f23e9faSHans Rosenfeld 
1824*8f23e9faSHans Rosenfeld 		(void) strlcpy((char *)write_obj->params.request.object_name,
1825*8f23e9faSHans Rosenfeld 		    "/prg", sizeof (write_obj->params.request.object_name));
1826*8f23e9faSHans Rosenfeld 		BE_SWAP32_BUFFER((uint8_t *)
1827*8f23e9faSHans Rosenfeld 		    write_obj->params.request.object_name,
1828*8f23e9faSHans Rosenfeld 		    sizeof (write_obj->params.request.object_name));
1829*8f23e9faSHans Rosenfeld 
1830*8f23e9faSHans Rosenfeld 		write_obj->params.request.buffer_desc_count = 1;
1831*8f23e9faSHans Rosenfeld 		write_obj->params.request.buffer_length = xfer_size;
1832*8f23e9faSHans Rosenfeld 		write_obj->params.request.buffer_addrlo = PADDR_LO(mp->phys);
1833*8f23e9faSHans Rosenfeld 		write_obj->params.request.buffer_addrhi = PADDR_HI(mp->phys);
1834*8f23e9faSHans Rosenfeld 
1835*8f23e9faSHans Rosenfeld 		hdr_req->req_length = 116 +
1836*8f23e9faSHans Rosenfeld 		    (write_obj->params.request.buffer_desc_count * 12);
1837*8f23e9faSHans Rosenfeld 
1838*8f23e9faSHans Rosenfeld 		bcopy(image_ptr, mp->virt, xfer_size);
1839*8f23e9faSHans Rosenfeld 
1840*8f23e9faSHans Rosenfeld 		hdr_rsp = (mbox_rsp_hdr_t *)
1841*8f23e9faSHans Rosenfeld 		    &mb->un.varSLIConfig.be.un_hdr.hdr_rsp;
1842*8f23e9faSHans Rosenfeld 		write_obj = (IOCTL_COMMON_WRITE_OBJECT *)(hdr_rsp + 1);
1843*8f23e9faSHans Rosenfeld 
1844*8f23e9faSHans Rosenfeld 		/* Send write request */
1845*8f23e9faSHans Rosenfeld 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
1846*8f23e9faSHans Rosenfeld 		    MBX_SUCCESS) {
1847*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1848*8f23e9faSHans Rosenfeld 			    "OBJ File: Unable to download image. status=%x "
1849*8f23e9faSHans Rosenfeld 			    "(%x,%x)",
1850*8f23e9faSHans Rosenfeld 			    mb->mbxStatus, hdr_rsp->status,
1851*8f23e9faSHans Rosenfeld 			    hdr_rsp->extra_status);
1852*8f23e9faSHans Rosenfeld 
1853*8f23e9faSHans Rosenfeld 			return (EMLXS_IMAGE_FAILED);
1854*8f23e9faSHans Rosenfeld 		}
1855*8f23e9faSHans Rosenfeld 
1856*8f23e9faSHans Rosenfeld 		/* Check header status */
1857*8f23e9faSHans Rosenfeld 		if (hdr_rsp->status) {
1858*8f23e9faSHans Rosenfeld 			if ((hdr_rsp->status == MBX_RSP_STATUS_FAILED) &&
1859*8f23e9faSHans Rosenfeld 			    (hdr_rsp->extra_status ==
1860*8f23e9faSHans Rosenfeld 			    MGMT_ADDI_STATUS_INCOMPATIBLE)) {
1861*8f23e9faSHans Rosenfeld 				EMLXS_MSGF(EMLXS_CONTEXT,
1862*8f23e9faSHans Rosenfeld 				    &emlxs_download_failed_msg,
1863*8f23e9faSHans Rosenfeld 				    "OBJ File: Image file incompatible with "
1864*8f23e9faSHans Rosenfeld 				    "adapter hardware.");
1865*8f23e9faSHans Rosenfeld 				return (EMLXS_IMAGE_INCOMPATIBLE);
1866*8f23e9faSHans Rosenfeld 			}
1867*8f23e9faSHans Rosenfeld 
1868*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1869*8f23e9faSHans Rosenfeld 			    "OBJ File: Unable to download image. "
1870*8f23e9faSHans Rosenfeld 			    "hdr_status=%x,%x size=%d,%d",
1871*8f23e9faSHans Rosenfeld 			    hdr_rsp->status, hdr_rsp->extra_status,
1872*8f23e9faSHans Rosenfeld 			    write_obj->params.response.actual_write_length,
1873*8f23e9faSHans Rosenfeld 			    xfer_size);
1874*8f23e9faSHans Rosenfeld 
1875*8f23e9faSHans Rosenfeld 			return (EMLXS_IMAGE_FAILED);
1876*8f23e9faSHans Rosenfeld 		}
1877*8f23e9faSHans Rosenfeld 
1878*8f23e9faSHans Rosenfeld 		/* Check response length */
1879*8f23e9faSHans Rosenfeld 		if (write_obj->params.response.actual_write_length == 0) {
1880*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1881*8f23e9faSHans Rosenfeld 			    "OBJ File: No data actually written.");
1882*8f23e9faSHans Rosenfeld 
1883*8f23e9faSHans Rosenfeld 			return (EMLXS_IMAGE_FAILED);
1884*8f23e9faSHans Rosenfeld 		}
1885*8f23e9faSHans Rosenfeld 
1886*8f23e9faSHans Rosenfeld 		if (write_obj->params.response.actual_write_length >
1887*8f23e9faSHans Rosenfeld 		    xfer_size) {
1888*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1889*8f23e9faSHans Rosenfeld 			    "OBJ File: Mismatch in data xfer size. "
1890*8f23e9faSHans Rosenfeld 			    "size=%d,%d offset=%d",
1891*8f23e9faSHans Rosenfeld 			    write_obj->params.response.actual_write_length,
1892*8f23e9faSHans Rosenfeld 			    xfer_size, image_offset);
1893*8f23e9faSHans Rosenfeld 
1894*8f23e9faSHans Rosenfeld 			return (EMLXS_IMAGE_FAILED);
1895*8f23e9faSHans Rosenfeld 		}
1896*8f23e9faSHans Rosenfeld 
1897*8f23e9faSHans Rosenfeld 		/* Set xfer_size to actual write length */
1898*8f23e9faSHans Rosenfeld 		xfer_size = write_obj->params.response.actual_write_length;
1899*8f23e9faSHans Rosenfeld 
1900*8f23e9faSHans Rosenfeld 		image_ptr  += xfer_size;
1901*8f23e9faSHans Rosenfeld 		image_offset += xfer_size;
1902*8f23e9faSHans Rosenfeld 		image_size -= xfer_size;
1903*8f23e9faSHans Rosenfeld 
1904*8f23e9faSHans Rosenfeld 		if (image_size == 0) {
1905*8f23e9faSHans Rosenfeld 			cstatus = write_obj->params.response.change_status;
1906*8f23e9faSHans Rosenfeld 		}
1907*8f23e9faSHans Rosenfeld 	}
1908*8f23e9faSHans Rosenfeld 
1909*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1910*8f23e9faSHans Rosenfeld 	    "OBJ File: Download complete. (cstatus=%d)",
1911*8f23e9faSHans Rosenfeld 	    cstatus);
1912*8f23e9faSHans Rosenfeld 
1913*8f23e9faSHans Rosenfeld 	if (change_status) {
1914*8f23e9faSHans Rosenfeld 		*change_status = cstatus;
1915*8f23e9faSHans Rosenfeld 	}
1916*8f23e9faSHans Rosenfeld 
1917*8f23e9faSHans Rosenfeld 	return (rval);
1918*8f23e9faSHans Rosenfeld 
1919*8f23e9faSHans Rosenfeld } /* emlxs_obj_flash_image() */
1920*8f23e9faSHans Rosenfeld 
1921*8f23e9faSHans Rosenfeld 
1922*8f23e9faSHans Rosenfeld static uint32_t
emlxs_obj_validate_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,emlxs_obj_header_t * obj_hdr_in)1923*8f23e9faSHans Rosenfeld emlxs_obj_validate_image(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
1924*8f23e9faSHans Rosenfeld     emlxs_obj_header_t *obj_hdr_in)
1925*8f23e9faSHans Rosenfeld {
1926*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
1927*8f23e9faSHans Rosenfeld 	emlxs_obj_header_t obj_hdr;
1928*8f23e9faSHans Rosenfeld 
1929*8f23e9faSHans Rosenfeld 	if (obj_hdr_in) {
1930*8f23e9faSHans Rosenfeld 		bzero(obj_hdr_in, sizeof (emlxs_obj_header_t));
1931*8f23e9faSHans Rosenfeld 	}
1932*8f23e9faSHans Rosenfeld 
1933*8f23e9faSHans Rosenfeld 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
1934*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1935*8f23e9faSHans Rosenfeld 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
1936*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
1937*8f23e9faSHans Rosenfeld 	}
1938*8f23e9faSHans Rosenfeld 
1939*8f23e9faSHans Rosenfeld 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
1940*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1941*8f23e9faSHans Rosenfeld 		    "Invalid adapter model. chip=%x", hba->model_info.chip);
1942*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
1943*8f23e9faSHans Rosenfeld 	}
1944*8f23e9faSHans Rosenfeld 
1945*8f23e9faSHans Rosenfeld 	if (len < sizeof (emlxs_obj_header_t)) {
1946*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1947*8f23e9faSHans Rosenfeld 		    "Image too small. (%d < %d)",
1948*8f23e9faSHans Rosenfeld 		    len,  sizeof (emlxs_obj_header_t));
1949*8f23e9faSHans Rosenfeld 
1950*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_BAD);
1951*8f23e9faSHans Rosenfeld 	}
1952*8f23e9faSHans Rosenfeld 
1953*8f23e9faSHans Rosenfeld 	bcopy(buffer, (uint8_t *)&obj_hdr, sizeof (emlxs_obj_header_t));
1954*8f23e9faSHans Rosenfeld 
1955*8f23e9faSHans Rosenfeld 	/* Swap first 3 words */
1956*8f23e9faSHans Rosenfeld 	LE_SWAP32_BUFFER((uint8_t *)&obj_hdr, 12);
1957*8f23e9faSHans Rosenfeld 
1958*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1959*8f23e9faSHans Rosenfeld 	    "Object Header: size=%d magic=%04x,%04x type=%02x id=%02x",
1960*8f23e9faSHans Rosenfeld 	    obj_hdr.FileSize,
1961*8f23e9faSHans Rosenfeld 	    obj_hdr.MagicNumHi, obj_hdr.MagicNumLo,
1962*8f23e9faSHans Rosenfeld 	    obj_hdr.FileType,
1963*8f23e9faSHans Rosenfeld 	    obj_hdr.Id);
1964*8f23e9faSHans Rosenfeld 
1965*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1966*8f23e9faSHans Rosenfeld 	    "Object Header: Date=%s Rev=%s",
1967*8f23e9faSHans Rosenfeld 	    obj_hdr.Date,
1968*8f23e9faSHans Rosenfeld 	    obj_hdr.Revision);
1969*8f23e9faSHans Rosenfeld 
1970*8f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1971*8f23e9faSHans Rosenfeld 	    "Object Header: Name=%s",
1972*8f23e9faSHans Rosenfeld 	    obj_hdr.RevName);
1973*8f23e9faSHans Rosenfeld 
1974*8f23e9faSHans Rosenfeld 	if ((obj_hdr.MagicNumHi != OBJ_MAGIC_NUM_HI) ||
1975*8f23e9faSHans Rosenfeld 	    (obj_hdr.MagicNumLo != OBJ_MAGIC_NUM_LO)) {
1976*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1977*8f23e9faSHans Rosenfeld 		    "Wrong Magic Number: %x,%x",
1978*8f23e9faSHans Rosenfeld 		    obj_hdr.MagicNumHi, obj_hdr.MagicNumLo);
1979*8f23e9faSHans Rosenfeld 
1980*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
1981*8f23e9faSHans Rosenfeld 	}
1982*8f23e9faSHans Rosenfeld 
1983*8f23e9faSHans Rosenfeld 	if (obj_hdr.FileSize != len) {
1984*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1985*8f23e9faSHans Rosenfeld 		    "Image too small. (%d < %d)",
1986*8f23e9faSHans Rosenfeld 		    len, obj_hdr.FileSize);
1987*8f23e9faSHans Rosenfeld 
1988*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_BAD);
1989*8f23e9faSHans Rosenfeld 	}
1990*8f23e9faSHans Rosenfeld 
1991*8f23e9faSHans Rosenfeld 	if ((hba->model_info.chip & EMLXS_LANCER_CHIP) &&
1992*8f23e9faSHans Rosenfeld 	    (obj_hdr.Id != OBJ_LANCER_ID)) {
1993*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1994*8f23e9faSHans Rosenfeld 		    "Invalid adapter model. chip=%x fwid=%x",
1995*8f23e9faSHans Rosenfeld 		    hba->model_info.chip,
1996*8f23e9faSHans Rosenfeld 		    obj_hdr.Id);
1997*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
1998*8f23e9faSHans Rosenfeld 	}
1999*8f23e9faSHans Rosenfeld 
2000*8f23e9faSHans Rosenfeld 	if (obj_hdr_in) {
2001*8f23e9faSHans Rosenfeld 		bcopy(&obj_hdr, obj_hdr_in, sizeof (emlxs_obj_header_t));
2002*8f23e9faSHans Rosenfeld 	}
2003*8f23e9faSHans Rosenfeld 
2004*8f23e9faSHans Rosenfeld 	return (0);
2005*8f23e9faSHans Rosenfeld 
2006*8f23e9faSHans Rosenfeld } /* emlxs_obj_validate_image() */
2007*8f23e9faSHans Rosenfeld 
2008*8f23e9faSHans Rosenfeld 
2009*8f23e9faSHans Rosenfeld static int32_t
emlxs_obj_fw_download(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline)2010*8f23e9faSHans Rosenfeld emlxs_obj_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
2011*8f23e9faSHans Rosenfeld     uint32_t offline)
2012*8f23e9faSHans Rosenfeld {
2013*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
2014*8f23e9faSHans Rosenfeld 	uint32_t rval = 0;
2015*8f23e9faSHans Rosenfeld 	MAILBOXQ *mbq = NULL;
2016*8f23e9faSHans Rosenfeld 	MATCHMAP *mp = NULL;
2017*8f23e9faSHans Rosenfeld 	uint32_t change_status = 0;
2018*8f23e9faSHans Rosenfeld 
2019*8f23e9faSHans Rosenfeld 	/* For now we will not take the driver offline during a download */
2020*8f23e9faSHans Rosenfeld 	offline = 0;
2021*8f23e9faSHans Rosenfeld 
2022*8f23e9faSHans Rosenfeld 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
2023*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2024*8f23e9faSHans Rosenfeld 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
2025*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
2026*8f23e9faSHans Rosenfeld 	}
2027*8f23e9faSHans Rosenfeld 
2028*8f23e9faSHans Rosenfeld 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
2029*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2030*8f23e9faSHans Rosenfeld 		    "Invalid adapter model. chip=%x", hba->model_info.chip);
2031*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
2032*8f23e9faSHans Rosenfeld 	}
2033*8f23e9faSHans Rosenfeld 
2034*8f23e9faSHans Rosenfeld 	if (buffer == NULL || len == 0) {
2035*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2036*8f23e9faSHans Rosenfeld 		    "Empty buffer provided. buf=%p size=%d", buffer, len);
2037*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_BAD);
2038*8f23e9faSHans Rosenfeld 	}
2039*8f23e9faSHans Rosenfeld 
2040*8f23e9faSHans Rosenfeld 	rval = emlxs_obj_validate_image(hba, buffer, len, 0);
2041*8f23e9faSHans Rosenfeld 
2042*8f23e9faSHans Rosenfeld 	if (rval) {
2043*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2044*8f23e9faSHans Rosenfeld 		    "Invalid image provided.");
2045*8f23e9faSHans Rosenfeld 		return (EMLXS_IMAGE_INCOMPATIBLE);
2046*8f23e9faSHans Rosenfeld 	}
2047*8f23e9faSHans Rosenfeld 
2048*8f23e9faSHans Rosenfeld 	/* Allocate resources */
2049*8f23e9faSHans Rosenfeld 
2050*8f23e9faSHans Rosenfeld 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2051*8f23e9faSHans Rosenfeld 	    KM_SLEEP)) == NULL) {
2052*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2053*8f23e9faSHans Rosenfeld 		    "Unable to allocate mailbox buffer.");
2054*8f23e9faSHans Rosenfeld 
2055*8f23e9faSHans Rosenfeld 		offline = 0;
2056*8f23e9faSHans Rosenfeld 		rval = EMLXS_IMAGE_FAILED;
2057*8f23e9faSHans Rosenfeld 		goto done;
2058*8f23e9faSHans Rosenfeld 	}
2059*8f23e9faSHans Rosenfeld 
2060*8f23e9faSHans Rosenfeld 	if ((mp = emlxs_mem_buf_alloc(hba, OBJ_MAX_XFER_SIZE)) == NULL) {
2061*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2062*8f23e9faSHans Rosenfeld 		    "Unable to allocate flash buffer.");
2063*8f23e9faSHans Rosenfeld 
2064*8f23e9faSHans Rosenfeld 		offline = 0;
2065*8f23e9faSHans Rosenfeld 		rval = EMLXS_IMAGE_FAILED;
2066*8f23e9faSHans Rosenfeld 		goto done;
2067*8f23e9faSHans Rosenfeld 	}
2068*8f23e9faSHans Rosenfeld 
2069*8f23e9faSHans Rosenfeld 	/*
2070*8f23e9faSHans Rosenfeld 	 * Everything checks out, now to just do it
2071*8f23e9faSHans Rosenfeld 	 */
2072*8f23e9faSHans Rosenfeld 	if (offline) {
2073*8f23e9faSHans Rosenfeld 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
2074*8f23e9faSHans Rosenfeld 
2075*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2076*8f23e9faSHans Rosenfeld 			    "Unable to take adapter offline.");
2077*8f23e9faSHans Rosenfeld 
2078*8f23e9faSHans Rosenfeld 			offline = 0;
2079*8f23e9faSHans Rosenfeld 			rval = EMLXS_OFFLINE_FAILED;
2080*8f23e9faSHans Rosenfeld 			goto done;
2081*8f23e9faSHans Rosenfeld 		}
2082*8f23e9faSHans Rosenfeld 	}
2083*8f23e9faSHans Rosenfeld 
2084*8f23e9faSHans Rosenfeld 	rval = emlxs_obj_flash_image(hba, buffer, len, mbq, mp, &change_status);
2085*8f23e9faSHans Rosenfeld 
2086*8f23e9faSHans Rosenfeld done:
2087*8f23e9faSHans Rosenfeld 	if (mbq) {
2088*8f23e9faSHans Rosenfeld 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2089*8f23e9faSHans Rosenfeld 	}
2090*8f23e9faSHans Rosenfeld 
2091*8f23e9faSHans Rosenfeld 	if (mp) {
2092*8f23e9faSHans Rosenfeld 		emlxs_mem_buf_free(hba, mp);
2093*8f23e9faSHans Rosenfeld 	}
2094*8f23e9faSHans Rosenfeld 
2095*8f23e9faSHans Rosenfeld 	if (offline) {
2096*8f23e9faSHans Rosenfeld 		(void) emlxs_online(hba);
2097*8f23e9faSHans Rosenfeld 	}
2098*8f23e9faSHans Rosenfeld 
2099*8f23e9faSHans Rosenfeld 	if (rval == 0) {
2100*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
2101*8f23e9faSHans Rosenfeld 		    "Status good.");
2102*8f23e9faSHans Rosenfeld 
2103*8f23e9faSHans Rosenfeld 		switch (change_status) {
2104*8f23e9faSHans Rosenfeld 		case CS_NO_RESET:
2105*8f23e9faSHans Rosenfeld 			break;
2106*8f23e9faSHans Rosenfeld 
2107*8f23e9faSHans Rosenfeld 		case CS_REBOOT_RQD:
2108*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
2109*8f23e9faSHans Rosenfeld 			    "The new firmware will not be activated until "
2110*8f23e9faSHans Rosenfeld 			    "the adapter is power cycled.");
2111*8f23e9faSHans Rosenfeld 			rval = EMLXS_REBOOT_REQUIRED;
2112*8f23e9faSHans Rosenfeld 			break;
2113*8f23e9faSHans Rosenfeld 
2114*8f23e9faSHans Rosenfeld 		case CS_FW_RESET_RQD:
2115*8f23e9faSHans Rosenfeld 		case CS_PROTO_RESET_RQD:
2116*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
2117*8f23e9faSHans Rosenfeld 			    "Resetting all ports to activate new firmware.");
2118*8f23e9faSHans Rosenfeld 
2119*8f23e9faSHans Rosenfeld 			emlxs_sli4_hba_reset_all(hba, 0);
2120*8f23e9faSHans Rosenfeld 		}
2121*8f23e9faSHans Rosenfeld 	}
2122*8f23e9faSHans Rosenfeld 
2123*8f23e9faSHans Rosenfeld 	return (rval);
2124*8f23e9faSHans Rosenfeld 
2125*8f23e9faSHans Rosenfeld } /* emlxs_obj_fw_download() */
2126fcf3ce44SJohn Forte 
2127fcf3ce44SJohn Forte 
2128fcf3ce44SJohn Forte extern int32_t
emlxs_cfl_download(emlxs_hba_t * hba,uint32_t region,caddr_t buffer,uint32_t len)2129fcf3ce44SJohn Forte emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer,
2130fcf3ce44SJohn Forte     uint32_t len)
2131fcf3ce44SJohn Forte {
2132fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2133fcf3ce44SJohn Forte 	MAILBOXQ *mbox = NULL;
2134fcf3ce44SJohn Forte 	MAILBOX *mb;
2135fcf3ce44SJohn Forte 	uint32_t rval = 0;
2136fcf3ce44SJohn Forte 	uint32_t region_id;
2137fcf3ce44SJohn Forte 	uint32_t id;
213882527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
2139fcf3ce44SJohn Forte 	caddr_t local_buffer;
2140fcf3ce44SJohn Forte 	uint32_t *bptr1;
2141fcf3ce44SJohn Forte 	uint32_t *bptr2;
2142fcf3ce44SJohn Forte 	uint32_t i;
214382527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
2144fcf3ce44SJohn Forte 
2145fcf3ce44SJohn Forte 	if (buffer == NULL || len == 0) {
2146fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
2147fcf3ce44SJohn Forte 	}
214882527734SSukumar Swaminathan 
214982527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
2150fcf3ce44SJohn Forte 	/* We need to swap the image buffer before we start */
2151fcf3ce44SJohn Forte 
2152fcf3ce44SJohn Forte 	/*
2153fcf3ce44SJohn Forte 	 * Use KM_SLEEP to allocate a temporary buffer
2154fcf3ce44SJohn Forte 	 */
2155fcf3ce44SJohn Forte 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
2156fcf3ce44SJohn Forte 
2157fcf3ce44SJohn Forte 	/* Perform a 32 bit swap of the image */
2158fcf3ce44SJohn Forte 	bptr1 = (uint32_t *)local_buffer;
2159fcf3ce44SJohn Forte 	bptr2 = (uint32_t *)buffer;
2160fcf3ce44SJohn Forte 
2161fcf3ce44SJohn Forte 	for (i = 0; i < (len / 4); i++) {
216282527734SSukumar Swaminathan 		*bptr1 = SWAP32(*bptr2);
2163fcf3ce44SJohn Forte 		bptr1++;
2164fcf3ce44SJohn Forte 		bptr2++;
2165fcf3ce44SJohn Forte 	}
2166fcf3ce44SJohn Forte 
2167fcf3ce44SJohn Forte 	/* Replace the original buffer */
2168fcf3ce44SJohn Forte 	buffer = local_buffer;
2169fcf3ce44SJohn Forte 
217082527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
2171fcf3ce44SJohn Forte 
2172fcf3ce44SJohn Forte 	if (len > 128) {
2173fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2174291a2b48SSukumar Swaminathan 		    "Invalid image length: 0x%x > 128", len);
2175fcf3ce44SJohn Forte 
2176fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
2177fcf3ce44SJohn Forte 	}
2178291a2b48SSukumar Swaminathan 
2179fcf3ce44SJohn Forte 	/* Check the region number */
2180fcf3ce44SJohn Forte 	if ((region > 2) && (region != 0xff)) {
2181fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2182291a2b48SSukumar Swaminathan 		    "Invalid region id: 0x%x", region);
2183fcf3ce44SJohn Forte 
2184fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
2185fcf3ce44SJohn Forte 
2186fcf3ce44SJohn Forte 	}
2187291a2b48SSukumar Swaminathan 
2188fcf3ce44SJohn Forte 	/* Check the image vendor id */
2189fcf3ce44SJohn Forte 	id = *(int32_t *)buffer;
2190fcf3ce44SJohn Forte 	if ((id & 0xffff) != 0x10df) {
2191fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2192291a2b48SSukumar Swaminathan 		    "Invalid image id: 0x%x", id);
2193fcf3ce44SJohn Forte 
2194fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
2195fcf3ce44SJohn Forte 	}
2196291a2b48SSukumar Swaminathan 
2197291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2198291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2199fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2200fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2201fcf3ce44SJohn Forte 
2202fcf3ce44SJohn Forte 		rval = 1;
2203fcf3ce44SJohn Forte 
2204fcf3ce44SJohn Forte 		goto done;
2205fcf3ce44SJohn Forte 	}
2206291a2b48SSukumar Swaminathan 
2207fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2208fcf3ce44SJohn Forte 
2209fcf3ce44SJohn Forte 	/*
2210fcf3ce44SJohn Forte 	 * Everything checks out, now to just do it
2211fcf3ce44SJohn Forte 	 */
2212*8f23e9faSHans Rosenfeld 	if (emlxs_offline(hba, 0) != FC_SUCCESS) {
2213fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2214fcf3ce44SJohn Forte 		    "Unable to take HBA offline.");
2215fcf3ce44SJohn Forte 
2216fcf3ce44SJohn Forte 		rval = EMLXS_OFFLINE_FAILED;
2217fcf3ce44SJohn Forte 
2218fcf3ce44SJohn Forte 		goto done;
2219fcf3ce44SJohn Forte 	}
2220291a2b48SSukumar Swaminathan 
222182527734SSukumar Swaminathan 	if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
2222fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2223fcf3ce44SJohn Forte 		    "Unable to restart adapter.");
2224fcf3ce44SJohn Forte 
2225fcf3ce44SJohn Forte 		rval = EMLXS_OFFLINE_FAILED;
2226fcf3ce44SJohn Forte 
2227fcf3ce44SJohn Forte 		goto done;
2228fcf3ce44SJohn Forte 	}
2229291a2b48SSukumar Swaminathan 
2230fcf3ce44SJohn Forte 	/* Check if default region is requested */
2231fcf3ce44SJohn Forte 	if (region == 0xff) {
2232fcf3ce44SJohn Forte 		/*
2233291a2b48SSukumar Swaminathan 		 * Sun-branded Helios and Zypher have different
2234291a2b48SSukumar Swaminathan 		 * default PCI region
2235fcf3ce44SJohn Forte 		 */
2236*8f23e9faSHans Rosenfeld 		if ((hba->model_info.flags & EMLXS_ORACLE_BRANDED) &&
2237fcf3ce44SJohn Forte 		    (hba->model_info.chip &
2238fcf3ce44SJohn Forte 		    (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
2239fcf3ce44SJohn Forte 			region = 2;
2240fcf3ce44SJohn Forte 		} else {
2241fcf3ce44SJohn Forte 			region = 0;
2242fcf3ce44SJohn Forte 		}
2243fcf3ce44SJohn Forte 	}
2244291a2b48SSukumar Swaminathan 
2245fcf3ce44SJohn Forte 	/* Set region id based on PCI region requested */
2246fcf3ce44SJohn Forte 	region_id = DEF_PCI_CFG_REGION_ID + region;
2247fcf3ce44SJohn Forte 
2248fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2249291a2b48SSukumar Swaminathan 	    "PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
2250291a2b48SSukumar Swaminathan 	    region_id, id, len);
2251fcf3ce44SJohn Forte 
2252fcf3ce44SJohn Forte 	/* Copy the data buffer to SLIM */
2253fcf3ce44SJohn Forte 	WRITE_SLIM_COPY(hba, (uint32_t *)buffer,
225482527734SSukumar Swaminathan 	    (volatile uint32_t *)((volatile char *)hba->sli.sli3.slim_addr +
2255291a2b48SSukumar Swaminathan 	    sizeof (MAILBOX)), (len / sizeof (uint32_t)));
2256fcf3ce44SJohn Forte 
22574baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
225882527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
22594baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
22604baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
22614baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
22624baa2c25SSukumar Swaminathan 		rval = 1;
22634baa2c25SSukumar Swaminathan 	}
22644baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
22654baa2c25SSukumar Swaminathan 
226682527734SSukumar Swaminathan 	emlxs_format_update_pci_cfg(hba, mbox, region_id, len);
2267fcf3ce44SJohn Forte 
226882527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2269fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2270291a2b48SSukumar Swaminathan 		    "Unable to update PCI configuration: Mailbox cmd=%x "
2271291a2b48SSukumar Swaminathan 		    "status=%x info=%d", mb->mbxCommand, mb->mbxStatus,
2272fcf3ce44SJohn Forte 		    mb->un.varUpdateCfg.rsp_info);
2273fcf3ce44SJohn Forte 
2274fcf3ce44SJohn Forte 		rval = 1;
2275fcf3ce44SJohn Forte 	}
2276291a2b48SSukumar Swaminathan 
2277fcf3ce44SJohn Forte 	(void) emlxs_online(hba);
2278fcf3ce44SJohn Forte 
2279fcf3ce44SJohn Forte 	if (rval == 0) {
2280fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
2281fcf3ce44SJohn Forte 		    "Status good.");
2282fcf3ce44SJohn Forte 	}
2283291a2b48SSukumar Swaminathan 
2284fcf3ce44SJohn Forte done:
2285fcf3ce44SJohn Forte 
2286fcf3ce44SJohn Forte 	if (mbox) {
2287fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2288fcf3ce44SJohn Forte 	}
228982527734SSukumar Swaminathan 
229082527734SSukumar Swaminathan #ifdef EMLXS_BIG_ENDIAN
2291fcf3ce44SJohn Forte 	/* Free the local buffer */
2292fcf3ce44SJohn Forte 	kmem_free(local_buffer, len);
229382527734SSukumar Swaminathan #endif /* EMLXS_BIG_ENDIAN */
2294fcf3ce44SJohn Forte 
2295fcf3ce44SJohn Forte 	return (rval);
2296fcf3ce44SJohn Forte 
229782527734SSukumar Swaminathan } /* emlxs_cfl_download */
2298fcf3ce44SJohn Forte 
2299fcf3ce44SJohn Forte 
2300fcf3ce44SJohn Forte static uint32_t
emlxs_valid_cksum(uint32_t * StartAddr,uint32_t * EndAddr)2301fcf3ce44SJohn Forte emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr)
2302fcf3ce44SJohn Forte {
2303fcf3ce44SJohn Forte 	uint32_t Temp;
2304fcf3ce44SJohn Forte 	uint32_t CkSum;
2305fcf3ce44SJohn Forte 
2306fcf3ce44SJohn Forte 	EndAddr++;
2307fcf3ce44SJohn Forte 	CkSum = SLI_CKSUM_SEED;
2308fcf3ce44SJohn Forte 
2309fcf3ce44SJohn Forte 	CkSum = (CkSum >> 1) | (CkSum << 31);
2310fcf3ce44SJohn Forte 	while (StartAddr != EndAddr) {
2311fcf3ce44SJohn Forte 		CkSum = (CkSum << 1) | (CkSum >> 31);
2312fcf3ce44SJohn Forte 		Temp = *StartAddr;
2313fcf3ce44SJohn Forte 
2314fcf3ce44SJohn Forte 		CkSum ^= Temp;
2315fcf3ce44SJohn Forte 		StartAddr++;
2316fcf3ce44SJohn Forte 	}
2317fcf3ce44SJohn Forte 
2318fcf3ce44SJohn Forte 	return (CkSum << 1) | (CkSum >> 31);
2319fcf3ce44SJohn Forte 
232082527734SSukumar Swaminathan } /* emlxs_valid_cksum() */
2321fcf3ce44SJohn Forte 
2322fcf3ce44SJohn Forte 
2323fcf3ce44SJohn Forte static void
emlxs_disp_aif_header(emlxs_hba_t * hba,PAIF_HDR AifHdr)2324fcf3ce44SJohn Forte emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr)
2325fcf3ce44SJohn Forte {
2326fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2327fcf3ce44SJohn Forte 
2328291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: ");
2329fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2330fcf3ce44SJohn Forte 	    "AIF Header: compress_br = 0x%x", AifHdr->CompressBr);
2331fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2332fcf3ce44SJohn Forte 	    "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr);
2333fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2334fcf3ce44SJohn Forte 	    "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr);
2335fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2336fcf3ce44SJohn Forte 	    "AIF Header: entry_br = 0x%x", AifHdr->EntryBr);
2337fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2338fcf3ce44SJohn Forte 	    "AIF Header: area_id = 0x%x", AifHdr->Area_ID);
2339fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2340fcf3ce44SJohn Forte 	    "AIF Header: rosize = 0x%x", AifHdr->RoSize);
2341fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2342fcf3ce44SJohn Forte 	    "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize);
2343fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2344fcf3ce44SJohn Forte 	    "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize);
2345fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2346fcf3ce44SJohn Forte 	    "AIF Header: dbgtype = 0x%x", AifHdr->DbgType);
2347fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2348fcf3ce44SJohn Forte 	    "AIF Header: imagebase = 0x%x", AifHdr->ImageBase);
2349fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2350fcf3ce44SJohn Forte 	    "AIF Header: area_size = 0x%x", AifHdr->Area_Size);
2351fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2352fcf3ce44SJohn Forte 	    "AIF Header: address_mode = 0x%x", AifHdr->AddressMode);
2353fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2354fcf3ce44SJohn Forte 	    "AIF Header: database = 0x%x", AifHdr->DataBase);
2355fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2356fcf3ce44SJohn Forte 	    "AIF Header: aversion = 0x%x", AifHdr->AVersion);
2357fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2358fcf3ce44SJohn Forte 	    "AIF Header: spare2 = 0x%x", AifHdr->Spare2);
2359fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2360fcf3ce44SJohn Forte 	    "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi);
2361fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2362fcf3ce44SJohn Forte 	    "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]);
2363fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2364fcf3ce44SJohn Forte 	    "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]);
2365fcf3ce44SJohn Forte 
236682527734SSukumar Swaminathan } /* emlxs_disp_aif_header() */
2367fcf3ce44SJohn Forte 
2368fcf3ce44SJohn Forte 
2369fcf3ce44SJohn Forte 
2370fcf3ce44SJohn Forte static void
emlxs_dump_image_header(emlxs_hba_t * hba,PIMAGE_HDR image)2371fcf3ce44SJohn Forte emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image)
2372fcf3ce44SJohn Forte {
2373fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2374fcf3ce44SJohn Forte 
2375291a2b48SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: ");
2376fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2377fcf3ce44SJohn Forte 	    "Img Header: BlockSize = 0x%x", image->BlockSize);
2378fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2379fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Type = 0x%x", image->Id.Type);
2380fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2381fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Id = 0x%x", image->Id.Id);
2382fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2383fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver);
2384fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2385fcf3ce44SJohn Forte 	    "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev);
2386fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2387fcf3ce44SJohn Forte 	    "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp);
2388fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2389fcf3ce44SJohn Forte 	    "Img Header: Flags = 0x%x", image->Flags);
2390fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2391fcf3ce44SJohn Forte 	    "Img Header: EntryAdr = 0x%x", image->EntryAdr);
2392fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2393fcf3ce44SJohn Forte 	    "Img Header: InitAdr = 0x%x", image->InitAdr);
2394fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2395fcf3ce44SJohn Forte 	    "Img Header: ExitAdr = 0x%x", image->ExitAdr);
2396fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2397fcf3ce44SJohn Forte 	    "Img Header: ImageBase = 0x%x", image->ImageBase);
2398fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2399fcf3ce44SJohn Forte 	    "Img Header: ImageSize = 0x%x", image->ImageSize);
2400fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2401fcf3ce44SJohn Forte 	    "Img Header: ZinitSize = 0x%x", image->ZinitSize);
2402fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2403fcf3ce44SJohn Forte 	    "Img Header: RelocSize = 0x%x", image->RelocSize);
2404fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2405fcf3ce44SJohn Forte 	    "Img Header: HdrCks = 0x%x", image->HdrCks);
2406fcf3ce44SJohn Forte 
240782527734SSukumar Swaminathan } /* emlxs_dump_image_header() */
2408fcf3ce44SJohn Forte 
2409fcf3ce44SJohn Forte 
2410fcf3ce44SJohn Forte static void
emlxs_format_dump(emlxs_hba_t * hba,MAILBOXQ * mbq,uint32_t Type,uint32_t RegionId,uint32_t WordCount,uint32_t BaseAddr)241182527734SSukumar Swaminathan emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t Type,
241282527734SSukumar Swaminathan     uint32_t RegionId, uint32_t WordCount, uint32_t BaseAddr)
2413fcf3ce44SJohn Forte {
2414fcf3ce44SJohn Forte 
241582527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
241682527734SSukumar Swaminathan 		MAILBOX4 *mb = (MAILBOX4 *)mbq;
241782527734SSukumar Swaminathan 
241882527734SSukumar Swaminathan 		/* Clear the local dump_region */
241982527734SSukumar Swaminathan 		bzero(hba->sli.sli4.dump_region.virt,
242082527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size);
242182527734SSukumar Swaminathan 
242282527734SSukumar Swaminathan 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
242382527734SSukumar Swaminathan 
242482527734SSukumar Swaminathan 		mb->mbxCommand = MBX_DUMP_MEMORY;
242582527734SSukumar Swaminathan 		mb->un.varDmp4.type = Type;
242682527734SSukumar Swaminathan 		mb->un.varDmp4.entry_index = BaseAddr;
242782527734SSukumar Swaminathan 		mb->un.varDmp4.region_id = RegionId;
242882527734SSukumar Swaminathan 
242982527734SSukumar Swaminathan 		mb->un.varDmp4.available_cnt = min((WordCount*4),
243082527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size);
243182527734SSukumar Swaminathan 		mb->un.varDmp4.addrHigh =
243282527734SSukumar Swaminathan 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
243382527734SSukumar Swaminathan 		mb->un.varDmp4.addrLow =
243482527734SSukumar Swaminathan 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
243582527734SSukumar Swaminathan 		mb->un.varDmp4.rsp_cnt = 0;
243682527734SSukumar Swaminathan 
243782527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
243882527734SSukumar Swaminathan 
243982527734SSukumar Swaminathan 	} else {
244082527734SSukumar Swaminathan 		MAILBOX *mb = (MAILBOX *)mbq;
244182527734SSukumar Swaminathan 
244282527734SSukumar Swaminathan 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
244382527734SSukumar Swaminathan 
244482527734SSukumar Swaminathan 		mb->mbxCommand = MBX_DUMP_MEMORY;
244582527734SSukumar Swaminathan 		mb->un.varDmp.type = Type;
244682527734SSukumar Swaminathan 		mb->un.varDmp.region_id = RegionId;
244782527734SSukumar Swaminathan 		mb->un.varDmp.word_cnt = WordCount;
244882527734SSukumar Swaminathan 		mb->un.varDmp.base_adr = BaseAddr;
244982527734SSukumar Swaminathan 		mb->mbxOwner = OWN_HOST;
245082527734SSukumar Swaminathan 	}
245182527734SSukumar Swaminathan 
245282527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2453fcf3ce44SJohn Forte 
2454fcf3ce44SJohn Forte 	return;
2455fcf3ce44SJohn Forte 
245682527734SSukumar Swaminathan } /* emlxs_format_dump() */
2457fcf3ce44SJohn Forte 
2458fcf3ce44SJohn Forte 
2459fcf3ce44SJohn Forte /* ARGSUSED */
2460fcf3ce44SJohn Forte static uint32_t
emlxs_start_abs_download(emlxs_hba_t * hba,PAIF_HDR AifHdr,caddr_t Buffer,uint32_t len,PWAKE_UP_PARMS WakeUpParms)2461291a2b48SSukumar Swaminathan emlxs_start_abs_download(emlxs_hba_t *hba,
2462291a2b48SSukumar Swaminathan     PAIF_HDR AifHdr,
2463291a2b48SSukumar Swaminathan     caddr_t Buffer,
24646a573d82SSukumar Swaminathan     uint32_t len,
24656a573d82SSukumar Swaminathan     PWAKE_UP_PARMS WakeUpParms)
2466fcf3ce44SJohn Forte {
2467fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2468fcf3ce44SJohn Forte 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
2469fcf3ce44SJohn Forte 	uint32_t *Src;
2470fcf3ce44SJohn Forte 	uint32_t *Dst;
2471fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
2472fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2473fcf3ce44SJohn Forte 	MAILBOX *mb;
2474fcf3ce44SJohn Forte 	uint32_t rval = 1;
2475fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
2476fcf3ce44SJohn Forte 	uint32_t DlToAddr = AifHdr->ImageBase;
2477fcf3ce44SJohn Forte 	uint32_t DlCount;
2478fcf3ce44SJohn Forte 	uint32_t i;
24796a573d82SSukumar Swaminathan 	WAKE_UP_PARMS AbsWakeUpParms;
24806a573d82SSukumar Swaminathan 	int32_t AbsChangeParams;
2481fcf3ce44SJohn Forte 
24826a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2483fcf3ce44SJohn Forte 	    "Performing absolute download...");
2484fcf3ce44SJohn Forte 
2485291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
2486291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2487fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2488fcf3ce44SJohn Forte 		    "Unable to allocate data buffer.");
2489fcf3ce44SJohn Forte 
2490fcf3ce44SJohn Forte 		return (rval);
2491fcf3ce44SJohn Forte 	}
2492291a2b48SSukumar Swaminathan 
2493291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2494291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2495fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2496fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2497fcf3ce44SJohn Forte 
2498fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2499fcf3ce44SJohn Forte 
2500fcf3ce44SJohn Forte 		return (rval);
2501fcf3ce44SJohn Forte 	}
2502fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2503fcf3ce44SJohn Forte 
25046a573d82SSukumar Swaminathan 	AbsChangeParams = emlxs_build_parms(Buffer,
25056a573d82SSukumar Swaminathan 	    &AbsWakeUpParms, len, AifHdr);
25066a573d82SSukumar Swaminathan 
2507fcf3ce44SJohn Forte 	Buffer += sizeof (AIF_HDR);
2508fcf3ce44SJohn Forte 
25096a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Erasing flash...");
2510fcf3ce44SJohn Forte 
25116a573d82SSukumar Swaminathan 	if (AifHdr->ImageBase == 0x20000) {
25126a573d82SSukumar Swaminathan 		/* DWC File */
251382527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0,
25146a573d82SSukumar Swaminathan 		    0, 0, NULL, 0);
2515fcf3ce44SJohn Forte 	} else {
251682527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount,
25176a573d82SSukumar Swaminathan 		    ERASE_FLASH, 0, 0, 0, NULL, 0);
2518fcf3ce44SJohn Forte 	}
2519fcf3ce44SJohn Forte 
252082527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2521fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2522fcf3ce44SJohn Forte 		    "Unable to erase Flash: Mailbox cmd=%x status=%x",
2523fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
2524fcf3ce44SJohn Forte 
2525fcf3ce44SJohn Forte 		rval = 1;
2526fcf3ce44SJohn Forte 
2527fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
2528fcf3ce44SJohn Forte 	}
2529291a2b48SSukumar Swaminathan 
25306a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2531291a2b48SSukumar Swaminathan 	    "Programming flash...");
2532fcf3ce44SJohn Forte 
2533fcf3ce44SJohn Forte 	while (DlByteCount) {
2534fcf3ce44SJohn Forte 
2535fcf3ce44SJohn Forte 		if (DlByteCount > SegSize) {
2536fcf3ce44SJohn Forte 			DlCount = SegSize;
2537fcf3ce44SJohn Forte 		} else {
2538fcf3ce44SJohn Forte 			DlCount = DlByteCount;
2539fcf3ce44SJohn Forte 		}
2540fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
2541fcf3ce44SJohn Forte 
2542fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
2543fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
2544fcf3ce44SJohn Forte 
2545fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
2546fcf3ce44SJohn Forte 			*Dst = *Src;
2547fcf3ce44SJohn Forte 			Dst++;
2548fcf3ce44SJohn Forte 			Src++;
2549fcf3ce44SJohn Forte 		}
2550fcf3ce44SJohn Forte 
2551fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
255282527734SSukumar Swaminathan 		    (volatile uint32_t *)
255382527734SSukumar Swaminathan 		    ((volatile char *)hba->sli.sli3.slim_addr +
2554291a2b48SSukumar Swaminathan 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2555fcf3ce44SJohn Forte 
255682527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox, DlToAddr, DlCount,
25576a573d82SSukumar Swaminathan 		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL, 0);
2558fcf3ce44SJohn Forte 
255982527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2560291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
2561fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2562fcf3ce44SJohn Forte 			    "Unable to program Flash: Mailbox cmd=%x status=%x",
2563fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
2564fcf3ce44SJohn Forte 
2565fcf3ce44SJohn Forte 			rval = 1;
2566fcf3ce44SJohn Forte 
2567fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
2568fcf3ce44SJohn Forte 		}
2569291a2b48SSukumar Swaminathan 
2570fcf3ce44SJohn Forte 		Buffer += DlCount;
2571fcf3ce44SJohn Forte 		DlToAddr += DlCount;
2572fcf3ce44SJohn Forte 	}
2573fcf3ce44SJohn Forte 
25744baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
257582527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
25764baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
25774baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
25784baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
25794baa2c25SSukumar Swaminathan 
25804baa2c25SSukumar Swaminathan 		rval = 1;
25814baa2c25SSukumar Swaminathan 
25824baa2c25SSukumar Swaminathan 		goto EXIT_ABS_DOWNLOAD;
25834baa2c25SSukumar Swaminathan 	}
25844baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
25854baa2c25SSukumar Swaminathan 
2586fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
2587fcf3ce44SJohn Forte 
25886a573d82SSukumar Swaminathan 	if (AbsChangeParams) {
2589291a2b48SSukumar Swaminathan 		rval =
25906a573d82SSukumar Swaminathan 		    emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
2591fcf3ce44SJohn Forte 		    WakeUpParms);
2592fcf3ce44SJohn Forte 	}
2593fcf3ce44SJohn Forte 
2594fcf3ce44SJohn Forte EXIT_ABS_DOWNLOAD:
2595fcf3ce44SJohn Forte 	if (DataBuffer) {
2596fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2597fcf3ce44SJohn Forte 	}
2598291a2b48SSukumar Swaminathan 
2599fcf3ce44SJohn Forte 	if (mbox) {
2600fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2601fcf3ce44SJohn Forte 	}
2602291a2b48SSukumar Swaminathan 
2603fcf3ce44SJohn Forte 	return (rval);
2604fcf3ce44SJohn Forte 
260582527734SSukumar Swaminathan } /* emlxs_start_abs_download() */
2606fcf3ce44SJohn Forte 
2607fcf3ce44SJohn Forte 
2608fcf3ce44SJohn Forte /* ARGSUSED */
2609fcf3ce44SJohn Forte static void
emlxs_format_prog_flash(MAILBOXQ * mbq,uint32_t Base,uint32_t DlByteCount,uint32_t Function,uint32_t Complete,uint32_t BdeAddress,uint32_t BdeSize,PROG_ID * ProgId,uint32_t keep)261082527734SSukumar Swaminathan emlxs_format_prog_flash(MAILBOXQ *mbq,
2611291a2b48SSukumar Swaminathan     uint32_t Base,
2612291a2b48SSukumar Swaminathan     uint32_t DlByteCount,
2613291a2b48SSukumar Swaminathan     uint32_t Function,
2614291a2b48SSukumar Swaminathan     uint32_t Complete,
26156a573d82SSukumar Swaminathan     uint32_t BdeAddress,
26166a573d82SSukumar Swaminathan     uint32_t BdeSize,
26176a573d82SSukumar Swaminathan     PROG_ID *ProgId,
26186a573d82SSukumar Swaminathan     uint32_t keep)
2619fcf3ce44SJohn Forte {
262082527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
262182527734SSukumar Swaminathan 
2622291a2b48SSukumar Swaminathan 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2623fcf3ce44SJohn Forte 
26246a573d82SSukumar Swaminathan 	if (ProgId) {
2625fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_DOWN_LOAD;
26266a573d82SSukumar Swaminathan 	} else {
2627fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_SM;
26286a573d82SSukumar Swaminathan 	}
2629fcf3ce44SJohn Forte 
2630fcf3ce44SJohn Forte 	mb->un.varLdSM.load_cmplt = Complete;
2631fcf3ce44SJohn Forte 	mb->un.varLdSM.method = DL_FROM_SLIM;
2632fcf3ce44SJohn Forte 	mb->un.varLdSM.update_flash = 1;
2633fcf3ce44SJohn Forte 	mb->un.varLdSM.erase_or_prog = Function;
2634fcf3ce44SJohn Forte 	mb->un.varLdSM.dl_to_adr = Base;
2635fcf3ce44SJohn Forte 	mb->un.varLdSM.dl_len = DlByteCount;
26366a573d82SSukumar Swaminathan 	mb->un.varLdSM.keep = keep;
2637fcf3ce44SJohn Forte 
2638fcf3ce44SJohn Forte 	if (BdeSize) {
2639fcf3ce44SJohn Forte 		mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
2640fcf3ce44SJohn Forte 	} else if (ProgId) {
2641fcf3ce44SJohn Forte 		mb->un.varLdSM.un.prog_id = *ProgId;
2642fcf3ce44SJohn Forte 	} else {
2643fcf3ce44SJohn Forte 		mb->un.varLdSM.un.dl_from_slim_offset = 0;
2644fcf3ce44SJohn Forte 	}
2645fcf3ce44SJohn Forte 
2646fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
264782527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
2648fcf3ce44SJohn Forte 
264982527734SSukumar Swaminathan } /* emlxs_format_prog_flash() */
2650fcf3ce44SJohn Forte 
2651fcf3ce44SJohn Forte 
2652fcf3ce44SJohn Forte static void
emlxs_format_update_parms(MAILBOXQ * mbq,PWAKE_UP_PARMS WakeUpParms)265382527734SSukumar Swaminathan emlxs_format_update_parms(MAILBOXQ *mbq, PWAKE_UP_PARMS WakeUpParms)
2654fcf3ce44SJohn Forte {
265582527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
265682527734SSukumar Swaminathan 
2657fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2658fcf3ce44SJohn Forte 
2659fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UPDATE_CFG;
2660fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2661fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID;
2662fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS);
2663fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS);
2664fcf3ce44SJohn Forte 
2665291a2b48SSukumar Swaminathan 	bcopy((caddr_t)WakeUpParms,
2666291a2b48SSukumar Swaminathan 	    (caddr_t)&(mb->un.varUpdateCfg.cfg_data),
2667fcf3ce44SJohn Forte 	    sizeof (WAKE_UP_PARMS));
266882527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
2669fcf3ce44SJohn Forte 
267082527734SSukumar Swaminathan } /* emlxs_format_update_parms () */
2671fcf3ce44SJohn Forte 
2672fcf3ce44SJohn Forte 
2673fcf3ce44SJohn Forte /* ARGSUSED */
2674fcf3ce44SJohn Forte static void
emlxs_format_update_pci_cfg(emlxs_hba_t * hba,MAILBOXQ * mbq,uint32_t region_id,uint32_t size)267582527734SSukumar Swaminathan emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
2676fcf3ce44SJohn Forte     uint32_t region_id, uint32_t size)
2677fcf3ce44SJohn Forte {
267882527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
267982527734SSukumar Swaminathan 
2680fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2681fcf3ce44SJohn Forte 
2682fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_UPDATE_CFG;
2683fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.Vbit = 1;
2684fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.Obit = 1;
2685fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET;
2686fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2687fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.region_id = region_id;
2688fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.entry_len = size;
2689fcf3ce44SJohn Forte 	mb->un.varUpdateCfg.byte_len = size;
269082527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
2691fcf3ce44SJohn Forte 
269282527734SSukumar Swaminathan } /* emlxs_format_update_pci_cfg() */
2693fcf3ce44SJohn Forte 
2694fcf3ce44SJohn Forte 
2695fcf3ce44SJohn Forte 
2696fcf3ce44SJohn Forte static uint32_t
emlxs_update_boot_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id,uint32_t proc_erom)2697fcf3ce44SJohn Forte emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2698fcf3ce44SJohn Forte     PROG_ID * prog_id, uint32_t proc_erom)
2699fcf3ce44SJohn Forte {
2700fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2701fcf3ce44SJohn Forte 	MAILBOX *mb;
2702fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2703fcf3ce44SJohn Forte 	uint32_t rval = 0;
27046a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2705fcf3ce44SJohn Forte 
2706291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2707291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2708fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2709fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2710fcf3ce44SJohn Forte 
2711fcf3ce44SJohn Forte 		return (1);
2712fcf3ce44SJohn Forte 	}
2713fcf3ce44SJohn Forte 
2714291a2b48SSukumar Swaminathan 	mb = (MAILBOX *)mbox;
2715291a2b48SSukumar Swaminathan 
2716291a2b48SSukumar Swaminathan 	if (proc_erom && !(hba->model_info.chip &
2717fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2718fcf3ce44SJohn Forte 		WakeUpParms->u1.EROM_prog_id = *prog_id;
2719fcf3ce44SJohn Forte 		(void) emlxs_update_exp_rom(hba, WakeUpParms);
2720fcf3ce44SJohn Forte 	}
2721291a2b48SSukumar Swaminathan 
27226a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->u0.boot_bios_id;
2723fcf3ce44SJohn Forte 	WakeUpParms->u0.boot_bios_id = *prog_id;
2724fcf3ce44SJohn Forte 
272582527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2726fcf3ce44SJohn Forte 
272782527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2728fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2729291a2b48SSukumar Swaminathan 		    "Unable to update boot wakeup parms: Mailbox cmd=%x "
2730291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2731fcf3ce44SJohn Forte 
27326a573d82SSukumar Swaminathan 		WakeUpParms->u0.boot_bios_id = old_prog_id;
2733fcf3ce44SJohn Forte 		rval = 1;
2734fcf3ce44SJohn Forte 	}
2735291a2b48SSukumar Swaminathan 
2736fcf3ce44SJohn Forte 	if (mbox) {
2737fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2738fcf3ce44SJohn Forte 	}
2739291a2b48SSukumar Swaminathan 
2740fcf3ce44SJohn Forte 	return (rval);
2741fcf3ce44SJohn Forte 
274282527734SSukumar Swaminathan } /* emlxs_update_boot_wakeup_parms() */
2743fcf3ce44SJohn Forte 
2744fcf3ce44SJohn Forte 
2745fcf3ce44SJohn Forte 
2746fcf3ce44SJohn Forte static uint32_t
emlxs_update_ff_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2747fcf3ce44SJohn Forte emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2748fcf3ce44SJohn Forte     PROG_ID *prog_id)
2749fcf3ce44SJohn Forte {
2750fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2751fcf3ce44SJohn Forte 	uint32_t rval = 0;
2752fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2753fcf3ce44SJohn Forte 	MAILBOX *mb;
27546a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2755fcf3ce44SJohn Forte 
2756291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2757291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2758fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2759fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2760fcf3ce44SJohn Forte 
2761fcf3ce44SJohn Forte 		return (1);
2762fcf3ce44SJohn Forte 	}
2763291a2b48SSukumar Swaminathan 
27646a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
27656a573d82SSukumar Swaminathan 	    "FF: Updating parms...");
27666a573d82SSukumar Swaminathan 
2767fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2768fcf3ce44SJohn Forte 
27696a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->prog_id;
2770fcf3ce44SJohn Forte 	WakeUpParms->prog_id = *prog_id;
2771fcf3ce44SJohn Forte 
277282527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2773fcf3ce44SJohn Forte 
277482527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2775fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2776291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
2777291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2778fcf3ce44SJohn Forte 
27796a573d82SSukumar Swaminathan 		WakeUpParms->prog_id = old_prog_id;
2780fcf3ce44SJohn Forte 		rval = 1;
2781fcf3ce44SJohn Forte 	}
2782291a2b48SSukumar Swaminathan 
2783fcf3ce44SJohn Forte 	if (mbox) {
2784fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2785fcf3ce44SJohn Forte 	}
2786291a2b48SSukumar Swaminathan 
2787fcf3ce44SJohn Forte 	return (rval);
2788fcf3ce44SJohn Forte 
278982527734SSukumar Swaminathan } /* emlxs_update_ff_wakeup_parms() */
2790fcf3ce44SJohn Forte 
2791fcf3ce44SJohn Forte 
2792fcf3ce44SJohn Forte static uint32_t
emlxs_update_sli1_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2793fcf3ce44SJohn Forte emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2794291a2b48SSukumar Swaminathan     PROG_ID * prog_id)
2795fcf3ce44SJohn Forte {
2796fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2797fcf3ce44SJohn Forte 	uint32_t rval = 0;
2798fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2799fcf3ce44SJohn Forte 	MAILBOX *mb;
28006a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2801fcf3ce44SJohn Forte 
2802291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2803291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2804fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2805fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2806fcf3ce44SJohn Forte 
2807fcf3ce44SJohn Forte 		return (1);
2808fcf3ce44SJohn Forte 	}
2809291a2b48SSukumar Swaminathan 
28106a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
28116a573d82SSukumar Swaminathan 	    "SLI1: Updating parms...");
28126a573d82SSukumar Swaminathan 
2813fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2814fcf3ce44SJohn Forte 
28156a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli1_prog_id;
2816fcf3ce44SJohn Forte 	WakeUpParms->sli1_prog_id = *prog_id;
2817fcf3ce44SJohn Forte 
281882527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2819fcf3ce44SJohn Forte 
282082527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2821fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2822291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2823291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2824fcf3ce44SJohn Forte 
28256a573d82SSukumar Swaminathan 		WakeUpParms->sli1_prog_id = old_prog_id;
2826fcf3ce44SJohn Forte 		rval = 1;
2827fcf3ce44SJohn Forte 	}
2828291a2b48SSukumar Swaminathan 
2829fcf3ce44SJohn Forte 	if (mbox) {
2830fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2831fcf3ce44SJohn Forte 	}
2832291a2b48SSukumar Swaminathan 
2833fcf3ce44SJohn Forte 	return (rval);
2834fcf3ce44SJohn Forte 
283582527734SSukumar Swaminathan } /* emlxs_update_sli1_wakeup_parms() */
2836fcf3ce44SJohn Forte 
2837fcf3ce44SJohn Forte 
2838fcf3ce44SJohn Forte static uint32_t
emlxs_update_sli2_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2839fcf3ce44SJohn Forte emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2840291a2b48SSukumar Swaminathan     PROG_ID * prog_id)
2841fcf3ce44SJohn Forte {
2842fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2843fcf3ce44SJohn Forte 	uint32_t rval = 0;
2844fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2845fcf3ce44SJohn Forte 	MAILBOX *mb;
28466a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2847fcf3ce44SJohn Forte 
2848291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2849291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2850fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2851fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2852fcf3ce44SJohn Forte 
2853fcf3ce44SJohn Forte 		return (1);
2854fcf3ce44SJohn Forte 	}
2855291a2b48SSukumar Swaminathan 
28566a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
28576a573d82SSukumar Swaminathan 	    "SLI2: Updating parms...");
28586a573d82SSukumar Swaminathan 
2859fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2860fcf3ce44SJohn Forte 
28616a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli2_prog_id;
2862fcf3ce44SJohn Forte 	WakeUpParms->sli2_prog_id = *prog_id;
2863fcf3ce44SJohn Forte 
286482527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2865fcf3ce44SJohn Forte 
286682527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2867fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2868291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2869291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2870fcf3ce44SJohn Forte 
28716a573d82SSukumar Swaminathan 		WakeUpParms->sli2_prog_id = old_prog_id;
2872fcf3ce44SJohn Forte 		rval = 1;
2873fcf3ce44SJohn Forte 	}
2874291a2b48SSukumar Swaminathan 
2875fcf3ce44SJohn Forte 	if (mbox) {
2876fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2877fcf3ce44SJohn Forte 	}
2878291a2b48SSukumar Swaminathan 
2879fcf3ce44SJohn Forte 	return (rval);
2880fcf3ce44SJohn Forte 
288182527734SSukumar Swaminathan } /* emlxs_update_sli2_wakeup_parms() */
2882fcf3ce44SJohn Forte 
2883fcf3ce44SJohn Forte 
2884fcf3ce44SJohn Forte static uint32_t
emlxs_update_sli3_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2885fcf3ce44SJohn Forte emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2886fcf3ce44SJohn Forte     PROG_ID *prog_id)
2887fcf3ce44SJohn Forte {
2888fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2889fcf3ce44SJohn Forte 	uint32_t rval = 0;
2890fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2891fcf3ce44SJohn Forte 	MAILBOX *mb;
28926a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2893fcf3ce44SJohn Forte 
2894291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2895291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2896fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2897fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2898fcf3ce44SJohn Forte 
2899fcf3ce44SJohn Forte 		return (1);
2900fcf3ce44SJohn Forte 	}
2901291a2b48SSukumar Swaminathan 
29026a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
29036a573d82SSukumar Swaminathan 	    "SLI3: Updating parms...");
29046a573d82SSukumar Swaminathan 
2905fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2906fcf3ce44SJohn Forte 
29076a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli3_prog_id;
2908fcf3ce44SJohn Forte 	WakeUpParms->sli3_prog_id = *prog_id;
2909fcf3ce44SJohn Forte 
291082527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2911fcf3ce44SJohn Forte 
291282527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2913fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2914291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2915291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2916fcf3ce44SJohn Forte 
29176a573d82SSukumar Swaminathan 		WakeUpParms->sli3_prog_id = old_prog_id;
2918fcf3ce44SJohn Forte 		rval = 1;
2919fcf3ce44SJohn Forte 	}
2920291a2b48SSukumar Swaminathan 
2921fcf3ce44SJohn Forte 	if (mbox) {
2922fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2923fcf3ce44SJohn Forte 	}
2924291a2b48SSukumar Swaminathan 
2925fcf3ce44SJohn Forte 	return (rval);
2926fcf3ce44SJohn Forte 
292782527734SSukumar Swaminathan } /* emlxs_update_sli3_wakeup_parms() */
2928fcf3ce44SJohn Forte 
2929fcf3ce44SJohn Forte 
2930fcf3ce44SJohn Forte static uint32_t
emlxs_update_sli4_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2931fcf3ce44SJohn Forte emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2932fcf3ce44SJohn Forte     PROG_ID *prog_id)
2933fcf3ce44SJohn Forte {
2934fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
2935fcf3ce44SJohn Forte 	uint32_t rval = 0;
2936fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
2937fcf3ce44SJohn Forte 	MAILBOX *mb;
29386a573d82SSukumar Swaminathan 	PROG_ID old_prog_id;
2939fcf3ce44SJohn Forte 
2940291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2941291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
2942fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2943fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
2944fcf3ce44SJohn Forte 
2945fcf3ce44SJohn Forte 		return (1);
2946fcf3ce44SJohn Forte 	}
2947291a2b48SSukumar Swaminathan 
29486a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
29496a573d82SSukumar Swaminathan 	    "SLI4: Updating parms...");
29506a573d82SSukumar Swaminathan 
2951fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
2952fcf3ce44SJohn Forte 
29536a573d82SSukumar Swaminathan 	old_prog_id = WakeUpParms->sli4_prog_id;
2954fcf3ce44SJohn Forte 	WakeUpParms->sli4_prog_id = *prog_id;
2955fcf3ce44SJohn Forte 
295682527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
2957fcf3ce44SJohn Forte 
295882527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2959fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2960291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2961291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2962fcf3ce44SJohn Forte 
29636a573d82SSukumar Swaminathan 		WakeUpParms->sli4_prog_id = old_prog_id;
2964fcf3ce44SJohn Forte 		rval = 1;
2965fcf3ce44SJohn Forte 	}
2966291a2b48SSukumar Swaminathan 
2967fcf3ce44SJohn Forte 	if (mbox) {
2968fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
2969fcf3ce44SJohn Forte 	}
2970291a2b48SSukumar Swaminathan 
2971fcf3ce44SJohn Forte 	return (rval);
2972fcf3ce44SJohn Forte 
297382527734SSukumar Swaminathan } /* emlxs_update_sli4_wakeup_parms() */
2974fcf3ce44SJohn Forte 
2975fcf3ce44SJohn Forte 
29766a573d82SSukumar Swaminathan static uint32_t
emlxs_clean_flash(emlxs_hba_t * hba,PWAKE_UP_PARMS OldWakeUpParms,PWAKE_UP_PARMS NewWakeUpParms)29776a573d82SSukumar Swaminathan emlxs_clean_flash(emlxs_hba_t *hba,
29786a573d82SSukumar Swaminathan     PWAKE_UP_PARMS OldWakeUpParms, PWAKE_UP_PARMS NewWakeUpParms)
29796a573d82SSukumar Swaminathan {
29806a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
29816a573d82SSukumar Swaminathan 	PROG_ID load_list[MAX_LOAD_ENTRY];
29826a573d82SSukumar Swaminathan 	PROG_ID *wakeup_list[MAX_LOAD_ENTRY];
29836a573d82SSukumar Swaminathan 	uint32_t count;
29846a573d82SSukumar Swaminathan 	uint32_t i;
29856a573d82SSukumar Swaminathan 	uint32_t j;
29866a573d82SSukumar Swaminathan 	uint32_t k = 0;
29876a573d82SSukumar Swaminathan 	uint32_t *wptr;
29886a573d82SSukumar Swaminathan 
29896a573d82SSukumar Swaminathan 	if (!NewWakeUpParms) {
29906a573d82SSukumar Swaminathan 		return (1);
29916a573d82SSukumar Swaminathan 	}
29926a573d82SSukumar Swaminathan 
29936a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
29946a573d82SSukumar Swaminathan 	    "Cleaning flash...");
29956a573d82SSukumar Swaminathan 
29966a573d82SSukumar Swaminathan 	/* If old wakeup parameter list is available, */
29976a573d82SSukumar Swaminathan 	/* then cleanup old entries */
29986a573d82SSukumar Swaminathan 	if (OldWakeUpParms) {
29996a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->prog_id, &NewWakeUpParms->prog_id,
30006a573d82SSukumar Swaminathan 		    sizeof (PROG_ID))) {
30016a573d82SSukumar Swaminathan 
30026a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->prog_id;
30036a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
30046a573d82SSukumar Swaminathan 			    "OLD:      prog_id: 0x%08x 0x%08x  Removing.",
30056a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
30066a573d82SSukumar Swaminathan 
30076a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
30086a573d82SSukumar Swaminathan 			    &OldWakeUpParms->prog_id);
30096a573d82SSukumar Swaminathan 		}
30106a573d82SSukumar Swaminathan 
30116a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->u0.boot_bios_id,
30126a573d82SSukumar Swaminathan 		    &NewWakeUpParms->u0.boot_bios_id, sizeof (PROG_ID))) {
30136a573d82SSukumar Swaminathan 
30146a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->u0.boot_bios_id;
30156a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
30166a573d82SSukumar Swaminathan 			    "OLD: boot_bios_id: 0x%08x 0x%08x  Removing.",
30176a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
30186a573d82SSukumar Swaminathan 
30196a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
30206a573d82SSukumar Swaminathan 			    &OldWakeUpParms->u0.boot_bios_id);
30216a573d82SSukumar Swaminathan 		}
30226a573d82SSukumar Swaminathan 
30236a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli1_prog_id,
30246a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli1_prog_id, sizeof (PROG_ID))) {
30256a573d82SSukumar Swaminathan 
30266a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli1_prog_id;
30276a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
30286a573d82SSukumar Swaminathan 			    "OLD: sli1_prog_id: 0x%08x 0x%08x  Removing.",
30296a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
30306a573d82SSukumar Swaminathan 
30316a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
30326a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli1_prog_id);
30336a573d82SSukumar Swaminathan 		}
30346a573d82SSukumar Swaminathan 
30356a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli2_prog_id,
30366a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli2_prog_id, sizeof (PROG_ID))) {
30376a573d82SSukumar Swaminathan 
30386a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli2_prog_id;
30396a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
30406a573d82SSukumar Swaminathan 			    "OLD: sli2_prog_id: 0x%08x 0x%08x  Removing.",
30416a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
30426a573d82SSukumar Swaminathan 
30436a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
30446a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli2_prog_id);
30456a573d82SSukumar Swaminathan 		}
30466a573d82SSukumar Swaminathan 
30476a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli3_prog_id,
30486a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli3_prog_id, sizeof (PROG_ID))) {
30496a573d82SSukumar Swaminathan 
30506a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli3_prog_id;
30516a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
30526a573d82SSukumar Swaminathan 			    "OLD: sli3_prog_id: 0x%08x 0x%08x  Removing.",
30536a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
30546a573d82SSukumar Swaminathan 
30556a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
30566a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli3_prog_id);
30576a573d82SSukumar Swaminathan 		}
30586a573d82SSukumar Swaminathan 
30596a573d82SSukumar Swaminathan 		if (bcmp(&OldWakeUpParms->sli4_prog_id,
30606a573d82SSukumar Swaminathan 		    &NewWakeUpParms->sli4_prog_id, sizeof (PROG_ID))) {
30616a573d82SSukumar Swaminathan 
30626a573d82SSukumar Swaminathan 			wptr = (uint32_t *)&OldWakeUpParms->sli4_prog_id;
30636a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
30646a573d82SSukumar Swaminathan 			    "OLD: sli4_prog_id: 0x%08x 0x%08x  Removing.",
30656a573d82SSukumar Swaminathan 			    wptr[0], wptr[1]);
30666a573d82SSukumar Swaminathan 
30676a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba,
30686a573d82SSukumar Swaminathan 			    &OldWakeUpParms->sli4_prog_id);
30696a573d82SSukumar Swaminathan 		}
30706a573d82SSukumar Swaminathan 
30716a573d82SSukumar Swaminathan 		return (0);
30726a573d82SSukumar Swaminathan 	}
30736a573d82SSukumar Swaminathan 
30746a573d82SSukumar Swaminathan 	/* Otherwise use the current load list */
30756a573d82SSukumar Swaminathan 	count = emlxs_get_load_list(hba, load_list);
30766a573d82SSukumar Swaminathan 
30776a573d82SSukumar Swaminathan 	if (!count) {
30786a573d82SSukumar Swaminathan 		return (1);
30796a573d82SSukumar Swaminathan 	}
30806a573d82SSukumar Swaminathan 
30816a573d82SSukumar Swaminathan 	/* Init the wakeup list */
30826a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->prog_id;
30836a573d82SSukumar Swaminathan 	if (*wptr) {
30846a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->prog_id;
30856a573d82SSukumar Swaminathan 	}
30866a573d82SSukumar Swaminathan 
30876a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->u0.boot_bios_id;
30886a573d82SSukumar Swaminathan 	if (*wptr) {
30896a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->u0.boot_bios_id;
30906a573d82SSukumar Swaminathan 	}
30916a573d82SSukumar Swaminathan 
30926a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli1_prog_id;
30936a573d82SSukumar Swaminathan 	if (*wptr) {
30946a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli1_prog_id;
30956a573d82SSukumar Swaminathan 	}
30966a573d82SSukumar Swaminathan 
30976a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli2_prog_id;
30986a573d82SSukumar Swaminathan 	if (*wptr) {
30996a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli2_prog_id;
31006a573d82SSukumar Swaminathan 	}
31016a573d82SSukumar Swaminathan 
31026a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli3_prog_id;
31036a573d82SSukumar Swaminathan 	if (*wptr) {
31046a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli3_prog_id;
31056a573d82SSukumar Swaminathan 	}
31066a573d82SSukumar Swaminathan 
31076a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&NewWakeUpParms->sli4_prog_id;
31086a573d82SSukumar Swaminathan 	if (*wptr) {
31096a573d82SSukumar Swaminathan 		wakeup_list[k++] = &NewWakeUpParms->sli4_prog_id;
31106a573d82SSukumar Swaminathan 	}
31116a573d82SSukumar Swaminathan 
31126a573d82SSukumar Swaminathan 	if (k == 0) {
31136a573d82SSukumar Swaminathan 		return (0);
31146a573d82SSukumar Swaminathan 	}
31156a573d82SSukumar Swaminathan 
31166a573d82SSukumar Swaminathan 	/* Match load list to wakeup list */
31176a573d82SSukumar Swaminathan 	for (i = 0; i < count; i++) {
31186a573d82SSukumar Swaminathan 
31196a573d82SSukumar Swaminathan 		wptr = (uint32_t *)&load_list[i];
31206a573d82SSukumar Swaminathan 
31216a573d82SSukumar Swaminathan 		for (j = 0; j < k; j++) {
31226a573d82SSukumar Swaminathan 			if (bcmp((uint8_t *)wakeup_list[j],
31236a573d82SSukumar Swaminathan 			    (uint8_t *)&load_list[i], sizeof (PROG_ID)) == 0) {
31246a573d82SSukumar Swaminathan 				break;
31256a573d82SSukumar Swaminathan 			}
31266a573d82SSukumar Swaminathan 		}
31276a573d82SSukumar Swaminathan 
31286a573d82SSukumar Swaminathan 		/* No match */
31296a573d82SSukumar Swaminathan 		if (j == k) {
31306a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
31316a573d82SSukumar Swaminathan 			    "Load List[%d]: %08x %08x  Removing.",
31326a573d82SSukumar Swaminathan 			    i, wptr[0], wptr[1]);
31336a573d82SSukumar Swaminathan 
31346a573d82SSukumar Swaminathan 			(void) emlxs_delete_load_entry(hba, &load_list[i]);
31356a573d82SSukumar Swaminathan 		} else {
31366a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
31376a573d82SSukumar Swaminathan 			    "Load List[%d]: %08x %08x  Preserving.",
31386a573d82SSukumar Swaminathan 			    i, wptr[0], wptr[1]);
31396a573d82SSukumar Swaminathan 		}
31406a573d82SSukumar Swaminathan 	}
31416a573d82SSukumar Swaminathan 
31426a573d82SSukumar Swaminathan 	return (0);
31436a573d82SSukumar Swaminathan 
31446a573d82SSukumar Swaminathan } /* emlxs_clean_flash() */
31456a573d82SSukumar Swaminathan 
31466a573d82SSukumar Swaminathan 
3147fcf3ce44SJohn Forte /* ARGSUSED */
3148fcf3ce44SJohn Forte static uint32_t
emlxs_start_rel_download(emlxs_hba_t * hba,PIMAGE_HDR ImageHdr,caddr_t Buffer,PWAKE_UP_PARMS WakeUpParms,uint32_t dwc_flag)3149291a2b48SSukumar Swaminathan emlxs_start_rel_download(emlxs_hba_t *hba,
3150291a2b48SSukumar Swaminathan     PIMAGE_HDR ImageHdr,
3151291a2b48SSukumar Swaminathan     caddr_t Buffer,
3152291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS WakeUpParms,
31536a573d82SSukumar Swaminathan     uint32_t dwc_flag)
3154fcf3ce44SJohn Forte {
3155fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3156fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
3157fcf3ce44SJohn Forte 	MAILBOX *mb;
3158fcf3ce44SJohn Forte 	uint32_t *Src;
3159fcf3ce44SJohn Forte 	uint32_t *Dst;
3160fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
31616a573d82SSukumar Swaminathan 	uint32_t rval = 0;
31626a573d82SSukumar Swaminathan 	uint32_t DlByteCount;
3163fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
3164fcf3ce44SJohn Forte 	uint32_t DlCount;
3165fcf3ce44SJohn Forte 	uint32_t i;
31666a573d82SSukumar Swaminathan 	uint32_t *wptr;
3167fcf3ce44SJohn Forte 
31686a573d82SSukumar Swaminathan 	wptr = (uint32_t *)&ImageHdr->Id;
31696a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
31706a573d82SSukumar Swaminathan 	    "Relative download: %08x %08x", wptr[0], wptr[1]);
3171fcf3ce44SJohn Forte 
3172291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
3173291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3174fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3175fcf3ce44SJohn Forte 		    "Unable to allocate data buffer.");
3176fcf3ce44SJohn Forte 
31776a573d82SSukumar Swaminathan 		return (1);
3178fcf3ce44SJohn Forte 	}
3179291a2b48SSukumar Swaminathan 
3180291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3181291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3182fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3183fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3184fcf3ce44SJohn Forte 
3185fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
3186fcf3ce44SJohn Forte 
31876a573d82SSukumar Swaminathan 		return (1);
3188fcf3ce44SJohn Forte 	}
3189291a2b48SSukumar Swaminathan 
3190fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3191fcf3ce44SJohn Forte 
31926a573d82SSukumar Swaminathan 	DlByteCount = ImageHdr->BlockSize;
31936a573d82SSukumar Swaminathan 
319482527734SSukumar Swaminathan 	emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
31956a573d82SSukumar Swaminathan 	    &ImageHdr->Id, 0);
31966a573d82SSukumar Swaminathan 
31976a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
31986a573d82SSukumar Swaminathan 	    "  Erasing flash...");
3199fcf3ce44SJohn Forte 
32006a573d82SSukumar Swaminathan 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
3201fcf3ce44SJohn Forte 
32026a573d82SSukumar Swaminathan 	if (rval) {
3203fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3204fcf3ce44SJohn Forte 		    "Unable to erase flash. Mailbox cmd=%x status=%x",
3205fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
3206fcf3ce44SJohn Forte 
3207fcf3ce44SJohn Forte 		goto EXIT_REL_DOWNLOAD;
3208fcf3ce44SJohn Forte 	}
3209291a2b48SSukumar Swaminathan 
32106a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
32116a573d82SSukumar Swaminathan 	    "  Programming flash...");
3212fcf3ce44SJohn Forte 
3213fcf3ce44SJohn Forte 	while (DlByteCount) {
3214fcf3ce44SJohn Forte 		if (DlByteCount > SegSize) {
3215fcf3ce44SJohn Forte 			DlCount = SegSize;
3216fcf3ce44SJohn Forte 		} else {
3217fcf3ce44SJohn Forte 			DlCount = DlByteCount;
3218fcf3ce44SJohn Forte 		}
3219fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
3220fcf3ce44SJohn Forte 
3221fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
3222fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
3223fcf3ce44SJohn Forte 
3224fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
3225fcf3ce44SJohn Forte 			*Dst = *Src;
3226fcf3ce44SJohn Forte 			Dst++;
3227fcf3ce44SJohn Forte 			Src++;
3228fcf3ce44SJohn Forte 		}
3229fcf3ce44SJohn Forte 
3230fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
323182527734SSukumar Swaminathan 		    (volatile uint32_t *)
323282527734SSukumar Swaminathan 		    ((volatile char *)hba->sli.sli3.slim_addr +
3233291a2b48SSukumar Swaminathan 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
3234fcf3ce44SJohn Forte 
323582527734SSukumar Swaminathan 		emlxs_format_prog_flash(mbox,
3236291a2b48SSukumar Swaminathan 		    0,
3237291a2b48SSukumar Swaminathan 		    DlCount,
3238291a2b48SSukumar Swaminathan 		    PROGRAM_FLASH,
32396a573d82SSukumar Swaminathan 		    (DlByteCount) ? 0 : 1,
32406a573d82SSukumar Swaminathan 		    0, DlCount, &ImageHdr->Id, dwc_flag);
3241fcf3ce44SJohn Forte 
32426a573d82SSukumar Swaminathan 		rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
32436a573d82SSukumar Swaminathan 
32446a573d82SSukumar Swaminathan 		if (rval) {
3245fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3246fcf3ce44SJohn Forte 			    "Unable to program flash. Mailbox cmd=%x status=%x",
3247fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
3248fcf3ce44SJohn Forte 
3249fcf3ce44SJohn Forte 			goto EXIT_REL_DOWNLOAD;
3250fcf3ce44SJohn Forte 		}
3251291a2b48SSukumar Swaminathan 
3252fcf3ce44SJohn Forte 		Buffer += DlCount;
3253fcf3ce44SJohn Forte 	}
3254fcf3ce44SJohn Forte 
32554baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
325682527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
32574baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
32584baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
32594baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
32604baa2c25SSukumar Swaminathan 
32614baa2c25SSukumar Swaminathan 		rval = 1;
32624baa2c25SSukumar Swaminathan 
32634baa2c25SSukumar Swaminathan 		goto EXIT_REL_DOWNLOAD;
32644baa2c25SSukumar Swaminathan 	}
32654baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
32664baa2c25SSukumar Swaminathan 
32676a573d82SSukumar Swaminathan 	/* Update wakeup parameters */
3268fcf3ce44SJohn Forte 	switch (ImageHdr->Id.Type) {
3269fcf3ce44SJohn Forte 	case TEST_PROGRAM:
3270fcf3ce44SJohn Forte 		break;
3271fcf3ce44SJohn Forte 
3272fcf3ce44SJohn Forte 	case FUNC_FIRMWARE:
32736a573d82SSukumar Swaminathan 		if (!dwc_flag) {
32746a573d82SSukumar Swaminathan 			rval = emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
32756a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
32766a573d82SSukumar Swaminathan 		} else {
32776a573d82SSukumar Swaminathan 			WakeUpParms->prog_id = ImageHdr->Id;
32786a573d82SSukumar Swaminathan 		}
3279fcf3ce44SJohn Forte 		break;
3280fcf3ce44SJohn Forte 
3281fcf3ce44SJohn Forte 	case BOOT_BIOS:
32826a573d82SSukumar Swaminathan 		if (!dwc_flag) {
32836a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
32846a573d82SSukumar Swaminathan 			    "BOOT: Updating parms...");
32856a573d82SSukumar Swaminathan 
32866a573d82SSukumar Swaminathan 			rval = emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
32876a573d82SSukumar Swaminathan 			    &ImageHdr->Id, 1);
32886a573d82SSukumar Swaminathan 		} else {
32896a573d82SSukumar Swaminathan 			if (hba->wakeup_parms.u0.boot_bios_wd[0]) {
32906a573d82SSukumar Swaminathan 				WakeUpParms->u0.boot_bios_id = ImageHdr->Id;
32916a573d82SSukumar Swaminathan 			}
32926a573d82SSukumar Swaminathan 
32936a573d82SSukumar Swaminathan 			if (!(hba->model_info.chip &
32946a573d82SSukumar Swaminathan 			    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
32956a573d82SSukumar Swaminathan 				WakeUpParms->u1.EROM_prog_id = ImageHdr->Id;
32966a573d82SSukumar Swaminathan 			}
32976a573d82SSukumar Swaminathan 		}
3298fcf3ce44SJohn Forte 		break;
3299fcf3ce44SJohn Forte 
3300fcf3ce44SJohn Forte 	case SLI1_OVERLAY:
33016a573d82SSukumar Swaminathan 		if (!dwc_flag) {
33026a573d82SSukumar Swaminathan 			rval = emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
33036a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
33046a573d82SSukumar Swaminathan 		} else {
33056a573d82SSukumar Swaminathan 			WakeUpParms->sli1_prog_id = ImageHdr->Id;
33066a573d82SSukumar Swaminathan 		}
3307fcf3ce44SJohn Forte 		break;
3308fcf3ce44SJohn Forte 
3309fcf3ce44SJohn Forte 	case SLI2_OVERLAY:
33106a573d82SSukumar Swaminathan 		if (!dwc_flag) {
33116a573d82SSukumar Swaminathan 			rval = emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
33126a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
33136a573d82SSukumar Swaminathan 		} else {
33146a573d82SSukumar Swaminathan 			WakeUpParms->sli2_prog_id = ImageHdr->Id;
33156a573d82SSukumar Swaminathan 		}
3316fcf3ce44SJohn Forte 		break;
3317fcf3ce44SJohn Forte 
3318fcf3ce44SJohn Forte 	case SLI3_OVERLAY:
33196a573d82SSukumar Swaminathan 		if (!dwc_flag) {
33206a573d82SSukumar Swaminathan 			rval = emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
33216a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
33226a573d82SSukumar Swaminathan 		} else {
33236a573d82SSukumar Swaminathan 			WakeUpParms->sli3_prog_id = ImageHdr->Id;
33246a573d82SSukumar Swaminathan 		}
3325fcf3ce44SJohn Forte 		break;
3326fcf3ce44SJohn Forte 
3327fcf3ce44SJohn Forte 	case SLI4_OVERLAY:
33286a573d82SSukumar Swaminathan 		if (!dwc_flag) {
33296a573d82SSukumar Swaminathan 			rval = emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
33306a573d82SSukumar Swaminathan 			    &ImageHdr->Id);
33316a573d82SSukumar Swaminathan 		} else {
33326a573d82SSukumar Swaminathan 			WakeUpParms->sli4_prog_id = ImageHdr->Id;
33336a573d82SSukumar Swaminathan 		}
3334fcf3ce44SJohn Forte 		break;
3335fcf3ce44SJohn Forte 
3336fcf3ce44SJohn Forte 	default:
3337fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3338291a2b48SSukumar Swaminathan 		    "Image type not supported. Type=%x", ImageHdr->Id.Type);
3339fcf3ce44SJohn Forte 
3340fcf3ce44SJohn Forte 		break;
3341fcf3ce44SJohn Forte 	}
3342fcf3ce44SJohn Forte 
3343fcf3ce44SJohn Forte EXIT_REL_DOWNLOAD:
3344fcf3ce44SJohn Forte 	if (DataBuffer) {
3345fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
3346fcf3ce44SJohn Forte 	}
3347291a2b48SSukumar Swaminathan 
3348fcf3ce44SJohn Forte 	if (mbox) {
3349fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3350fcf3ce44SJohn Forte 	}
3351291a2b48SSukumar Swaminathan 
3352fcf3ce44SJohn Forte 	return (rval);
3353fcf3ce44SJohn Forte 
335482527734SSukumar Swaminathan } /* emlxs_start_rel_download() */
3355fcf3ce44SJohn Forte 
3356fcf3ce44SJohn Forte 
33576a573d82SSukumar Swaminathan static uint32_t
emlxs_proc_rel_2mb(emlxs_hba_t * hba,caddr_t buffer,emlxs_fw_image_t * fw_image)33586a573d82SSukumar Swaminathan emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer, emlxs_fw_image_t *fw_image)
3359291a2b48SSukumar Swaminathan {
33606a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
33616a573d82SSukumar Swaminathan 	uint32_t rval = 0;
33626a573d82SSukumar Swaminathan 	WAKE_UP_PARMS RelWakeUpParms;
33636a573d82SSukumar Swaminathan 	WAKE_UP_PARMS WakeUpParms;
33646a573d82SSukumar Swaminathan 	uint32_t i;
33656a573d82SSukumar Swaminathan 	IMAGE_HDR ImageHdr;
33666a573d82SSukumar Swaminathan 	caddr_t bptr;
33676a573d82SSukumar Swaminathan 	uint32_t flash_cleaned = 0;
33686a573d82SSukumar Swaminathan 
33696a573d82SSukumar Swaminathan 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 0)) {
33706a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
33716a573d82SSukumar Swaminathan 		    "Unable to get wakeup parameters.");
33726a573d82SSukumar Swaminathan 
33736a573d82SSukumar Swaminathan 		return (EMLXS_IMAGE_FAILED);
33746a573d82SSukumar Swaminathan 	}
33756a573d82SSukumar Swaminathan 
33766a573d82SSukumar Swaminathan download:
33776a573d82SSukumar Swaminathan 
33786a573d82SSukumar Swaminathan 	bcopy(&WakeUpParms, &RelWakeUpParms, sizeof (WAKE_UP_PARMS));
33796a573d82SSukumar Swaminathan 
33806a573d82SSukumar Swaminathan 	for (i = 0; i < MAX_PROG_TYPES; i++) {
33816a573d82SSukumar Swaminathan 		if (!fw_image->prog[i].version) {
33826a573d82SSukumar Swaminathan 			continue;
33836a573d82SSukumar Swaminathan 		}
33846a573d82SSukumar Swaminathan 
33856a573d82SSukumar Swaminathan 		bptr = buffer + fw_image->prog[i].offset;
33866a573d82SSukumar Swaminathan 
33876a573d82SSukumar Swaminathan 		bcopy(bptr, &ImageHdr, sizeof (IMAGE_HDR));
33886a573d82SSukumar Swaminathan 
33896a573d82SSukumar Swaminathan 		rval = emlxs_start_rel_download(hba, &ImageHdr, bptr,
33906a573d82SSukumar Swaminathan 		    &RelWakeUpParms, 1);
33916a573d82SSukumar Swaminathan 
33926a573d82SSukumar Swaminathan 		if (rval) {
33936a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
33946a573d82SSukumar Swaminathan 			    &emlxs_download_failed_msg,
33956a573d82SSukumar Swaminathan 			    "Failed to program flash.");
33966a573d82SSukumar Swaminathan 
33976a573d82SSukumar Swaminathan 			if ((rval == NO_FLASH_MEM_AVAIL) && !flash_cleaned) {
33986a573d82SSukumar Swaminathan 				/* Cleanup using current load list */
33996a573d82SSukumar Swaminathan 				(void) emlxs_clean_flash(hba, 0, &WakeUpParms);
34006a573d82SSukumar Swaminathan 
34016a573d82SSukumar Swaminathan 				flash_cleaned = 1;
34026a573d82SSukumar Swaminathan 				goto download;
34036a573d82SSukumar Swaminathan 			}
34046a573d82SSukumar Swaminathan 
34056a573d82SSukumar Swaminathan 			return (EMLXS_IMAGE_FAILED);
34066a573d82SSukumar Swaminathan 		}
34076a573d82SSukumar Swaminathan 	}
34086a573d82SSukumar Swaminathan 
34096a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
34106a573d82SSukumar Swaminathan 	    "Updating wakeup parameters.");
34116a573d82SSukumar Swaminathan 
34126a573d82SSukumar Swaminathan 	if (emlxs_update_wakeup_parms(hba, &RelWakeUpParms,
34136a573d82SSukumar Swaminathan 	    &RelWakeUpParms)) {
34146a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
34156a573d82SSukumar Swaminathan 		    "Unable to update parameters.");
34166a573d82SSukumar Swaminathan 
34176a573d82SSukumar Swaminathan 		return (EMLXS_IMAGE_FAILED);
34186a573d82SSukumar Swaminathan 	}
34196a573d82SSukumar Swaminathan 
3420a9800bebSGarrett D'Amore 	/* Cleanup using old wakeup paramters */
3421a9800bebSGarrett D'Amore 	(void) emlxs_clean_flash(hba, &WakeUpParms, &RelWakeUpParms);
3422a9800bebSGarrett D'Amore 
34236a573d82SSukumar Swaminathan 	return (0);
34246a573d82SSukumar Swaminathan 
34256a573d82SSukumar Swaminathan } /* emlxs_proc_rel_2mb() */
34266a573d82SSukumar Swaminathan 
34276a573d82SSukumar Swaminathan 
34286a573d82SSukumar Swaminathan #define	FLASH_POLLING_BIT	0x80
34296a573d82SSukumar Swaminathan #define	FLASH_ERROR_BIT		0x20
34306a573d82SSukumar Swaminathan 
34316a573d82SSukumar Swaminathan typedef struct _flash_t
34326a573d82SSukumar Swaminathan {
34336a573d82SSukumar Swaminathan 	uint32_t	offset;
34346a573d82SSukumar Swaminathan 	uint8_t		val;
34356a573d82SSukumar Swaminathan } flash_t;
34366a573d82SSukumar Swaminathan 
34376a573d82SSukumar Swaminathan 
3438fcf3ce44SJohn Forte 
3439fcf3ce44SJohn Forte static uint32_t
emlxs_write_fcode_flash(emlxs_hba_t * hba,PIMAGE_HDR ImageHdr,caddr_t Buffer)3440291a2b48SSukumar Swaminathan emlxs_write_fcode_flash(emlxs_hba_t *hba,
3441291a2b48SSukumar Swaminathan     PIMAGE_HDR ImageHdr, caddr_t Buffer)
3442fcf3ce44SJohn Forte {
3443fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3444fcf3ce44SJohn Forte 	uint8_t bb;
3445fcf3ce44SJohn Forte 	uint8_t cc;
3446fcf3ce44SJohn Forte 	uint8_t *src;
3447fcf3ce44SJohn Forte 	uint32_t DlByteCount = ImageHdr->BlockSize;
3448fcf3ce44SJohn Forte 	uint32_t i;
3449fcf3ce44SJohn Forte 	uint32_t j;
3450fcf3ce44SJohn Forte 	uint32_t k;
3451fcf3ce44SJohn Forte 
3452291a2b48SSukumar Swaminathan 	flash_t wr[3] = {
3453fcf3ce44SJohn Forte 		{0x555, 0xaa},
3454fcf3ce44SJohn Forte 		{0x2aa, 0x55},
3455fcf3ce44SJohn Forte 		{0x555, 0xa0}
3456fcf3ce44SJohn Forte 	};
3457fcf3ce44SJohn Forte 
3458fcf3ce44SJohn Forte 	/* Load Fcode */
3459fcf3ce44SJohn Forte 	src = (uint8_t *)Buffer + sizeof (IMAGE_HDR);
3460fcf3ce44SJohn Forte 	for (i = 0; i < DlByteCount; i++) {
3461fcf3ce44SJohn Forte 		for (k = 0; k < 3; k++) {
3462fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
3463fcf3ce44SJohn Forte 		}
3464fcf3ce44SJohn Forte 
3465fcf3ce44SJohn Forte 		/* Reverse Endian word alignment */
3466fcf3ce44SJohn Forte 		j = (i & 3) ^ 3;
3467fcf3ce44SJohn Forte 
3468fcf3ce44SJohn Forte 		bb = src[j];
3469fcf3ce44SJohn Forte 
3470fcf3ce44SJohn Forte 		if (j == 0) {
3471fcf3ce44SJohn Forte 			src += 4;
3472fcf3ce44SJohn Forte 		}
3473291a2b48SSukumar Swaminathan 
3474fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
3475fcf3ce44SJohn Forte 
3476fcf3ce44SJohn Forte 		/* check for complete */
3477fcf3ce44SJohn Forte 		for (;;) {
3478*8f23e9faSHans Rosenfeld 			BUSYWAIT_US(20);
3479fcf3ce44SJohn Forte 
3480fcf3ce44SJohn Forte 			cc = SBUS_READ_FLASH_COPY(hba, i);
3481fcf3ce44SJohn Forte 
3482fcf3ce44SJohn Forte 			/* If data matches then continue */
3483fcf3ce44SJohn Forte 			if (cc == bb) {
3484fcf3ce44SJohn Forte 				break;
3485fcf3ce44SJohn Forte 			}
3486291a2b48SSukumar Swaminathan 
3487291a2b48SSukumar Swaminathan 			/* Polling bit will be inverse final value */
3488291a2b48SSukumar Swaminathan 			/* while active */
3489fcf3ce44SJohn Forte 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
3490fcf3ce44SJohn Forte 				/* Still busy */
3491fcf3ce44SJohn Forte 
3492fcf3ce44SJohn Forte 				/* Check for error bit */
3493fcf3ce44SJohn Forte 				if (cc & FLASH_ERROR_BIT) {
3494fcf3ce44SJohn Forte 					/* Read data one more time */
3495fcf3ce44SJohn Forte 					cc = SBUS_READ_FLASH_COPY(hba, i);
3496fcf3ce44SJohn Forte 
3497fcf3ce44SJohn Forte 					/* Check if data matches */
3498fcf3ce44SJohn Forte 					if (cc == bb) {
3499fcf3ce44SJohn Forte 						break;
3500fcf3ce44SJohn Forte 					}
3501291a2b48SSukumar Swaminathan 
3502fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
3503fcf3ce44SJohn Forte 					    &emlxs_download_failed_msg,
3504fcf3ce44SJohn Forte 					    "FCode write error: offset:%x "
3505291a2b48SSukumar Swaminathan 					    "wrote:%x read:%x\n", i, bb, cc);
3506fcf3ce44SJohn Forte 
3507fcf3ce44SJohn Forte 					return (1);
3508fcf3ce44SJohn Forte 				}
3509fcf3ce44SJohn Forte 			}
3510fcf3ce44SJohn Forte 		}
3511fcf3ce44SJohn Forte 	}
3512fcf3ce44SJohn Forte 
3513fcf3ce44SJohn Forte 	/* Load Header */
3514fcf3ce44SJohn Forte 	src = (uint8_t *)ImageHdr;
3515fcf3ce44SJohn Forte 
3516fcf3ce44SJohn Forte 	for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) {
3517fcf3ce44SJohn Forte 		for (k = 0; k < 3; k++) {
3518fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
3519fcf3ce44SJohn Forte 		}
3520fcf3ce44SJohn Forte 
3521fcf3ce44SJohn Forte 		/* Reverse Endian word alignment */
3522fcf3ce44SJohn Forte 		j = (i & 3) ^ 3;
3523fcf3ce44SJohn Forte 
3524fcf3ce44SJohn Forte 		bb = src[j];
3525fcf3ce44SJohn Forte 
3526fcf3ce44SJohn Forte 		if (j == 0) {
3527fcf3ce44SJohn Forte 			src += 4;
3528fcf3ce44SJohn Forte 		}
3529291a2b48SSukumar Swaminathan 
3530fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
3531fcf3ce44SJohn Forte 
3532fcf3ce44SJohn Forte 		/* check for complete */
3533fcf3ce44SJohn Forte 		for (;;) {
3534*8f23e9faSHans Rosenfeld 			BUSYWAIT_US(20);
3535fcf3ce44SJohn Forte 
3536fcf3ce44SJohn Forte 			cc = SBUS_READ_FLASH_COPY(hba, i);
3537fcf3ce44SJohn Forte 
3538fcf3ce44SJohn Forte 			/* If data matches then continue */
3539fcf3ce44SJohn Forte 			if (cc == bb) {
3540fcf3ce44SJohn Forte 				break;
3541fcf3ce44SJohn Forte 			}
3542291a2b48SSukumar Swaminathan 
3543291a2b48SSukumar Swaminathan 			/* Polling bit will be inverse final value */
3544291a2b48SSukumar Swaminathan 			/* while active */
3545fcf3ce44SJohn Forte 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
3546fcf3ce44SJohn Forte 				/* Still busy */
3547fcf3ce44SJohn Forte 
3548fcf3ce44SJohn Forte 				/* Check for error bit */
3549fcf3ce44SJohn Forte 				if (cc & FLASH_ERROR_BIT) {
3550fcf3ce44SJohn Forte 					/* Read data one more time */
3551fcf3ce44SJohn Forte 					cc = SBUS_READ_FLASH_COPY(hba, i);
3552fcf3ce44SJohn Forte 
3553fcf3ce44SJohn Forte 					/* Check if data matches */
3554fcf3ce44SJohn Forte 					if (cc == bb) {
3555fcf3ce44SJohn Forte 						break;
3556fcf3ce44SJohn Forte 					}
3557291a2b48SSukumar Swaminathan 
3558fcf3ce44SJohn Forte 					EMLXS_MSGF(EMLXS_CONTEXT,
3559fcf3ce44SJohn Forte 					    &emlxs_download_failed_msg,
3560fcf3ce44SJohn Forte 					    "FCode write error: offset:%x "
3561291a2b48SSukumar Swaminathan 					    "wrote:%x read:%x\n", i, bb, cc);
3562fcf3ce44SJohn Forte 
3563fcf3ce44SJohn Forte 					return (1);
3564fcf3ce44SJohn Forte 				}
3565fcf3ce44SJohn Forte 			}
3566fcf3ce44SJohn Forte 		}
3567fcf3ce44SJohn Forte 	}
3568fcf3ce44SJohn Forte 
35694baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
357082527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
35714baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
35724baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
35734baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
35744baa2c25SSukumar Swaminathan 		return (1);
35754baa2c25SSukumar Swaminathan 	}
35764baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
3577291a2b48SSukumar Swaminathan 
3578fcf3ce44SJohn Forte 	return (0);
3579fcf3ce44SJohn Forte 
358082527734SSukumar Swaminathan } /* emlxs_write_fcode_flash() */
3581fcf3ce44SJohn Forte 
3582fcf3ce44SJohn Forte 
3583fcf3ce44SJohn Forte 
3584fcf3ce44SJohn Forte static uint32_t
emlxs_erase_fcode_flash(emlxs_hba_t * hba)3585fcf3ce44SJohn Forte emlxs_erase_fcode_flash(emlxs_hba_t *hba)
3586fcf3ce44SJohn Forte {
3587fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3588fcf3ce44SJohn Forte 	int32_t i, j;
3589fcf3ce44SJohn Forte 	uint8_t cc;
3590fcf3ce44SJohn Forte 	uint32_t offset;
3591fcf3ce44SJohn Forte 
3592291a2b48SSukumar Swaminathan 	flash_t ef[6] = {
3593fcf3ce44SJohn Forte 		{0x555, 0xaa},
3594fcf3ce44SJohn Forte 		{0x2aa, 0x55},
3595fcf3ce44SJohn Forte 		{0x555, 0x80},
3596fcf3ce44SJohn Forte 		{0x555, 0xaa},
3597fcf3ce44SJohn Forte 		{0x2aa, 0x55},
3598fcf3ce44SJohn Forte 		{0x555, 0x10}
3599fcf3ce44SJohn Forte 	};
3600fcf3ce44SJohn Forte 
3601fcf3ce44SJohn Forte 	/* Auto select */
3602291a2b48SSukumar Swaminathan 	flash_t as[3] = {
3603fcf3ce44SJohn Forte 		{0x555, 0xaa},
3604fcf3ce44SJohn Forte 		{0x2aa, 0x55},
3605fcf3ce44SJohn Forte 		{0x555, 0x90}
3606fcf3ce44SJohn Forte 	};
3607fcf3ce44SJohn Forte 
3608fcf3ce44SJohn Forte 
3609fcf3ce44SJohn Forte 	/* Check Manufacturers Code */
3610fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++) {
3611fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3612fcf3ce44SJohn Forte 	}
3613fcf3ce44SJohn Forte 
3614fcf3ce44SJohn Forte 	cc = SBUS_READ_FLASH_COPY(hba, 0);
3615fcf3ce44SJohn Forte 
3616fcf3ce44SJohn Forte 	/* Check Device Code */
3617fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++) {
3618fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3619fcf3ce44SJohn Forte 	}
3620fcf3ce44SJohn Forte 
3621fcf3ce44SJohn Forte 	cc = SBUS_READ_FLASH_COPY(hba, 1);
3622fcf3ce44SJohn Forte 
3623fcf3ce44SJohn Forte 
3624fcf3ce44SJohn Forte 	/* Check block protections (up to 4 16K blocks = 64K) */
3625fcf3ce44SJohn Forte 	for (j = 0; j < 4; j++) {
3626fcf3ce44SJohn Forte 		for (i = 0; i < 3; i++) {
3627fcf3ce44SJohn Forte 			SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3628fcf3ce44SJohn Forte 		}
3629fcf3ce44SJohn Forte 
3630fcf3ce44SJohn Forte 		offset = (j << 14) | 0x2;
3631fcf3ce44SJohn Forte 
3632fcf3ce44SJohn Forte 		cc = SBUS_READ_FLASH_COPY(hba, offset);
3633fcf3ce44SJohn Forte 
3634fcf3ce44SJohn Forte 		if (cc == 0x01) {
3635fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3636fcf3ce44SJohn Forte 			    "Block %d is protected and can't be erased.", j);
3637fcf3ce44SJohn Forte 		}
3638fcf3ce44SJohn Forte 	}
3639fcf3ce44SJohn Forte 
3640fcf3ce44SJohn Forte 	/* Write erase flash sequence */
3641fcf3ce44SJohn Forte 	for (i = 0; i < 6; i++) {
3642fcf3ce44SJohn Forte 		SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val);
3643fcf3ce44SJohn Forte 	}
3644fcf3ce44SJohn Forte 
3645fcf3ce44SJohn Forte 	/* check for complete */
3646fcf3ce44SJohn Forte 	for (;;) {
3647fcf3ce44SJohn Forte 		/* Delay 3 seconds */
3648*8f23e9faSHans Rosenfeld 		BUSYWAIT_MS(3000);
3649fcf3ce44SJohn Forte 
3650fcf3ce44SJohn Forte 		cc = SBUS_READ_FLASH_COPY(hba, 0);
3651fcf3ce44SJohn Forte 
3652fcf3ce44SJohn Forte 
3653fcf3ce44SJohn Forte 		/* If data matches then continue; */
3654fcf3ce44SJohn Forte 		if (cc == 0xff) {
3655fcf3ce44SJohn Forte 			break;
3656fcf3ce44SJohn Forte 		}
3657291a2b48SSukumar Swaminathan 
3658fcf3ce44SJohn Forte 		/* Polling bit will be inverse final value while active */
3659fcf3ce44SJohn Forte 		if ((cc ^ 0xff) & FLASH_POLLING_BIT) {
3660fcf3ce44SJohn Forte 			/* Still busy */
3661fcf3ce44SJohn Forte 
3662fcf3ce44SJohn Forte 			/* Check for error bit */
3663fcf3ce44SJohn Forte 			if (cc & FLASH_ERROR_BIT) {
3664fcf3ce44SJohn Forte 				/* Read data one more time */
3665fcf3ce44SJohn Forte 				cc = SBUS_READ_FLASH_COPY(hba, 0);
3666fcf3ce44SJohn Forte 
3667fcf3ce44SJohn Forte 				/* Check if data matches */
3668fcf3ce44SJohn Forte 				if (cc == 0xff) {
3669fcf3ce44SJohn Forte 					break;
3670fcf3ce44SJohn Forte 				}
3671291a2b48SSukumar Swaminathan 
3672fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
3673fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
3674291a2b48SSukumar Swaminathan 				    "FCode write error: offset:%x wrote:%x "
3675291a2b48SSukumar Swaminathan 				    "read:%x\n", i, 0xff, cc);
3676fcf3ce44SJohn Forte 
3677fcf3ce44SJohn Forte 				return (1);
3678fcf3ce44SJohn Forte 			}
3679fcf3ce44SJohn Forte 		}
3680fcf3ce44SJohn Forte 	}
3681fcf3ce44SJohn Forte 
36824baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
368382527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
36844baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
36854baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
36864baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
36874baa2c25SSukumar Swaminathan 		return (1);
36884baa2c25SSukumar Swaminathan 	}
36894baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
36904baa2c25SSukumar Swaminathan 
3691fcf3ce44SJohn Forte 	return (0);
3692fcf3ce44SJohn Forte 
369382527734SSukumar Swaminathan } /* emlxs_erase_fcode_flash() */
3694fcf3ce44SJohn Forte 
3695fcf3ce44SJohn Forte 
36966a573d82SSukumar Swaminathan static uint32_t
emlxs_delete_load_entry(emlxs_hba_t * hba,PROG_ID * progId)36976a573d82SSukumar Swaminathan emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId)
36986a573d82SSukumar Swaminathan {
36996a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
37006a573d82SSukumar Swaminathan 	MAILBOXQ *mbox = NULL;
37016a573d82SSukumar Swaminathan 	MAILBOX *mb;
37026a573d82SSukumar Swaminathan 	uint32_t rval = 0;
37036a573d82SSukumar Swaminathan 
37046a573d82SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
37056a573d82SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
37066a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
37076a573d82SSukumar Swaminathan 		    "Unable to allocate mailbox buffer.");
37086a573d82SSukumar Swaminathan 
37096a573d82SSukumar Swaminathan 		return (1);
37106a573d82SSukumar Swaminathan 	}
37116a573d82SSukumar Swaminathan 
37126a573d82SSukumar Swaminathan 	mb = (MAILBOX *)mbox;
37136a573d82SSukumar Swaminathan 	mb->mbxCommand = MBX_DEL_LD_ENTRY;
37146a573d82SSukumar Swaminathan 	mb->un.varDelLdEntry.list_req = FLASH_LOAD_LIST;
37156a573d82SSukumar Swaminathan 	mb->un.varDelLdEntry.prog_id = *progId;
37166a573d82SSukumar Swaminathan 
37176a573d82SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
37186a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
37196a573d82SSukumar Swaminathan 		    "Unable to delete load entry: Mailbox cmd=%x status=%x",
37206a573d82SSukumar Swaminathan 		    mb->mbxCommand, mb->mbxStatus);
37216a573d82SSukumar Swaminathan 
37226a573d82SSukumar Swaminathan 		rval = 1;
37236a573d82SSukumar Swaminathan 	}
37246a573d82SSukumar Swaminathan 
37256a573d82SSukumar Swaminathan done:
37266a573d82SSukumar Swaminathan 
37276a573d82SSukumar Swaminathan 	if (mbox) {
37286a573d82SSukumar Swaminathan 		kmem_free(mbox, sizeof (MAILBOXQ));
37296a573d82SSukumar Swaminathan 	}
37306a573d82SSukumar Swaminathan 
37316a573d82SSukumar Swaminathan 	return (rval);
37326a573d82SSukumar Swaminathan 
37336a573d82SSukumar Swaminathan } /* emlxs_delete_load_entry() */
37346a573d82SSukumar Swaminathan 
37356a573d82SSukumar Swaminathan 
3736fcf3ce44SJohn Forte extern uint32_t
emlxs_get_load_list(emlxs_hba_t * hba,PROG_ID * load_list)3737fcf3ce44SJohn Forte emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
3738fcf3ce44SJohn Forte {
3739fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3740fcf3ce44SJohn Forte 	LOAD_ENTRY *LoadEntry;
3741fcf3ce44SJohn Forte 	LOAD_LIST *LoadList = NULL;
3742fcf3ce44SJohn Forte 	uint32_t i;
37436a573d82SSukumar Swaminathan 	uint32_t count = 0;
3744fcf3ce44SJohn Forte 
3745fcf3ce44SJohn Forte 	bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
3746fcf3ce44SJohn Forte 
3747291a2b48SSukumar Swaminathan 	if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST),
3748291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3749fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3750fcf3ce44SJohn Forte 		    "Unable to allocate LOADLIST buffer.");
3751fcf3ce44SJohn Forte 
3752fcf3ce44SJohn Forte 		goto done;
3753fcf3ce44SJohn Forte 	}
3754291a2b48SSukumar Swaminathan 
3755fcf3ce44SJohn Forte 	if (emlxs_read_load_list(hba, LoadList)) {
3756fcf3ce44SJohn Forte 		goto done;
3757fcf3ce44SJohn Forte 	}
3758291a2b48SSukumar Swaminathan 
3759fcf3ce44SJohn Forte 	for (i = 0; i < LoadList->entry_cnt; i++) {
3760fcf3ce44SJohn Forte 		LoadEntry = &LoadList->load_entry[i];
3761fcf3ce44SJohn Forte 		if ((LoadEntry->un.wd[0] != 0) &&
3762fcf3ce44SJohn Forte 		    (LoadEntry->un.wd[0] != 0xffffffff)) {
3763fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
37646a573d82SSukumar Swaminathan 			    "Load List[%d]: %08x %08x", count,
3765291a2b48SSukumar Swaminathan 			    LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
37666a573d82SSukumar Swaminathan 
37676a573d82SSukumar Swaminathan 			load_list[count++] = LoadEntry->un.id;
3768fcf3ce44SJohn Forte 		}
3769fcf3ce44SJohn Forte 	}
3770fcf3ce44SJohn Forte 
3771fcf3ce44SJohn Forte done:
3772fcf3ce44SJohn Forte 
3773fcf3ce44SJohn Forte 	if (LoadList) {
3774fcf3ce44SJohn Forte 		kmem_free(LoadList, sizeof (LOAD_LIST));
3775fcf3ce44SJohn Forte 	}
3776291a2b48SSukumar Swaminathan 
37776a573d82SSukumar Swaminathan 	return (count);
3778fcf3ce44SJohn Forte 
377982527734SSukumar Swaminathan } /* emlxs_get_load_list() */
3780fcf3ce44SJohn Forte 
3781fcf3ce44SJohn Forte 
3782fcf3ce44SJohn Forte extern uint32_t
emlxs_read_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,uint32_t verbose)3783fcf3ce44SJohn Forte emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
3784fcf3ce44SJohn Forte     uint32_t verbose)
3785fcf3ce44SJohn Forte {
3786fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3787fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
3788fcf3ce44SJohn Forte 	MAILBOX *mb;
3789fcf3ce44SJohn Forte 	uint32_t rval = 0;
3790fcf3ce44SJohn Forte 	uint32_t *wd;
3791fcf3ce44SJohn Forte 
3792fcf3ce44SJohn Forte 	bzero(WakeUpParms, sizeof (WAKE_UP_PARMS));
3793fcf3ce44SJohn Forte 
3794291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3795291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3796fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3797fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3798fcf3ce44SJohn Forte 
3799fcf3ce44SJohn Forte 		return (1);
3800fcf3ce44SJohn Forte 	}
3801291a2b48SSukumar Swaminathan 
3802fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3803fcf3ce44SJohn Forte 
380482527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox,
3805291a2b48SSukumar Swaminathan 	    DMP_NV_PARAMS,
3806291a2b48SSukumar Swaminathan 	    WAKE_UP_PARMS_REGION_ID,
3807fcf3ce44SJohn Forte 	    sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
3808fcf3ce44SJohn Forte 
380982527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3810fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3811fcf3ce44SJohn Forte 		    "Unable to get parameters: Mailbox cmd=%x status=%x",
3812fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
3813fcf3ce44SJohn Forte 
3814fcf3ce44SJohn Forte 		if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) {
3815fcf3ce44SJohn Forte 			rval = (uint32_t)CFG_DATA_NO_REGION;
3816fcf3ce44SJohn Forte 		} else {
3817fcf3ce44SJohn Forte 			rval = 1;
3818fcf3ce44SJohn Forte 		}
3819fcf3ce44SJohn Forte 	} else {
382082527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
382182527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
382282527734SSukumar Swaminathan 			    0, hba->sli.sli4.dump_region.size,
382382527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
382482527734SSukumar Swaminathan 
382582527734SSukumar Swaminathan 			bcopy((caddr_t)hba->sli.sli4.dump_region.virt,
382682527734SSukumar Swaminathan 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
382782527734SSukumar Swaminathan 		} else {
382882527734SSukumar Swaminathan 			bcopy((caddr_t)&mb->un.varDmp.resp_offset,
382982527734SSukumar Swaminathan 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
383082527734SSukumar Swaminathan 		}
3831fcf3ce44SJohn Forte 
3832fcf3ce44SJohn Forte 		if (verbose) {
3833fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->prog_id;
3834fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3835291a2b48SSukumar Swaminathan 			    "Wakeup:      prog_id=%08x %08x", wd[0], wd[1]);
3836fcf3ce44SJohn Forte 
3837fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id;
3838fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3839291a2b48SSukumar Swaminathan 			    "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]);
3840fcf3ce44SJohn Forte 
3841fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli1_prog_id;
3842fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3843291a2b48SSukumar Swaminathan 			    "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]);
3844fcf3ce44SJohn Forte 
3845fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli2_prog_id;
3846fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3847291a2b48SSukumar Swaminathan 			    "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]);
3848fcf3ce44SJohn Forte 
3849fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli3_prog_id;
3850fcf3ce44SJohn Forte 			if (wd[0] || wd[1]) {
3851291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3852291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
3853291a2b48SSukumar Swaminathan 				    "Wakeup: sli3_prog_id=%08x %08x", wd[0],
3854291a2b48SSukumar Swaminathan 				    wd[1]);
3855fcf3ce44SJohn Forte 			}
3856291a2b48SSukumar Swaminathan 
3857fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->sli4_prog_id;
3858fcf3ce44SJohn Forte 			if (wd[0] || wd[1]) {
3859291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
3860291a2b48SSukumar Swaminathan 				    &emlxs_init_debug_msg,
3861291a2b48SSukumar Swaminathan 				    "Wakeup: sli4_prog_id=%08x %08x", wd[0],
3862291a2b48SSukumar Swaminathan 				    wd[1]);
3863fcf3ce44SJohn Forte 			}
3864291a2b48SSukumar Swaminathan 
3865fcf3ce44SJohn Forte 			wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id;
3866fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3867291a2b48SSukumar Swaminathan 			    "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]);
3868fcf3ce44SJohn Forte 
3869fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3870fcf3ce44SJohn Forte 			    "Wakeup: pci_cfg_rsvd=%x",
3871fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_rsvd);
3872fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3873fcf3ce44SJohn Forte 			    "Wakeup:  use_hdw_def=%x",
3874fcf3ce44SJohn Forte 			    WakeUpParms->use_hdw_def);
3875fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3876fcf3ce44SJohn Forte 			    "Wakeup:  pci_cfg_sel=%x",
3877fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_sel);
3878fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3879fcf3ce44SJohn Forte 			    "Wakeup:   cfg_lookup=%x",
3880fcf3ce44SJohn Forte 			    WakeUpParms->pci_cfg_lookup_sel);
3881fcf3ce44SJohn Forte 		}
3882fcf3ce44SJohn Forte 	}
3883fcf3ce44SJohn Forte 
3884fcf3ce44SJohn Forte done:
3885fcf3ce44SJohn Forte 
3886fcf3ce44SJohn Forte 	if (mbox) {
3887fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3888fcf3ce44SJohn Forte 	}
3889291a2b48SSukumar Swaminathan 
3890b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3891b3660a96SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3892b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
3893b3660a96SSukumar Swaminathan 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3894b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
3895b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
3896*8f23e9faSHans Rosenfeld 			    "read_wakeup_parms: hdl=%p",
3897b3660a96SSukumar Swaminathan 			    hba->sli.sli4.dump_region.dma_handle);
3898b3660a96SSukumar Swaminathan 			rval = 1;
3899b3660a96SSukumar Swaminathan 		}
3900b3660a96SSukumar Swaminathan 	}
3901b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
3902b3660a96SSukumar Swaminathan 
3903fcf3ce44SJohn Forte 	return (rval);
3904fcf3ce44SJohn Forte 
390582527734SSukumar Swaminathan } /* emlxs_read_wakeup_parms() */
3906fcf3ce44SJohn Forte 
3907fcf3ce44SJohn Forte 
3908fcf3ce44SJohn Forte static uint32_t
emlxs_read_load_list(emlxs_hba_t * hba,LOAD_LIST * LoadList)3909291a2b48SSukumar Swaminathan emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
3910fcf3ce44SJohn Forte {
3911fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
3912fcf3ce44SJohn Forte 	LOAD_ENTRY *LoadEntry;
3913fcf3ce44SJohn Forte 	uint32_t *Uptr;
3914fcf3ce44SJohn Forte 	uint32_t CurEntryAddr;
3915fcf3ce44SJohn Forte 	MAILBOXQ *mbox = NULL;
3916fcf3ce44SJohn Forte 	MAILBOX *mb;
3917fcf3ce44SJohn Forte 
3918fcf3ce44SJohn Forte 	bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
3919fcf3ce44SJohn Forte 
3920291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3921291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
3922fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3923fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
3924fcf3ce44SJohn Forte 
3925fcf3ce44SJohn Forte 		return (1);
3926fcf3ce44SJohn Forte 	}
3927291a2b48SSukumar Swaminathan 
3928fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
3929fcf3ce44SJohn Forte 
393082527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
3931fcf3ce44SJohn Forte 
393282527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3933fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3934fcf3ce44SJohn Forte 		    "Unable to get load list: Mailbox cmd=%x status=%x",
3935fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
3936fcf3ce44SJohn Forte 
3937fcf3ce44SJohn Forte 		goto done;
3938fcf3ce44SJohn Forte 	}
3939291a2b48SSukumar Swaminathan 
394082527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
394182527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
394282527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
394382527734SSukumar Swaminathan 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
394482527734SSukumar Swaminathan 	} else {
394582527734SSukumar Swaminathan 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
394682527734SSukumar Swaminathan 	}
3947fcf3ce44SJohn Forte 
3948fcf3ce44SJohn Forte 	LoadList->head = Uptr[0];
3949fcf3ce44SJohn Forte 	LoadList->tail = Uptr[1];
3950fcf3ce44SJohn Forte 
3951fcf3ce44SJohn Forte 	CurEntryAddr = LoadList->head;
3952fcf3ce44SJohn Forte 
3953fcf3ce44SJohn Forte 	while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
3954fcf3ce44SJohn Forte 	    (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
3955fcf3ce44SJohn Forte 		LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
3956fcf3ce44SJohn Forte 		LoadList->entry_cnt++;
3957fcf3ce44SJohn Forte 
395882527734SSukumar Swaminathan 		emlxs_format_dump(hba, mbox,
3959291a2b48SSukumar Swaminathan 		    DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
3960fcf3ce44SJohn Forte 
396182527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3962291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
3963fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3964291a2b48SSukumar Swaminathan 			    "Unable to get load list (%d): Mailbox cmd=%x "
3965291a2b48SSukumar Swaminathan 			    "status=%x", LoadList->entry_cnt, mb->mbxCommand,
3966291a2b48SSukumar Swaminathan 			    mb->mbxStatus);
3967fcf3ce44SJohn Forte 
3968fcf3ce44SJohn Forte 			goto done;
3969fcf3ce44SJohn Forte 		}
3970291a2b48SSukumar Swaminathan 
397182527734SSukumar Swaminathan 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
397282527734SSukumar Swaminathan 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
397382527734SSukumar Swaminathan 			    0, hba->sli.sli4.dump_region.size,
397482527734SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
397582527734SSukumar Swaminathan 			Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
397682527734SSukumar Swaminathan 		} else {
397782527734SSukumar Swaminathan 			Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
397882527734SSukumar Swaminathan 		}
3979fcf3ce44SJohn Forte 
3980fcf3ce44SJohn Forte 		LoadEntry->next = Uptr[0];
3981fcf3ce44SJohn Forte 		LoadEntry->prev = Uptr[1];
3982fcf3ce44SJohn Forte 		LoadEntry->start_adr = Uptr[2];
3983fcf3ce44SJohn Forte 		LoadEntry->len = Uptr[3];
3984fcf3ce44SJohn Forte 		LoadEntry->un.wd[0] = Uptr[4];
3985fcf3ce44SJohn Forte 		LoadEntry->un.wd[1] = Uptr[5];
3986fcf3ce44SJohn Forte 
3987fcf3ce44SJohn Forte 		/* update next current load entry address */
3988fcf3ce44SJohn Forte 		CurEntryAddr = LoadEntry->next;
3989fcf3ce44SJohn Forte 
3990fcf3ce44SJohn Forte 	}	/* end of while (not end of list) */
3991fcf3ce44SJohn Forte 
3992fcf3ce44SJohn Forte done:
3993fcf3ce44SJohn Forte 
3994fcf3ce44SJohn Forte 	if (mbox) {
3995fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
3996fcf3ce44SJohn Forte 	}
3997291a2b48SSukumar Swaminathan 
3998b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
3999b3660a96SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4000b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
4001b3660a96SSukumar Swaminathan 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
4002b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
4003b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
4004*8f23e9faSHans Rosenfeld 			    "read_load_list: hdl=%p",
4005b3660a96SSukumar Swaminathan 			    hba->sli.sli4.dump_region.dma_handle);
4006b3660a96SSukumar Swaminathan 			return (1);
4007b3660a96SSukumar Swaminathan 		}
4008b3660a96SSukumar Swaminathan 	}
4009b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
4010b3660a96SSukumar Swaminathan 
4011fcf3ce44SJohn Forte 	return (0);
4012fcf3ce44SJohn Forte 
401382527734SSukumar Swaminathan } /* emlxs_read_load_list() */
4014fcf3ce44SJohn Forte 
4015fcf3ce44SJohn Forte 
4016*8f23e9faSHans Rosenfeld extern uint32_t
emlxs_get_boot_config(emlxs_hba_t * hba,uint8_t * boot_state)4017*8f23e9faSHans Rosenfeld emlxs_get_boot_config(emlxs_hba_t *hba, uint8_t *boot_state)
4018*8f23e9faSHans Rosenfeld {
4019*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
4020*8f23e9faSHans Rosenfeld 	MAILBOXQ *mbq;
4021*8f23e9faSHans Rosenfeld 	MAILBOX4 *mb;
4022*8f23e9faSHans Rosenfeld 	mbox_req_hdr_t	*hdr_req;
4023*8f23e9faSHans Rosenfeld 	IOCTL_COMMON_BOOT_CFG *boot_cfg;
4024*8f23e9faSHans Rosenfeld 
4025*8f23e9faSHans Rosenfeld 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4026*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4027*8f23e9faSHans Rosenfeld 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
4028*8f23e9faSHans Rosenfeld 
4029*8f23e9faSHans Rosenfeld 		return (1);
4030*8f23e9faSHans Rosenfeld 	}
4031*8f23e9faSHans Rosenfeld 
4032*8f23e9faSHans Rosenfeld 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4033*8f23e9faSHans Rosenfeld 	    KM_NOSLEEP)) == NULL) {
4034*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4035*8f23e9faSHans Rosenfeld 		    "Unable to allocate mailbox buffer.");
4036*8f23e9faSHans Rosenfeld 
4037*8f23e9faSHans Rosenfeld 		return (1);
4038*8f23e9faSHans Rosenfeld 	}
4039*8f23e9faSHans Rosenfeld 
4040*8f23e9faSHans Rosenfeld 	mb = (MAILBOX4 *)mbq;
4041*8f23e9faSHans Rosenfeld 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
4042*8f23e9faSHans Rosenfeld 
4043*8f23e9faSHans Rosenfeld 	mb->un.varSLIConfig.be.embedded = 1;
4044*8f23e9faSHans Rosenfeld 	mbq->nonembed = NULL;
4045*8f23e9faSHans Rosenfeld 	mbq->mbox_cmpl = NULL;
4046*8f23e9faSHans Rosenfeld 
4047*8f23e9faSHans Rosenfeld 	mb->mbxCommand = MBX_SLI_CONFIG;
4048*8f23e9faSHans Rosenfeld 	mb->mbxOwner = OWN_HOST;
4049*8f23e9faSHans Rosenfeld 
4050*8f23e9faSHans Rosenfeld 	hdr_req = (mbox_req_hdr_t *)
4051*8f23e9faSHans Rosenfeld 	    &mb->un.varSLIConfig.be.un_hdr.hdr_req;
4052*8f23e9faSHans Rosenfeld 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
4053*8f23e9faSHans Rosenfeld 	hdr_req->opcode = COMMON_OPCODE_GET_BOOT_CFG;
4054*8f23e9faSHans Rosenfeld 
4055*8f23e9faSHans Rosenfeld 	boot_cfg = (IOCTL_COMMON_BOOT_CFG *)(hdr_req + 1);
4056*8f23e9faSHans Rosenfeld 
4057*8f23e9faSHans Rosenfeld 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
4058*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4059*8f23e9faSHans Rosenfeld 		    "Unable to read boot config: Mailbox cmd=%x "
4060*8f23e9faSHans Rosenfeld 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
4061*8f23e9faSHans Rosenfeld 
4062*8f23e9faSHans Rosenfeld 		kmem_free(mbq, sizeof (MAILBOXQ));
4063*8f23e9faSHans Rosenfeld 		return (1);
4064*8f23e9faSHans Rosenfeld 	}
4065*8f23e9faSHans Rosenfeld 
4066*8f23e9faSHans Rosenfeld 	*boot_state = boot_cfg->params.response.boot_status;
4067*8f23e9faSHans Rosenfeld 
4068*8f23e9faSHans Rosenfeld 	kmem_free(mbq, sizeof (MAILBOXQ));
4069*8f23e9faSHans Rosenfeld 	return (0);
4070*8f23e9faSHans Rosenfeld }
4071*8f23e9faSHans Rosenfeld 
4072*8f23e9faSHans Rosenfeld 
4073*8f23e9faSHans Rosenfeld extern uint32_t
emlxs_set_boot_config(emlxs_hba_t * hba,uint8_t boot_state)4074*8f23e9faSHans Rosenfeld emlxs_set_boot_config(emlxs_hba_t *hba, uint8_t boot_state)
4075*8f23e9faSHans Rosenfeld {
4076*8f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
4077*8f23e9faSHans Rosenfeld 	MAILBOXQ *mbq;
4078*8f23e9faSHans Rosenfeld 	MAILBOX4 *mb;
4079*8f23e9faSHans Rosenfeld 	mbox_req_hdr_t	*hdr_req;
4080*8f23e9faSHans Rosenfeld 	IOCTL_COMMON_BOOT_CFG *boot_cfg;
4081*8f23e9faSHans Rosenfeld 
4082*8f23e9faSHans Rosenfeld 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4083*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4084*8f23e9faSHans Rosenfeld 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
4085*8f23e9faSHans Rosenfeld 
4086*8f23e9faSHans Rosenfeld 		return (1);
4087*8f23e9faSHans Rosenfeld 	}
4088*8f23e9faSHans Rosenfeld 
4089*8f23e9faSHans Rosenfeld 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4090*8f23e9faSHans Rosenfeld 	    KM_NOSLEEP)) == NULL) {
4091*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4092*8f23e9faSHans Rosenfeld 		    "Unable to allocate mailbox buffer.");
4093*8f23e9faSHans Rosenfeld 
4094*8f23e9faSHans Rosenfeld 		return (1);
4095*8f23e9faSHans Rosenfeld 	}
4096*8f23e9faSHans Rosenfeld 
4097*8f23e9faSHans Rosenfeld 	mb = (MAILBOX4 *)mbq;
4098*8f23e9faSHans Rosenfeld 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
4099*8f23e9faSHans Rosenfeld 
4100*8f23e9faSHans Rosenfeld 	mb->un.varSLIConfig.be.embedded = 1;
4101*8f23e9faSHans Rosenfeld 	mbq->nonembed = NULL;
4102*8f23e9faSHans Rosenfeld 	mbq->mbox_cmpl = NULL;
4103*8f23e9faSHans Rosenfeld 
4104*8f23e9faSHans Rosenfeld 	mb->mbxCommand = MBX_SLI_CONFIG;
4105*8f23e9faSHans Rosenfeld 	mb->mbxOwner = OWN_HOST;
4106*8f23e9faSHans Rosenfeld 
4107*8f23e9faSHans Rosenfeld 	hdr_req = (mbox_req_hdr_t *)
4108*8f23e9faSHans Rosenfeld 	    &mb->un.varSLIConfig.be.un_hdr.hdr_req;
4109*8f23e9faSHans Rosenfeld 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
4110*8f23e9faSHans Rosenfeld 	hdr_req->opcode = COMMON_OPCODE_SET_BOOT_CFG;
4111*8f23e9faSHans Rosenfeld 
4112*8f23e9faSHans Rosenfeld 	boot_cfg = (IOCTL_COMMON_BOOT_CFG *)(hdr_req + 1);
4113*8f23e9faSHans Rosenfeld 	boot_cfg->params.request.boot_status = boot_state;
4114*8f23e9faSHans Rosenfeld 
4115*8f23e9faSHans Rosenfeld 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
4116*8f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4117*8f23e9faSHans Rosenfeld 		    "Unable to read boot config: Mailbox cmd=%x "
4118*8f23e9faSHans Rosenfeld 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
4119*8f23e9faSHans Rosenfeld 
4120*8f23e9faSHans Rosenfeld 		kmem_free(mbq, sizeof (MAILBOXQ));
4121*8f23e9faSHans Rosenfeld 		return (1);
4122*8f23e9faSHans Rosenfeld 	}
4123*8f23e9faSHans Rosenfeld 
4124*8f23e9faSHans Rosenfeld 	kmem_free(mbq, sizeof (MAILBOXQ));
4125*8f23e9faSHans Rosenfeld 	return (0);
4126*8f23e9faSHans Rosenfeld }
4127*8f23e9faSHans Rosenfeld 
4128*8f23e9faSHans Rosenfeld 
4129fcf3ce44SJohn Forte 
4130a9800bebSGarrett D'Amore 
4131fcf3ce44SJohn Forte static int
emlxs_build_parms(caddr_t Buffer,PWAKE_UP_PARMS AbsWakeUpParms,uint32_t BufferSize,PAIF_HDR AifHeader)4132291a2b48SSukumar Swaminathan emlxs_build_parms(caddr_t Buffer,
4133291a2b48SSukumar Swaminathan     PWAKE_UP_PARMS AbsWakeUpParms,
41346a573d82SSukumar Swaminathan     uint32_t BufferSize, PAIF_HDR AifHeader)
4135fcf3ce44SJohn Forte {
4136fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
4137fcf3ce44SJohn Forte 	uint32_t NextImage;
4138fcf3ce44SJohn Forte 	uint32_t i;
4139fcf3ce44SJohn Forte 	int32_t ChangeParams = FALSE;
4140fcf3ce44SJohn Forte 	caddr_t Sptr;
4141fcf3ce44SJohn Forte 	caddr_t Dptr;
4142fcf3ce44SJohn Forte 
4143fcf3ce44SJohn Forte 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
4144fcf3ce44SJohn Forte 
41456a573d82SSukumar Swaminathan 	if ((AifHeader->ImageBase != 0x20000) &&
41466a573d82SSukumar Swaminathan 	    ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
4147fcf3ce44SJohn Forte 		return (FALSE);
4148fcf3ce44SJohn Forte 	}
4149291a2b48SSukumar Swaminathan 
4150fcf3ce44SJohn Forte 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
4151fcf3ce44SJohn Forte 
4152fcf3ce44SJohn Forte 	while (BufferSize > NextImage) {
4153fcf3ce44SJohn Forte 		Sptr = &Buffer[NextImage];
4154fcf3ce44SJohn Forte 		Dptr = (caddr_t)&ImageHdr;
4155fcf3ce44SJohn Forte 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
4156fcf3ce44SJohn Forte 			Dptr[i] = Sptr[i];
4157fcf3ce44SJohn Forte 		}
4158fcf3ce44SJohn Forte 
4159fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff)
4160fcf3ce44SJohn Forte 			break;
4161fcf3ce44SJohn Forte 
4162fcf3ce44SJohn Forte 		switch (ImageHdr.Id.Type) {
4163fcf3ce44SJohn Forte 		case TEST_PROGRAM:
4164fcf3ce44SJohn Forte 			break;
4165fcf3ce44SJohn Forte 		case FUNC_FIRMWARE:
4166fcf3ce44SJohn Forte 			AbsWakeUpParms->prog_id = ImageHdr.Id;
4167fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4168fcf3ce44SJohn Forte 			break;
4169fcf3ce44SJohn Forte 		case BOOT_BIOS:
4170fcf3ce44SJohn Forte 			AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
4171fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4172fcf3ce44SJohn Forte 			break;
4173fcf3ce44SJohn Forte 		case SLI1_OVERLAY:
4174fcf3ce44SJohn Forte 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
4175fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4176fcf3ce44SJohn Forte 			break;
4177fcf3ce44SJohn Forte 		case SLI2_OVERLAY:
4178fcf3ce44SJohn Forte 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
4179fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4180fcf3ce44SJohn Forte 			break;
4181fcf3ce44SJohn Forte 		case SLI3_OVERLAY:
4182fcf3ce44SJohn Forte 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
4183fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4184fcf3ce44SJohn Forte 			break;
4185fcf3ce44SJohn Forte 		case SLI4_OVERLAY:
4186fcf3ce44SJohn Forte 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
4187fcf3ce44SJohn Forte 			ChangeParams = TRUE;
4188fcf3ce44SJohn Forte 			break;
4189fcf3ce44SJohn Forte 		default:
4190fcf3ce44SJohn Forte 			break;
4191fcf3ce44SJohn Forte 		}
4192fcf3ce44SJohn Forte 
4193fcf3ce44SJohn Forte 		NextImage += ImageHdr.BlockSize;
4194fcf3ce44SJohn Forte 	}
4195fcf3ce44SJohn Forte 
4196fcf3ce44SJohn Forte 	return (ChangeParams);
4197fcf3ce44SJohn Forte 
419882527734SSukumar Swaminathan } /* emlxs_build_parms() */
4199fcf3ce44SJohn Forte 
4200fcf3ce44SJohn Forte 
4201fcf3ce44SJohn Forte static uint32_t
emlxs_update_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS AbsWakeUpParms,PWAKE_UP_PARMS WakeUpParms)4202fcf3ce44SJohn Forte emlxs_update_wakeup_parms(emlxs_hba_t *hba,
4203fcf3ce44SJohn Forte     PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
4204fcf3ce44SJohn Forte {
4205fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4206fcf3ce44SJohn Forte 	MAILBOX *mb;
4207fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
4208fcf3ce44SJohn Forte 	uint32_t rval = 0;
4209fcf3ce44SJohn Forte 
4210291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4211291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
4212fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4213fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
4214fcf3ce44SJohn Forte 
4215fcf3ce44SJohn Forte 		return (1);
4216fcf3ce44SJohn Forte 	}
4217291a2b48SSukumar Swaminathan 
4218fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
4219fcf3ce44SJohn Forte 
4220fcf3ce44SJohn Forte 	WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
4221fcf3ce44SJohn Forte 	WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
4222fcf3ce44SJohn Forte 	WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
4223fcf3ce44SJohn Forte 	WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
4224fcf3ce44SJohn Forte 	WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
4225fcf3ce44SJohn Forte 	WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
4226fcf3ce44SJohn Forte 
422782527734SSukumar Swaminathan 	emlxs_format_update_parms(mbox, WakeUpParms);
4228fcf3ce44SJohn Forte 
422982527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4230fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4231291a2b48SSukumar Swaminathan 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
4232291a2b48SSukumar Swaminathan 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
4233fcf3ce44SJohn Forte 
4234fcf3ce44SJohn Forte 		rval = 1;
4235fcf3ce44SJohn Forte 	}
4236291a2b48SSukumar Swaminathan 
4237fcf3ce44SJohn Forte 	if (mbox) {
4238fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
4239fcf3ce44SJohn Forte 	}
4240291a2b48SSukumar Swaminathan 
4241fcf3ce44SJohn Forte 	return (rval);
4242fcf3ce44SJohn Forte 
424382527734SSukumar Swaminathan } /* emlxs_update_wakeup_parms() */
4244fcf3ce44SJohn Forte 
4245fcf3ce44SJohn Forte 
4246fcf3ce44SJohn Forte static uint32_t
emlxs_validate_version(emlxs_hba_t * hba,emlxs_fw_file_t * file,uint32_t id,uint32_t type,char * file_type)4247291a2b48SSukumar Swaminathan emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
4248291a2b48SSukumar Swaminathan     uint32_t type, char *file_type)
4249fcf3ce44SJohn Forte {
4250fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4251fcf3ce44SJohn Forte 
4252fcf3ce44SJohn Forte 	/* Create the version label */
4253*8f23e9faSHans Rosenfeld 	emlxs_decode_version(file->version, file->label, sizeof (file->label));
4254fcf3ce44SJohn Forte 
4255fcf3ce44SJohn Forte 	/* Process the DWC type */
4256fcf3ce44SJohn Forte 	switch (type) {
4257fcf3ce44SJohn Forte 	case TEST_PROGRAM:
4258fcf3ce44SJohn Forte 
4259fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4260291a2b48SSukumar Swaminathan 		    "%s: TEST: offset=%08x  version=%08x, %s", file_type,
4261291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4262fcf3ce44SJohn Forte 
4263fcf3ce44SJohn Forte 		break;
4264fcf3ce44SJohn Forte 
4265fcf3ce44SJohn Forte 	case BOOT_BIOS:
4266fcf3ce44SJohn Forte 
4267fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4268291a2b48SSukumar Swaminathan 		    "%s: BOOT: offset=%08x  version=%08x, %s", file_type,
4269291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4270fcf3ce44SJohn Forte 
4271fcf3ce44SJohn Forte 		if (!emlxs_bios_check(hba, id)) {
4272fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4273fcf3ce44SJohn Forte 			    "BOOT Check: Image not compatible with %s. id=%02x",
4274fcf3ce44SJohn Forte 			    hba->model_info.model, id);
4275fcf3ce44SJohn Forte 
4276fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4277fcf3ce44SJohn Forte 		}
4278291a2b48SSukumar Swaminathan 
4279fcf3ce44SJohn Forte 		break;
4280fcf3ce44SJohn Forte 
4281fcf3ce44SJohn Forte 	case FUNC_FIRMWARE:	/* Stub */
4282fcf3ce44SJohn Forte 
4283fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4284291a2b48SSukumar Swaminathan 		    "%s: STUB: offset=%08x  version=%08x, %s", file_type,
4285291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4286fcf3ce44SJohn Forte 
4287fcf3ce44SJohn Forte 		if (!emlxs_stub_check(hba, id)) {
4288fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4289fcf3ce44SJohn Forte 			    "STUB Check: Image not compatible with %s. id=%02x",
4290fcf3ce44SJohn Forte 			    hba->model_info.model, id);
4291fcf3ce44SJohn Forte 
4292fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4293fcf3ce44SJohn Forte 		}
4294291a2b48SSukumar Swaminathan 
4295fcf3ce44SJohn Forte 		break;
4296fcf3ce44SJohn Forte 
4297fcf3ce44SJohn Forte 	case SLI1_OVERLAY:
4298fcf3ce44SJohn Forte 
4299fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4300291a2b48SSukumar Swaminathan 		    "%s: SLI1: offset=%08x  version=%08x, %s", file_type,
4301291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4302fcf3ce44SJohn Forte 
4303fcf3ce44SJohn Forte 		if (!emlxs_sli1_check(hba, id)) {
4304fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4305fcf3ce44SJohn Forte 			    "SLI1 Check: Image not compatible with %s. id=%02x",
4306fcf3ce44SJohn Forte 			    hba->model_info.model, id);
4307fcf3ce44SJohn Forte 
4308fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4309fcf3ce44SJohn Forte 		}
4310291a2b48SSukumar Swaminathan 
4311fcf3ce44SJohn Forte 		break;
4312fcf3ce44SJohn Forte 
4313fcf3ce44SJohn Forte 	case SLI2_OVERLAY:
4314fcf3ce44SJohn Forte 
4315fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4316291a2b48SSukumar Swaminathan 		    "%s: SLI2: offset=%08x  version=%08x, %s", file_type,
4317291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4318fcf3ce44SJohn Forte 
4319fcf3ce44SJohn Forte 		if (!emlxs_sli2_check(hba, id)) {
4320fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4321fcf3ce44SJohn Forte 			    "SLI2 Check: Image not compatible with %s. id=%02x",
4322fcf3ce44SJohn Forte 			    hba->model_info.model, id);
4323fcf3ce44SJohn Forte 
4324fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4325fcf3ce44SJohn Forte 		}
4326291a2b48SSukumar Swaminathan 
4327fcf3ce44SJohn Forte 		break;
4328fcf3ce44SJohn Forte 
4329fcf3ce44SJohn Forte 	case SLI3_OVERLAY:
4330fcf3ce44SJohn Forte 
4331fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4332291a2b48SSukumar Swaminathan 		    "%s: SLI3: offset=%08x  version=%08x, %s", file_type,
4333291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4334fcf3ce44SJohn Forte 
4335fcf3ce44SJohn Forte 		if (!emlxs_sli3_check(hba, id)) {
4336fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4337fcf3ce44SJohn Forte 			    "SLI3 Check: Image not compatible with %s. id=%02x",
4338fcf3ce44SJohn Forte 			    hba->model_info.model, id);
4339fcf3ce44SJohn Forte 
4340fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4341fcf3ce44SJohn Forte 		}
4342291a2b48SSukumar Swaminathan 
4343fcf3ce44SJohn Forte 		break;
4344fcf3ce44SJohn Forte 
4345fcf3ce44SJohn Forte 	case SLI4_OVERLAY:
4346fcf3ce44SJohn Forte 
4347fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4348291a2b48SSukumar Swaminathan 		    "%s: SLI4: offset=%08x  version=%08x, %s", file_type,
4349291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4350fcf3ce44SJohn Forte 
4351fcf3ce44SJohn Forte 		if (!emlxs_sli4_check(hba, id)) {
4352fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4353fcf3ce44SJohn Forte 			    "SLI4 Check: Image not compatible with %s. id=%02x",
4354fcf3ce44SJohn Forte 			    hba->model_info.model, id);
4355fcf3ce44SJohn Forte 
4356fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4357fcf3ce44SJohn Forte 		}
4358291a2b48SSukumar Swaminathan 
4359fcf3ce44SJohn Forte 		break;
4360fcf3ce44SJohn Forte 
4361fcf3ce44SJohn Forte 	case SBUS_FCODE:
4362fcf3ce44SJohn Forte 
4363fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4364fcf3ce44SJohn Forte 		    "%s: SBUS FCODE: offset=%08x  version=%08x, %s",
4365291a2b48SSukumar Swaminathan 		    file_type, file->offset, file->version, file->label);
4366fcf3ce44SJohn Forte 
4367fcf3ce44SJohn Forte 		if (!emlxs_sbus_fcode_check(hba, id)) {
4368fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4369fcf3ce44SJohn Forte 			    "SBUS FCODE Check: Image not compatible with %s. "
4370291a2b48SSukumar Swaminathan 			    "id=%02x", hba->model_info.model, id);
4371fcf3ce44SJohn Forte 
4372fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4373fcf3ce44SJohn Forte 		}
4374291a2b48SSukumar Swaminathan 
4375fcf3ce44SJohn Forte 		break;
4376fcf3ce44SJohn Forte 
4377fcf3ce44SJohn Forte 	case KERNEL_CODE:
4378fcf3ce44SJohn Forte 
4379fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4380291a2b48SSukumar Swaminathan 		    "%s: KERN: offset=%08x  version=%08x, %s", file_type,
4381291a2b48SSukumar Swaminathan 		    file->offset, file->version, file->label);
4382fcf3ce44SJohn Forte 
4383fcf3ce44SJohn Forte 		if (!emlxs_kern_check(hba, id)) {
4384fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4385fcf3ce44SJohn Forte 			    "KERN Check: Image not compatible with %s. id=%02x",
4386fcf3ce44SJohn Forte 			    hba->model_info.model, id);
4387fcf3ce44SJohn Forte 
4388fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_INCOMPATIBLE);
4389fcf3ce44SJohn Forte 		}
4390291a2b48SSukumar Swaminathan 
4391fcf3ce44SJohn Forte 		break;
4392fcf3ce44SJohn Forte 
4393fcf3ce44SJohn Forte 	default:
4394fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4395291a2b48SSukumar Swaminathan 		    "%s: Image type not supported. type=%x", file_type, type);
4396fcf3ce44SJohn Forte 
4397fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_BAD);
4398fcf3ce44SJohn Forte 	}
4399fcf3ce44SJohn Forte 
4400fcf3ce44SJohn Forte 	return (0);
4401fcf3ce44SJohn Forte 
440282527734SSukumar Swaminathan } /* emlxs_validate_version() */
4403fcf3ce44SJohn Forte 
4404fcf3ce44SJohn Forte 
44056a573d82SSukumar Swaminathan static void
emlxs_verify_image(emlxs_hba_t * hba,emlxs_fw_image_t * fw_image)44066a573d82SSukumar Swaminathan emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *fw_image)
44076a573d82SSukumar Swaminathan {
44086a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
44096a573d82SSukumar Swaminathan 	emlxs_vpd_t *vpd = &VPD;
44106a573d82SSukumar Swaminathan 	uint32_t i;
44116a573d82SSukumar Swaminathan 	uint32_t count;
44126a573d82SSukumar Swaminathan 
44136a573d82SSukumar Swaminathan 	/* Check for AWC file */
44146a573d82SSukumar Swaminathan 	if (fw_image->awc.version) {
44156a573d82SSukumar Swaminathan 		if (fw_image->awc.version == vpd->postKernRev) {
44166a573d82SSukumar Swaminathan 			fw_image->awc.version = 0;
44176a573d82SSukumar Swaminathan 		}
44186a573d82SSukumar Swaminathan 
44196a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
44206a573d82SSukumar Swaminathan 		    "AWC file: KERN: old=%s  new=%s  %s.",
44216a573d82SSukumar Swaminathan 		    vpd->postKernName,
44226a573d82SSukumar Swaminathan 		    fw_image->awc.label,
44236a573d82SSukumar Swaminathan 		    (fw_image->awc.version)? "Update":"Skip");
44246a573d82SSukumar Swaminathan 	}
44256a573d82SSukumar Swaminathan 
44266a573d82SSukumar Swaminathan 	/* Check for BWC file */
44276a573d82SSukumar Swaminathan 	if (fw_image->bwc.version) {
44286a573d82SSukumar Swaminathan 		if (strcmp(vpd->fcode_version, fw_image->bwc.label) == 0) {
44296a573d82SSukumar Swaminathan 			fw_image->bwc.version = 0;
44306a573d82SSukumar Swaminathan 		}
44316a573d82SSukumar Swaminathan 
44326a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
44336a573d82SSukumar Swaminathan 		    "BWC file: BOOT: old=%s  new=%s  %s.",
44346a573d82SSukumar Swaminathan 		    vpd->fcode_version,
44356a573d82SSukumar Swaminathan 		    fw_image->bwc.label,
44366a573d82SSukumar Swaminathan 		    (fw_image->bwc.version)? "Update":"Skip");
44376a573d82SSukumar Swaminathan 	}
44386a573d82SSukumar Swaminathan 
44396a573d82SSukumar Swaminathan 	/* Check for DWC file */
44406a573d82SSukumar Swaminathan 	if (fw_image->dwc.version) {
44416a573d82SSukumar Swaminathan 		/* Check for program files */
44426a573d82SSukumar Swaminathan 		count = 0;
44436a573d82SSukumar Swaminathan 		for (i = 0; i < MAX_PROG_TYPES; i++) {
44446a573d82SSukumar Swaminathan 			if (!fw_image->prog[i].version) {
44456a573d82SSukumar Swaminathan 				continue;
44466a573d82SSukumar Swaminathan 			}
44476a573d82SSukumar Swaminathan 
44486a573d82SSukumar Swaminathan 			/* Skip components that don't need updating */
44496a573d82SSukumar Swaminathan 			switch (i) {
44506a573d82SSukumar Swaminathan 			case TEST_PROGRAM:
44516a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
44526a573d82SSukumar Swaminathan 				    "DWC file: TEST:             new=%s  "
44536a573d82SSukumar Swaminathan 				    "Update.",
44546a573d82SSukumar Swaminathan 				    fw_image->prog[i].label);
44556a573d82SSukumar Swaminathan 				break;
44566a573d82SSukumar Swaminathan 
44576a573d82SSukumar Swaminathan 			case BOOT_BIOS:
44586a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
44596a573d82SSukumar Swaminathan 				    "DWC file: BOOT:             new=%s  "
44606a573d82SSukumar Swaminathan 				    "Update.",
44616a573d82SSukumar Swaminathan 				    fw_image->prog[i].label);
44626a573d82SSukumar Swaminathan 				break;
44636a573d82SSukumar Swaminathan 
44646a573d82SSukumar Swaminathan 			case FUNC_FIRMWARE:
44656a573d82SSukumar Swaminathan 				if (vpd->opFwRev &&
44666a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
44676a573d82SSukumar Swaminathan 				    vpd->opFwRev)) {
44686a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
44696a573d82SSukumar Swaminathan 				}
44706a573d82SSukumar Swaminathan 
44716a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
44726a573d82SSukumar Swaminathan 				    "DWC file: STUB: old=%s  new=%s  %s.",
44736a573d82SSukumar Swaminathan 				    vpd->opFwName,
44746a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
44756a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
44766a573d82SSukumar Swaminathan 				    "Update":"Skip");
44776a573d82SSukumar Swaminathan 				break;
44786a573d82SSukumar Swaminathan 
44796a573d82SSukumar Swaminathan 			case SLI1_OVERLAY:
44806a573d82SSukumar Swaminathan 				if (vpd->sli1FwRev &&
44816a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
44826a573d82SSukumar Swaminathan 				    vpd->sli1FwRev)) {
44836a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
44846a573d82SSukumar Swaminathan 				}
44856a573d82SSukumar Swaminathan 
44866a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
44876a573d82SSukumar Swaminathan 				    "DWC file: SLI1: old=%s  new=%s  %s.",
44886a573d82SSukumar Swaminathan 				    vpd->sli1FwName,
44896a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
44906a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
44916a573d82SSukumar Swaminathan 				    "Update":"Skip");
44926a573d82SSukumar Swaminathan 				break;
44936a573d82SSukumar Swaminathan 
44946a573d82SSukumar Swaminathan 			case SLI2_OVERLAY:
44956a573d82SSukumar Swaminathan 				if (vpd->sli2FwRev &&
44966a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
44976a573d82SSukumar Swaminathan 				    vpd->sli2FwRev)) {
44986a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
44996a573d82SSukumar Swaminathan 				}
45006a573d82SSukumar Swaminathan 
45016a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
45026a573d82SSukumar Swaminathan 				    "DWC file: SLI2: old=%s  new=%s  %s.",
45036a573d82SSukumar Swaminathan 				    vpd->sli2FwName,
45046a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
45056a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
45066a573d82SSukumar Swaminathan 				    "Update":"Skip");
45076a573d82SSukumar Swaminathan 				break;
45086a573d82SSukumar Swaminathan 
45096a573d82SSukumar Swaminathan 			case SLI3_OVERLAY:
45106a573d82SSukumar Swaminathan 				if (vpd->sli3FwRev &&
45116a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
45126a573d82SSukumar Swaminathan 				    vpd->sli3FwRev)) {
45136a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
45146a573d82SSukumar Swaminathan 				}
45156a573d82SSukumar Swaminathan 
45166a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
45176a573d82SSukumar Swaminathan 				    "DWC file: SLI3: old=%s  new=%s  %s.",
45186a573d82SSukumar Swaminathan 				    vpd->sli3FwName,
45196a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
45206a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
45216a573d82SSukumar Swaminathan 				    "Update":"Skip");
45226a573d82SSukumar Swaminathan 				break;
45236a573d82SSukumar Swaminathan 
45246a573d82SSukumar Swaminathan 			case SLI4_OVERLAY:
45256a573d82SSukumar Swaminathan 				if (vpd->sli4FwRev &&
45266a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version ==
45276a573d82SSukumar Swaminathan 				    vpd->sli4FwRev)) {
45286a573d82SSukumar Swaminathan 					fw_image->prog[i].version = 0;
45296a573d82SSukumar Swaminathan 				}
45306a573d82SSukumar Swaminathan 
45316a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
45326a573d82SSukumar Swaminathan 				    "DWC file: SLI4: old=%s  new=%s  %s.",
45336a573d82SSukumar Swaminathan 				    vpd->sli4FwRev,
45346a573d82SSukumar Swaminathan 				    fw_image->prog[i].label,
45356a573d82SSukumar Swaminathan 				    (fw_image->prog[i].version)?
45366a573d82SSukumar Swaminathan 				    "Update":"Skip");
45376a573d82SSukumar Swaminathan 				break;
45386a573d82SSukumar Swaminathan 
45396a573d82SSukumar Swaminathan 			default:
45406a573d82SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
45416a573d82SSukumar Swaminathan 				    "DWC file: type=%x version=%x label=%s  "
45426a573d82SSukumar Swaminathan 				    "Update.",
45436a573d82SSukumar Swaminathan 				    i,
45446a573d82SSukumar Swaminathan 				    fw_image->prog[i].version,
45456a573d82SSukumar Swaminathan 				    fw_image->prog[i].label);
45466a573d82SSukumar Swaminathan 			}
45476a573d82SSukumar Swaminathan 
45486a573d82SSukumar Swaminathan 			if (fw_image->prog[i].version) {
45496a573d82SSukumar Swaminathan 				count++;
45506a573d82SSukumar Swaminathan 			}
45516a573d82SSukumar Swaminathan 		}
45526a573d82SSukumar Swaminathan 
45536a573d82SSukumar Swaminathan 		if (!count) {
45546a573d82SSukumar Swaminathan 			fw_image->dwc.version = 0;
45556a573d82SSukumar Swaminathan 		}
45566a573d82SSukumar Swaminathan 	}
45576a573d82SSukumar Swaminathan 
45586a573d82SSukumar Swaminathan 	return;
45596a573d82SSukumar Swaminathan 
45606a573d82SSukumar Swaminathan } /* emlxs_verify_image() */
45616a573d82SSukumar Swaminathan 
45626a573d82SSukumar Swaminathan 
4563fcf3ce44SJohn Forte static uint32_t
emlxs_validate_image(emlxs_hba_t * hba,caddr_t Buffer,uint32_t Size,emlxs_fw_image_t * image)4564fcf3ce44SJohn Forte emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
4565fcf3ce44SJohn Forte     emlxs_fw_image_t *image)
4566fcf3ce44SJohn Forte {
4567fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4568fcf3ce44SJohn Forte 	uint32_t ImageType;
4569fcf3ce44SJohn Forte 	AIF_HDR AifHdr;
4570fcf3ce44SJohn Forte 	IMAGE_HDR ImageHdr;
4571fcf3ce44SJohn Forte 	uint32_t NextImage;
45726a573d82SSukumar Swaminathan 	uint32_t count;
4573fcf3ce44SJohn Forte 	uint32_t FileType;
4574fcf3ce44SJohn Forte 	uint32_t FileLen = 0;
4575fcf3ce44SJohn Forte 	uint32_t TotalLen = 0;
4576fcf3ce44SJohn Forte 	uint32_t *CkSumEnd;
4577fcf3ce44SJohn Forte 	uint32_t id;
4578fcf3ce44SJohn Forte 	uint32_t type;
4579fcf3ce44SJohn Forte 	uint32_t ver;
4580fcf3ce44SJohn Forte 	uint32_t ImageLength;
4581fcf3ce44SJohn Forte 	uint32_t BufferSize;
4582fcf3ce44SJohn Forte 	uint32_t rval = 0;
4583fcf3ce44SJohn Forte 	caddr_t bptr;
4584fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
4585fcf3ce44SJohn Forte 
4586fcf3ce44SJohn Forte 	vpd = &VPD;
4587fcf3ce44SJohn Forte 
4588fcf3ce44SJohn Forte 	/* Get image type */
4589fcf3ce44SJohn Forte 	ImageType = *((uint32_t *)Buffer);
4590fcf3ce44SJohn Forte 
4591fcf3ce44SJohn Forte 	/* Pegasus and beyond adapters */
4592fcf3ce44SJohn Forte 	if ((ImageType == NOP_IMAGE_TYPE) &&
4593fcf3ce44SJohn Forte 	    !(hba->model_info.chip &
4594fcf3ce44SJohn Forte 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
4595fcf3ce44SJohn Forte 		bptr = Buffer;
4596fcf3ce44SJohn Forte 		TotalLen = sizeof (uint32_t);
4597fcf3ce44SJohn Forte 
4598fcf3ce44SJohn Forte 		while (TotalLen < Size) {
4599fcf3ce44SJohn Forte 			if (Size < sizeof (AIF_HDR)) {
4600291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
4601291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
4602fcf3ce44SJohn Forte 				    "Invalid image header length: 0x%x < 0x%x",
4603fcf3ce44SJohn Forte 				    Size, sizeof (AIF_HDR));
4604fcf3ce44SJohn Forte 
4605fcf3ce44SJohn Forte 				return (EMLXS_IMAGE_BAD);
4606fcf3ce44SJohn Forte 			}
4607291a2b48SSukumar Swaminathan 
4608fcf3ce44SJohn Forte 			bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
4609fcf3ce44SJohn Forte 			emlxs_disp_aif_header(hba, &AifHdr);
4610fcf3ce44SJohn Forte 
4611fcf3ce44SJohn Forte 			ImageLength = AifHdr.RoSize;
4612fcf3ce44SJohn Forte 
4613fcf3ce44SJohn Forte 			/* Validate checksum */
4614291a2b48SSukumar Swaminathan 			CkSumEnd =
4615291a2b48SSukumar Swaminathan 			    (uint32_t *)(bptr + ImageLength +
4616291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR));
4617fcf3ce44SJohn Forte 			if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
4618291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
4619291a2b48SSukumar Swaminathan 				    &emlxs_image_bad_msg,
4620fcf3ce44SJohn Forte 				    "Invalid checksum found.");
4621fcf3ce44SJohn Forte 
4622fcf3ce44SJohn Forte 				return (EMLXS_IMAGE_BAD);
4623fcf3ce44SJohn Forte 			}
4624291a2b48SSukumar Swaminathan 
4625fcf3ce44SJohn Forte 			FileType = AifHdr.ZinitBr;
4626fcf3ce44SJohn Forte 			switch (FileType) {
4627fcf3ce44SJohn Forte 			case FILE_TYPE_AWC:
4628291a2b48SSukumar Swaminathan 				image->awc.offset =
4629291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
4630291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
4631fcf3ce44SJohn Forte 				image->awc.version = AifHdr.AVersion;
4632fcf3ce44SJohn Forte 				image->awc.revcomp = 0;
4633fcf3ce44SJohn Forte 
4634fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4635fcf3ce44SJohn Forte 				type = emlxs_type_check(
4636fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
4637fcf3ce44SJohn Forte 
4638fcf3ce44SJohn Forte 				/* Validate the file version */
4639fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
4640fcf3ce44SJohn Forte 				    &image->awc, id, type, "AWC file"))) {
4641fcf3ce44SJohn Forte 					return (rval);
4642fcf3ce44SJohn Forte 				}
4643291a2b48SSukumar Swaminathan 
4644fcf3ce44SJohn Forte 				break;
4645fcf3ce44SJohn Forte 
4646fcf3ce44SJohn Forte 			case FILE_TYPE_BWC:
4647291a2b48SSukumar Swaminathan 				image->bwc.offset =
4648291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
4649291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
4650fcf3ce44SJohn Forte 				image->bwc.version = AifHdr.AVersion;
4651fcf3ce44SJohn Forte 				image->bwc.revcomp = 0;
4652fcf3ce44SJohn Forte 
4653fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4654fcf3ce44SJohn Forte 				type = emlxs_type_check(
4655fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
4656fcf3ce44SJohn Forte 
4657fcf3ce44SJohn Forte 				/* Validate the file version */
4658fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
4659fcf3ce44SJohn Forte 				    &image->bwc, id, type, "BWC file"))) {
4660fcf3ce44SJohn Forte 					return (rval);
4661fcf3ce44SJohn Forte 				}
4662291a2b48SSukumar Swaminathan 
4663fcf3ce44SJohn Forte 				break;
4664fcf3ce44SJohn Forte 
4665fcf3ce44SJohn Forte 			case FILE_TYPE_DWC:
4666291a2b48SSukumar Swaminathan 				image->dwc.offset =
4667291a2b48SSukumar Swaminathan 				    (uint32_t)((uintptr_t)bptr -
4668291a2b48SSukumar Swaminathan 				    (uintptr_t)Buffer);
4669fcf3ce44SJohn Forte 				image->dwc.version = AifHdr.AVersion;
4670fcf3ce44SJohn Forte 				image->dwc.revcomp = 0;
4671fcf3ce44SJohn Forte 
4672fcf3ce44SJohn Forte 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4673fcf3ce44SJohn Forte 				type = emlxs_type_check(
4674fcf3ce44SJohn Forte 				    (AifHdr.AVersion & 0xff000000) >> 24);
4675fcf3ce44SJohn Forte 
4676fcf3ce44SJohn Forte 				/* Validate the file version */
4677fcf3ce44SJohn Forte 				if ((rval = emlxs_validate_version(hba,
4678fcf3ce44SJohn Forte 				    &image->dwc, id, type, "DWC file"))) {
4679fcf3ce44SJohn Forte 					return (rval);
4680fcf3ce44SJohn Forte 				}
4681291a2b48SSukumar Swaminathan 
4682fcf3ce44SJohn Forte 				/* Scan for program types */
4683fcf3ce44SJohn Forte 				NextImage = sizeof (AIF_HDR) + 4;
4684fcf3ce44SJohn Forte 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
4685fcf3ce44SJohn Forte 
46866a573d82SSukumar Swaminathan 				count = 0;
4687fcf3ce44SJohn Forte 				while (BufferSize > NextImage) {
4688fcf3ce44SJohn Forte 					bcopy(&bptr[NextImage], &ImageHdr,
4689fcf3ce44SJohn Forte 					    sizeof (IMAGE_HDR));
4690291a2b48SSukumar Swaminathan 					emlxs_dump_image_header(hba,
4691291a2b48SSukumar Swaminathan 					    &ImageHdr);
4692fcf3ce44SJohn Forte 
4693fcf3ce44SJohn Forte 					/* Validate block size */
4694fcf3ce44SJohn Forte 					if (ImageHdr.BlockSize == 0xffffffff) {
4695fcf3ce44SJohn Forte 						break;
4696fcf3ce44SJohn Forte 					}
4697291a2b48SSukumar Swaminathan 
4698fcf3ce44SJohn Forte 					type = emlxs_type_check(
4699fcf3ce44SJohn Forte 					    ImageHdr.Id.Type);
4700fcf3ce44SJohn Forte 
4701fcf3ce44SJohn Forte 					/* Calculate the program offset */
4702291a2b48SSukumar Swaminathan 					image->prog[type].offset =
4703291a2b48SSukumar Swaminathan 					    (uint32_t)((uintptr_t)
4704291a2b48SSukumar Swaminathan 					    &bptr[NextImage] -
4705fcf3ce44SJohn Forte 					    (uintptr_t)Buffer);
4706fcf3ce44SJohn Forte 
4707fcf3ce44SJohn Forte 					/* Acquire the versions */
4708fcf3ce44SJohn Forte 					image->prog[type].version =
4709fcf3ce44SJohn Forte 					    (ImageHdr.Id.Type << 24) |
4710fcf3ce44SJohn Forte 					    (ImageHdr.Id.Id << 16) |
4711fcf3ce44SJohn Forte 					    (ImageHdr.Id.Ver << 8) |
4712fcf3ce44SJohn Forte 					    ImageHdr.Id.Rev;
4713fcf3ce44SJohn Forte 
4714fcf3ce44SJohn Forte 					image->prog[type].revcomp =
4715fcf3ce44SJohn Forte 					    ImageHdr.Id.un.revcomp;
4716fcf3ce44SJohn Forte 
4717fcf3ce44SJohn Forte 					/* Validate the file version */
4718fcf3ce44SJohn Forte 					if ((rval = emlxs_validate_version(hba,
4719fcf3ce44SJohn Forte 					    &image->prog[type], ImageHdr.Id.Id,
4720fcf3ce44SJohn Forte 					    type, "DWC prog"))) {
4721fcf3ce44SJohn Forte 						return (rval);
4722fcf3ce44SJohn Forte 					}
4723291a2b48SSukumar Swaminathan 
47246a573d82SSukumar Swaminathan 					count++;
4725fcf3ce44SJohn Forte 					NextImage += ImageHdr.BlockSize;
4726fcf3ce44SJohn Forte 
472782527734SSukumar Swaminathan 				}	/* while () */
4728fcf3ce44SJohn Forte 
47296a573d82SSukumar Swaminathan 				if (count == 0) {
47306a573d82SSukumar Swaminathan 					EMLXS_MSGF(EMLXS_CONTEXT,
47316a573d82SSukumar Swaminathan 					    &emlxs_image_bad_msg,
47326a573d82SSukumar Swaminathan 					    "DWC file has no PRG images.");
47336a573d82SSukumar Swaminathan 
47346a573d82SSukumar Swaminathan 					return (EMLXS_IMAGE_BAD);
47356a573d82SSukumar Swaminathan 				}
47366a573d82SSukumar Swaminathan 
4737fcf3ce44SJohn Forte 				break;
4738fcf3ce44SJohn Forte 			}
4739fcf3ce44SJohn Forte 
4740291a2b48SSukumar Swaminathan 			FileLen =
4741291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR) + ImageLength +
4742fcf3ce44SJohn Forte 			    sizeof (uint32_t);
4743fcf3ce44SJohn Forte 			TotalLen += FileLen;
4744fcf3ce44SJohn Forte 			bptr += FileLen;
4745fcf3ce44SJohn Forte 		}
4746fcf3ce44SJohn Forte 	}
4747291a2b48SSukumar Swaminathan 
4748fcf3ce44SJohn Forte 	/* Pre-pegasus adapters */
4749fcf3ce44SJohn Forte 
4750fcf3ce44SJohn Forte 	else if (ImageType == NOP_IMAGE_TYPE) {
4751fcf3ce44SJohn Forte 		if (Size < sizeof (AIF_HDR)) {
4752fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4753291a2b48SSukumar Swaminathan 			    "Invalid image header length: 0x%x < 0x%x", Size,
4754291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR));
4755fcf3ce44SJohn Forte 
4756fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4757fcf3ce44SJohn Forte 		}
4758291a2b48SSukumar Swaminathan 
4759fcf3ce44SJohn Forte 		bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
4760fcf3ce44SJohn Forte 		emlxs_disp_aif_header(hba, &AifHdr);
4761fcf3ce44SJohn Forte 
4762fcf3ce44SJohn Forte 		ImageLength = AifHdr.RoSize + AifHdr.RwSize;
4763fcf3ce44SJohn Forte 
4764fcf3ce44SJohn Forte 		if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
4765fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4766291a2b48SSukumar Swaminathan 			    "Image length incorrect: 0x%x != 0x%x", Size,
4767291a2b48SSukumar Swaminathan 			    sizeof (AIF_HDR) + ImageLength +
4768291a2b48SSukumar Swaminathan 			    sizeof (uint32_t));
4769fcf3ce44SJohn Forte 
4770fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4771fcf3ce44SJohn Forte 		}
4772291a2b48SSukumar Swaminathan 
4773fcf3ce44SJohn Forte 		if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
4774fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4775fcf3ce44SJohn Forte 			    "Invalid imageBase value %x != 0x20000",
4776fcf3ce44SJohn Forte 			    AifHdr.ImageBase);
4777fcf3ce44SJohn Forte 
4778fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4779fcf3ce44SJohn Forte 		}
4780291a2b48SSukumar Swaminathan 
4781291a2b48SSukumar Swaminathan 		CkSumEnd =
4782291a2b48SSukumar Swaminathan 		    (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
4783fcf3ce44SJohn Forte 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4784fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4785fcf3ce44SJohn Forte 			    "Invalid checksum found.");
4786fcf3ce44SJohn Forte 
4787fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4788fcf3ce44SJohn Forte 		}
4789291a2b48SSukumar Swaminathan 
4790fcf3ce44SJohn Forte 		image->dwc.offset = 0;
4791fcf3ce44SJohn Forte 		image->dwc.version = AifHdr.AVersion;
4792fcf3ce44SJohn Forte 		image->dwc.revcomp = 0;
4793fcf3ce44SJohn Forte 
4794fcf3ce44SJohn Forte 		id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4795fcf3ce44SJohn Forte 		type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
4796fcf3ce44SJohn Forte 
4797fcf3ce44SJohn Forte 		/* Validate the file version */
4798291a2b48SSukumar Swaminathan 		if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
4799291a2b48SSukumar Swaminathan 		    "DWC file"))) {
4800fcf3ce44SJohn Forte 			return (rval);
4801fcf3ce44SJohn Forte 		}
4802291a2b48SSukumar Swaminathan 
4803fcf3ce44SJohn Forte 		NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
4804fcf3ce44SJohn Forte 		while (Size > NextImage) {
4805fcf3ce44SJohn Forte 			bcopy(&Buffer[NextImage], &ImageHdr,
4806fcf3ce44SJohn Forte 			    sizeof (IMAGE_HDR));
4807fcf3ce44SJohn Forte 			emlxs_dump_image_header(hba, &ImageHdr);
4808fcf3ce44SJohn Forte 
4809fcf3ce44SJohn Forte 			/* Validate block size */
4810fcf3ce44SJohn Forte 			if (ImageHdr.BlockSize == 0xffffffff) {
4811fcf3ce44SJohn Forte 				break;
4812fcf3ce44SJohn Forte 			}
4813291a2b48SSukumar Swaminathan 
4814fcf3ce44SJohn Forte 			type = emlxs_type_check(ImageHdr.Id.Type);
4815fcf3ce44SJohn Forte 
4816fcf3ce44SJohn Forte 			/* Calculate the program offset */
4817fcf3ce44SJohn Forte 			image->prog[type].offset = NextImage;
4818fcf3ce44SJohn Forte 
4819fcf3ce44SJohn Forte 			/* Acquire the versions */
4820291a2b48SSukumar Swaminathan 			image->prog[type].version =
4821291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Type << 24) |
4822291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Id << 16) |
4823291a2b48SSukumar Swaminathan 			    (ImageHdr.Id.Ver << 8) |
4824fcf3ce44SJohn Forte 			    ImageHdr.Id.Rev;
4825fcf3ce44SJohn Forte 
4826fcf3ce44SJohn Forte 			image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4827fcf3ce44SJohn Forte 
4828fcf3ce44SJohn Forte 			/* Validate the file version */
4829fcf3ce44SJohn Forte 			if ((rval = emlxs_validate_version(hba,
4830291a2b48SSukumar Swaminathan 			    &image->prog[type], ImageHdr.Id.Id, type,
4831291a2b48SSukumar Swaminathan 			    "DWC prog"))) {
4832fcf3ce44SJohn Forte 				return (rval);
4833fcf3ce44SJohn Forte 			}
4834291a2b48SSukumar Swaminathan 
4835fcf3ce44SJohn Forte 			NextImage += ImageHdr.BlockSize;
4836fcf3ce44SJohn Forte 		}
48376a573d82SSukumar Swaminathan 
48386a573d82SSukumar Swaminathan 	} else { /* PRG File */
48396a573d82SSukumar Swaminathan 
4840fcf3ce44SJohn Forte 		/* Precheck image size */
4841fcf3ce44SJohn Forte 		if (Size < sizeof (IMAGE_HDR)) {
4842fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4843291a2b48SSukumar Swaminathan 			    "Invalid image header length: 0x%x < 0x%x", Size,
4844291a2b48SSukumar Swaminathan 			    sizeof (IMAGE_HDR));
4845fcf3ce44SJohn Forte 
4846fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4847fcf3ce44SJohn Forte 		}
4848291a2b48SSukumar Swaminathan 
4849fcf3ce44SJohn Forte 		bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
4850fcf3ce44SJohn Forte 		emlxs_dump_image_header(hba, &ImageHdr);
4851fcf3ce44SJohn Forte 
4852fcf3ce44SJohn Forte 		/* Validate block size */
4853fcf3ce44SJohn Forte 		if (ImageHdr.BlockSize == 0xffffffff) {
4854fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4855fcf3ce44SJohn Forte 			    "Invalid block size.");
4856fcf3ce44SJohn Forte 
4857fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4858fcf3ce44SJohn Forte 		}
4859291a2b48SSukumar Swaminathan 
4860fcf3ce44SJohn Forte 		ImageLength = ImageHdr.BlockSize;
4861fcf3ce44SJohn Forte 
4862fcf3ce44SJohn Forte 		/* Validate image length */
4863fcf3ce44SJohn Forte 		if (Size != ImageLength) {
4864fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4865291a2b48SSukumar Swaminathan 			    "Invalid image length: 0x%x != 0x%x", Size,
4866291a2b48SSukumar Swaminathan 			    ImageLength);
4867fcf3ce44SJohn Forte 
4868fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4869fcf3ce44SJohn Forte 		}
4870291a2b48SSukumar Swaminathan 
4871fcf3ce44SJohn Forte 		/* Validate Checksum */
4872291a2b48SSukumar Swaminathan 		CkSumEnd =
4873291a2b48SSukumar Swaminathan 		    (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
4874291a2b48SSukumar Swaminathan 		    1;
4875fcf3ce44SJohn Forte 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4876fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4877fcf3ce44SJohn Forte 			    "Invalid checksum found.");
4878fcf3ce44SJohn Forte 
4879fcf3ce44SJohn Forte 			return (EMLXS_IMAGE_BAD);
4880fcf3ce44SJohn Forte 		}
4881291a2b48SSukumar Swaminathan 
4882fcf3ce44SJohn Forte 		type = emlxs_type_check(ImageHdr.Id.Type);
4883fcf3ce44SJohn Forte 
4884fcf3ce44SJohn Forte 		/* Calculate the program offset */
4885fcf3ce44SJohn Forte 		image->prog[type].offset = 0;
4886fcf3ce44SJohn Forte 
4887fcf3ce44SJohn Forte 		/* Acquire the versions */
4888291a2b48SSukumar Swaminathan 		image->prog[type].version =
48896a573d82SSukumar Swaminathan 		    (ImageHdr.Id.Type << 24) |
48906a573d82SSukumar Swaminathan 		    (ImageHdr.Id.Id << 16) |
48916a573d82SSukumar Swaminathan 		    (ImageHdr.Id.Ver << 8) |
48926a573d82SSukumar Swaminathan 		    ImageHdr.Id.Rev;
4893fcf3ce44SJohn Forte 
4894fcf3ce44SJohn Forte 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4895fcf3ce44SJohn Forte 
4896fcf3ce44SJohn Forte 		/* Validate the file version */
4897fcf3ce44SJohn Forte 		if ((rval = emlxs_validate_version(hba, &image->prog[type],
4898fcf3ce44SJohn Forte 		    ImageHdr.Id.Id, type, "DWC file"))) {
4899fcf3ce44SJohn Forte 			return (rval);
4900fcf3ce44SJohn Forte 		}
4901fcf3ce44SJohn Forte 	}
4902fcf3ce44SJohn Forte 
4903fcf3ce44SJohn Forte 	/*
4904291a2b48SSukumar Swaminathan 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
49056a573d82SSukumar Swaminathan 	 * image file is < version 3.8
4906fcf3ce44SJohn Forte 	 */
4907fcf3ce44SJohn Forte 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
49086a573d82SSukumar Swaminathan 		ver = (image->prog[SLI2_OVERLAY].version &
49096a573d82SSukumar Swaminathan 		    0x0000ff00) >> 8;
4910fcf3ce44SJohn Forte 
49116a573d82SSukumar Swaminathan 		if (ver >= 0x38) {
49126a573d82SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
49136a573d82SSukumar Swaminathan 			    &emlxs_image_incompat_msg,
49146a573d82SSukumar Swaminathan 			    "ASIC Check: Image requires DragonFly "
49156a573d82SSukumar Swaminathan 			    "V2 ASIC");
4916fcf3ce44SJohn Forte 
49176a573d82SSukumar Swaminathan 			return (EMLXS_IMAGE_INCOMPATIBLE);
4918fcf3ce44SJohn Forte 		}
4919fcf3ce44SJohn Forte 	}
4920291a2b48SSukumar Swaminathan 
4921fcf3ce44SJohn Forte 	return (0);
4922fcf3ce44SJohn Forte 
492382527734SSukumar Swaminathan } /* emlxs_validate_image() */
4924fcf3ce44SJohn Forte 
4925fcf3ce44SJohn Forte 
4926fcf3ce44SJohn Forte static uint32_t
emlxs_update_exp_rom(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms)4927fcf3ce44SJohn Forte emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
4928fcf3ce44SJohn Forte {
4929fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
4930fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
4931fcf3ce44SJohn Forte 	MAILBOX *mb;
4932fcf3ce44SJohn Forte 	uint32_t next_address;
4933fcf3ce44SJohn Forte 	uint32_t rval = 0;
4934fcf3ce44SJohn Forte 
4935fcf3ce44SJohn Forte 	if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
4936fcf3ce44SJohn Forte 		return (1);
4937fcf3ce44SJohn Forte 	}
4938291a2b48SSukumar Swaminathan 
4939291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4940291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
4941fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4942fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
4943fcf3ce44SJohn Forte 
4944fcf3ce44SJohn Forte 		return (1);
4945fcf3ce44SJohn Forte 	}
4946291a2b48SSukumar Swaminathan 
4947fcf3ce44SJohn Forte 	bzero(mbox, sizeof (MAILBOXQ));
4948fcf3ce44SJohn Forte 
4949fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
4950fcf3ce44SJohn Forte 	mb->mbxCommand = MBX_LOAD_EXP_ROM;
4951fcf3ce44SJohn Forte 	mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
4952fcf3ce44SJohn Forte 	mb->un.varLdExpRom.progress = 0;
4953fcf3ce44SJohn Forte 	mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
495482527734SSukumar Swaminathan 	mbox->mbox_cmpl = NULL;
4955fcf3ce44SJohn Forte 
495682527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4957fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4958fcf3ce44SJohn Forte 		    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4959fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
4960fcf3ce44SJohn Forte 
4961fcf3ce44SJohn Forte 		rval = 1;
4962fcf3ce44SJohn Forte 
4963fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
4964fcf3ce44SJohn Forte 	}
4965291a2b48SSukumar Swaminathan 
4966fcf3ce44SJohn Forte 	if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
4967fcf3ce44SJohn Forte 		(void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4968fcf3ce44SJohn Forte 
4969fcf3ce44SJohn Forte 		rval = 1;
4970fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
4971fcf3ce44SJohn Forte 	}
4972291a2b48SSukumar Swaminathan 
4973fcf3ce44SJohn Forte 	if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
4974fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4975fcf3ce44SJohn Forte 		    "Invalid exp ROM progress. progress=%x",
4976fcf3ce44SJohn Forte 		    mb->un.varLdExpRom.progress);
4977fcf3ce44SJohn Forte 
4978fcf3ce44SJohn Forte 		rval = 1;
4979fcf3ce44SJohn Forte 
4980fcf3ce44SJohn Forte 		goto SLI_DOWNLOAD_EXIT;
4981fcf3ce44SJohn Forte 	}
4982291a2b48SSukumar Swaminathan 
4983fcf3ce44SJohn Forte 	/*
4984fcf3ce44SJohn Forte 	 * continue Erase
4985fcf3ce44SJohn Forte 	 */
4986fcf3ce44SJohn Forte 	while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
4987fcf3ce44SJohn Forte 
4988fcf3ce44SJohn Forte 		next_address = mb->un.varLdExpRom.dl_to_adr;
4989fcf3ce44SJohn Forte 
4990fcf3ce44SJohn Forte 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
4991fcf3ce44SJohn Forte 
4992fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
4993fcf3ce44SJohn Forte 		mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
4994fcf3ce44SJohn Forte 		mb->un.varLdExpRom.dl_to_adr = next_address;
4995fcf3ce44SJohn Forte 		mb->un.varLdExpRom.progress = 0;
4996fcf3ce44SJohn Forte 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
499782527734SSukumar Swaminathan 		mbox->mbox_cmpl = NULL;
4998fcf3ce44SJohn Forte 
499982527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5000291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
5001fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5002fcf3ce44SJohn Forte 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
5003fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
5004fcf3ce44SJohn Forte 
5005fcf3ce44SJohn Forte 			rval = 1;
5006fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
5007fcf3ce44SJohn Forte 		}
5008291a2b48SSukumar Swaminathan 
5009fcf3ce44SJohn Forte 	}
5010fcf3ce44SJohn Forte 
5011fcf3ce44SJohn Forte 	while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
5012fcf3ce44SJohn Forte 		next_address = mb->un.varLdExpRom.dl_to_adr;
5013fcf3ce44SJohn Forte 
5014fcf3ce44SJohn Forte 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
5015fcf3ce44SJohn Forte 
5016fcf3ce44SJohn Forte 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
5017fcf3ce44SJohn Forte 		mb->un.varLdExpRom.step = EROM_CMD_COPY;
5018fcf3ce44SJohn Forte 		mb->un.varLdExpRom.dl_to_adr = next_address;
5019fcf3ce44SJohn Forte 		mb->un.varLdExpRom.progress = 0;
5020fcf3ce44SJohn Forte 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
502182527734SSukumar Swaminathan 		mbox->mbox_cmpl = NULL;
5022fcf3ce44SJohn Forte 
502382527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5024291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
5025fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5026fcf3ce44SJohn Forte 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
5027fcf3ce44SJohn Forte 			    mb->mbxCommand, mb->mbxStatus);
5028fcf3ce44SJohn Forte 
5029fcf3ce44SJohn Forte 			rval = 1;
5030fcf3ce44SJohn Forte 
5031fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_EXIT;
5032fcf3ce44SJohn Forte 		}
5033fcf3ce44SJohn Forte 	}
5034fcf3ce44SJohn Forte 
5035fcf3ce44SJohn Forte 	rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
5036fcf3ce44SJohn Forte 
5037fcf3ce44SJohn Forte SLI_DOWNLOAD_EXIT:
5038fcf3ce44SJohn Forte 
5039fcf3ce44SJohn Forte 	if (mbox) {
5040fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
5041fcf3ce44SJohn Forte 	}
5042291a2b48SSukumar Swaminathan 
5043fcf3ce44SJohn Forte 	return (rval);
5044fcf3ce44SJohn Forte 
504582527734SSukumar Swaminathan } /* emlxs_update_exp_rom() */
5046fcf3ce44SJohn Forte 
5047fcf3ce44SJohn Forte 
5048fcf3ce44SJohn Forte /*
5049fcf3ce44SJohn Forte  *
5050fcf3ce44SJohn Forte  * FUNCTION NAME: emlxs_start_abs_download_2mb
5051fcf3ce44SJohn Forte  *
5052fcf3ce44SJohn Forte  * DESCRIPTION: Perform absolute download for 2 MB flash.  A incoming
5053fcf3ce44SJohn Forte  *              buffer may consist of more than 1 file.  This function
5054fcf3ce44SJohn Forte  *              will parse the buffer to find all the files.
5055fcf3ce44SJohn Forte  *
5056fcf3ce44SJohn Forte  *
5057fcf3ce44SJohn Forte  * PARAMETERS:
5058fcf3ce44SJohn Forte  *
5059fcf3ce44SJohn Forte  *
5060fcf3ce44SJohn Forte  * RETURNS:
5061fcf3ce44SJohn Forte  *
5062fcf3ce44SJohn Forte  */
5063fcf3ce44SJohn Forte /* ARGSUSED */
5064fcf3ce44SJohn Forte static uint32_t
emlxs_start_abs_download_2mb(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline,emlxs_fw_image_t * fw_image)5065fcf3ce44SJohn Forte emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
5066fcf3ce44SJohn Forte     uint32_t offline, emlxs_fw_image_t *fw_image)
5067fcf3ce44SJohn Forte {
5068fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5069fcf3ce44SJohn Forte 	uint32_t rval = 0;
5070fcf3ce44SJohn Forte 
5071fcf3ce44SJohn Forte 	/* If nothing to download then quit now */
50726a573d82SSukumar Swaminathan 	if (!fw_image->awc.version &&
50736a573d82SSukumar Swaminathan 	    !fw_image->dwc.version &&
50746a573d82SSukumar Swaminathan 	    !fw_image->bwc.version) {
50756a573d82SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
50766a573d82SSukumar Swaminathan 		    "Nothing new to update.  Exiting.");
5077fcf3ce44SJohn Forte 		return (0);
5078fcf3ce44SJohn Forte 	}
5079291a2b48SSukumar Swaminathan 
5080fcf3ce44SJohn Forte 	/*
5081fcf3ce44SJohn Forte 	 * Everything checks out, now to just do it
5082fcf3ce44SJohn Forte 	 */
5083fcf3ce44SJohn Forte 	if (offline) {
5084*8f23e9faSHans Rosenfeld 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
5085fcf3ce44SJohn Forte 			return (EMLXS_OFFLINE_FAILED);
5086fcf3ce44SJohn Forte 		}
5087291a2b48SSukumar Swaminathan 
508882527734SSukumar Swaminathan 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
5089fcf3ce44SJohn Forte 			return (EMLXS_OFFLINE_FAILED);
5090fcf3ce44SJohn Forte 		}
5091fcf3ce44SJohn Forte 	}
5092291a2b48SSukumar Swaminathan 
50936a573d82SSukumar Swaminathan 	if (fw_image->awc.version) {
5094291a2b48SSukumar Swaminathan 		rval = emlxs_proc_abs_2mb(hba,
50956a573d82SSukumar Swaminathan 		    (buffer + fw_image->awc.offset),
50966a573d82SSukumar Swaminathan 		    FILE_TYPE_AWC, 0);
5097fcf3ce44SJohn Forte 
5098fcf3ce44SJohn Forte 		if (rval) {
5099fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_2MB_EXIT;
5100fcf3ce44SJohn Forte 		}
5101fcf3ce44SJohn Forte 	}
5102291a2b48SSukumar Swaminathan 
51036a573d82SSukumar Swaminathan 	if (fw_image->bwc.version) {
5104291a2b48SSukumar Swaminathan 		rval = emlxs_proc_abs_2mb(hba,
51056a573d82SSukumar Swaminathan 		    (buffer + fw_image->bwc.offset),
51066a573d82SSukumar Swaminathan 		    FILE_TYPE_BWC,
51076a573d82SSukumar Swaminathan 		    (fw_image->dwc.version)? ALLext:BWCext);
5108fcf3ce44SJohn Forte 
5109fcf3ce44SJohn Forte 		if (rval) {
5110fcf3ce44SJohn Forte 			goto SLI_DOWNLOAD_2MB_EXIT;
5111fcf3ce44SJohn Forte 		}
5112fcf3ce44SJohn Forte 	}
5113291a2b48SSukumar Swaminathan 
51146a573d82SSukumar Swaminathan 	if (fw_image->dwc.version) {
51156a573d82SSukumar Swaminathan 		rval = emlxs_proc_rel_2mb(hba, buffer, fw_image);
5116fcf3ce44SJohn Forte 
51176a573d82SSukumar Swaminathan 		if (rval) {
51186a573d82SSukumar Swaminathan 			goto SLI_DOWNLOAD_2MB_EXIT;
51196a573d82SSukumar Swaminathan 		}
5120fcf3ce44SJohn Forte 	}
5121291a2b48SSukumar Swaminathan 
5122fcf3ce44SJohn Forte SLI_DOWNLOAD_2MB_EXIT:
5123fcf3ce44SJohn Forte 
5124fcf3ce44SJohn Forte 	if (offline) {
5125fcf3ce44SJohn Forte 		(void) emlxs_online(hba);
5126fcf3ce44SJohn Forte 	}
5127291a2b48SSukumar Swaminathan 
5128fcf3ce44SJohn Forte 	return (rval);
5129fcf3ce44SJohn Forte 
513082527734SSukumar Swaminathan } /* emlxs_start_abs_download_2mb() */
5131fcf3ce44SJohn Forte 
5132fcf3ce44SJohn Forte 
5133fcf3ce44SJohn Forte /*
5134fcf3ce44SJohn Forte  *
5135fcf3ce44SJohn Forte  * FUNCTION NAME: emlxs_proc_abs_2mb
5136fcf3ce44SJohn Forte  *
5137fcf3ce44SJohn Forte  * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
5138fcf3ce44SJohn Forte  *              the port and download the file with sliIssueMbCommand()
5139fcf3ce44SJohn Forte  *
5140fcf3ce44SJohn Forte  *
5141fcf3ce44SJohn Forte  * PARAMETERS:
5142fcf3ce44SJohn Forte  *
5143fcf3ce44SJohn Forte  *
5144fcf3ce44SJohn Forte  * RETURNS:
5145fcf3ce44SJohn Forte  *
5146fcf3ce44SJohn Forte  */
5147fcf3ce44SJohn Forte static uint32_t
emlxs_proc_abs_2mb(emlxs_hba_t * hba,caddr_t EntireBuffer,uint32_t FileType,uint32_t extType)51486a573d82SSukumar Swaminathan emlxs_proc_abs_2mb(emlxs_hba_t *hba, caddr_t EntireBuffer,
51496a573d82SSukumar Swaminathan     uint32_t FileType, uint32_t extType)
5150fcf3ce44SJohn Forte {
5151fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
51526a573d82SSukumar Swaminathan 	PAIF_HDR AifHdr;
5153fcf3ce44SJohn Forte 	caddr_t Buffer = NULL;
5154fcf3ce44SJohn Forte 	caddr_t DataBuffer = NULL;
5155fcf3ce44SJohn Forte 	uint32_t *Src;
5156fcf3ce44SJohn Forte 	uint32_t *Dst;
5157fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
5158fcf3ce44SJohn Forte 	MAILBOX *mb;
51596a573d82SSukumar Swaminathan 	uint32_t DlByteCount;
5160fcf3ce44SJohn Forte 	uint32_t rval = 0;
5161fcf3ce44SJohn Forte 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
51626a573d82SSukumar Swaminathan 	uint32_t DlToAddr;
5163fcf3ce44SJohn Forte 	uint32_t DlCount;
5164fcf3ce44SJohn Forte 	WAKE_UP_PARMS AbsWakeUpParms;
5165fcf3ce44SJohn Forte 	uint32_t i;
5166fcf3ce44SJohn Forte 	uint32_t NextAddr;
5167fcf3ce44SJohn Forte 	uint32_t EraseByteCount;
5168fcf3ce44SJohn Forte 	uint32_t AreaId;
5169fcf3ce44SJohn Forte 	uint32_t RspProgress = 0;
51706a573d82SSukumar Swaminathan 	uint32_t ParamsChg;
51716a573d82SSukumar Swaminathan 
51726a573d82SSukumar Swaminathan 	AifHdr = (PAIF_HDR)EntireBuffer;
51736a573d82SSukumar Swaminathan 	DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
51746a573d82SSukumar Swaminathan 	DlToAddr = AifHdr->ImageBase;
5175fcf3ce44SJohn Forte 
5176291a2b48SSukumar Swaminathan 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
5177291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
5178fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5179fcf3ce44SJohn Forte 		    "%x: Unable to allocate data buffer.", FileType);
5180fcf3ce44SJohn Forte 
5181fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_FAILED);
5182fcf3ce44SJohn Forte 	}
5183291a2b48SSukumar Swaminathan 
5184291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
5185291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
5186fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5187fcf3ce44SJohn Forte 		    "%x: Unable to allocate mailbox buffer.", FileType);
5188fcf3ce44SJohn Forte 
5189fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
5190fcf3ce44SJohn Forte 
5191fcf3ce44SJohn Forte 		return (EMLXS_IMAGE_FAILED);
5192fcf3ce44SJohn Forte 	}
5193291a2b48SSukumar Swaminathan 
5194fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
5195fcf3ce44SJohn Forte 
5196fcf3ce44SJohn Forte 	Buffer = EntireBuffer + sizeof (AIF_HDR);
5197fcf3ce44SJohn Forte 
5198fcf3ce44SJohn Forte 	switch (FileType) {
5199fcf3ce44SJohn Forte 	case FILE_TYPE_AWC:
52006a573d82SSukumar Swaminathan 		ParamsChg = 0;
5201fcf3ce44SJohn Forte 		break;
5202fcf3ce44SJohn Forte 
5203fcf3ce44SJohn Forte 	case FILE_TYPE_BWC:
52046a573d82SSukumar Swaminathan 		rval = emlxs_build_parms_2mb_bwc(hba,
5205291a2b48SSukumar Swaminathan 		    AifHdr, extType, &AbsWakeUpParms);
5206fcf3ce44SJohn Forte 
52076a573d82SSukumar Swaminathan 		if (rval == FALSE) {
5208fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5209fcf3ce44SJohn Forte 			    "BWC build parms failed.");
5210fcf3ce44SJohn Forte 
5211fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
5212fcf3ce44SJohn Forte 
5213fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
5214fcf3ce44SJohn Forte 		}
52156a573d82SSukumar Swaminathan 		ParamsChg = 1;
5216fcf3ce44SJohn Forte 		break;
5217fcf3ce44SJohn Forte 
5218fcf3ce44SJohn Forte 	default:
5219fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
5220fcf3ce44SJohn Forte 		    "Invalid file type: %x", FileType);
5221fcf3ce44SJohn Forte 
5222fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_BAD;
5223fcf3ce44SJohn Forte 
5224fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
5225fcf3ce44SJohn Forte 	}
5226fcf3ce44SJohn Forte 
5227fcf3ce44SJohn Forte 	EraseByteCount = AifHdr->Area_Size;
5228fcf3ce44SJohn Forte 	AreaId = AifHdr->Area_ID;
5229fcf3ce44SJohn Forte 
523082527734SSukumar Swaminathan 	emlxs_format_load_area_cmd(mbox,
5231291a2b48SSukumar Swaminathan 	    DlToAddr,
5232291a2b48SSukumar Swaminathan 	    EraseByteCount,
5233291a2b48SSukumar Swaminathan 	    ERASE_FLASH,
5234fcf3ce44SJohn Forte 	    0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
5235fcf3ce44SJohn Forte 
523682527734SSukumar Swaminathan 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
5237fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5238fcf3ce44SJohn Forte 		    "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
5239fcf3ce44SJohn Forte 		    FileType, mb->mbxCommand, mb->mbxStatus);
5240fcf3ce44SJohn Forte 
5241fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_FAILED;
5242fcf3ce44SJohn Forte 
5243fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
5244fcf3ce44SJohn Forte 	}
5245291a2b48SSukumar Swaminathan 
5246fcf3ce44SJohn Forte 	while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
5247fcf3ce44SJohn Forte 		NextAddr = mb->un.varLdArea.dl_to_adr;
5248fcf3ce44SJohn Forte 
524982527734SSukumar Swaminathan 		emlxs_format_load_area_cmd(mbox,
5250291a2b48SSukumar Swaminathan 		    NextAddr,
5251291a2b48SSukumar Swaminathan 		    EraseByteCount,
5252291a2b48SSukumar Swaminathan 		    ERASE_FLASH,
5253291a2b48SSukumar Swaminathan 		    0,
5254291a2b48SSukumar Swaminathan 		    DL_FROM_SLIM_OFFSET,
5255291a2b48SSukumar Swaminathan 		    AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
5256fcf3ce44SJohn Forte 
525782527734SSukumar Swaminathan 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5258291a2b48SSukumar Swaminathan 		    MBX_SUCCESS) {
5259fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5260291a2b48SSukumar Swaminathan 			    "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
5261291a2b48SSukumar Swaminathan 			    "status=%x", FileType, mb->mbxCommand,
5262291a2b48SSukumar Swaminathan 			    mb->mbxStatus);
5263fcf3ce44SJohn Forte 
5264fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
5265fcf3ce44SJohn Forte 
5266fcf3ce44SJohn Forte 			goto EXIT_ABS_DOWNLOAD;
5267fcf3ce44SJohn Forte 		}
5268fcf3ce44SJohn Forte 	}
5269fcf3ce44SJohn Forte 
5270fcf3ce44SJohn Forte 	while (DlByteCount) {
5271fcf3ce44SJohn Forte 		if (DlByteCount >= SegSize)
5272fcf3ce44SJohn Forte 			DlCount = SegSize;
5273fcf3ce44SJohn Forte 		else
5274fcf3ce44SJohn Forte 			DlCount = DlByteCount;
5275fcf3ce44SJohn Forte 
5276fcf3ce44SJohn Forte 		DlByteCount -= DlCount;
5277fcf3ce44SJohn Forte 
5278fcf3ce44SJohn Forte 		Dst = (uint32_t *)DataBuffer;
5279fcf3ce44SJohn Forte 		Src = (uint32_t *)Buffer;
5280fcf3ce44SJohn Forte 
5281fcf3ce44SJohn Forte 		for (i = 0; i < (DlCount / 4); i++) {
5282fcf3ce44SJohn Forte 			*Dst = *Src;
5283fcf3ce44SJohn Forte 			Dst++;
5284fcf3ce44SJohn Forte 			Src++;
5285fcf3ce44SJohn Forte 		}
5286fcf3ce44SJohn Forte 
5287fcf3ce44SJohn Forte 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
528882527734SSukumar Swaminathan 		    (volatile uint32_t *)((volatile char *)
528982527734SSukumar Swaminathan 		    hba->sli.sli3.slim_addr + sizeof (MAILBOX)),
529082527734SSukumar Swaminathan 		    (DlCount / sizeof (uint32_t)));
5291fcf3ce44SJohn Forte 
5292fcf3ce44SJohn Forte 		if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
529382527734SSukumar Swaminathan 			emlxs_format_load_area_cmd(mbox,
5294291a2b48SSukumar Swaminathan 			    DlToAddr,
5295291a2b48SSukumar Swaminathan 			    DlCount,
5296291a2b48SSukumar Swaminathan 			    PROGRAM_FLASH,
5297291a2b48SSukumar Swaminathan 			    (DlByteCount) ? 0 : 1,
5298291a2b48SSukumar Swaminathan 			    DL_FROM_SLIM_OFFSET,
5299291a2b48SSukumar Swaminathan 			    AreaId,
5300291a2b48SSukumar Swaminathan 			    MBX_LOAD_AREA,
5301fcf3ce44SJohn Forte 			    (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
5302fcf3ce44SJohn Forte 
530382527734SSukumar Swaminathan 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5304fcf3ce44SJohn Forte 			    MBX_SUCCESS) {
5305fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT,
5306fcf3ce44SJohn Forte 				    &emlxs_download_failed_msg,
5307291a2b48SSukumar Swaminathan 				    "%x: Could not program 2MB Flash: Mailbox "
5308291a2b48SSukumar Swaminathan 				    "cmd=%x status=%x", FileType,
5309291a2b48SSukumar Swaminathan 				    mb->mbxCommand, mb->mbxStatus);
5310fcf3ce44SJohn Forte 
5311fcf3ce44SJohn Forte 				rval = EMLXS_IMAGE_FAILED;
5312fcf3ce44SJohn Forte 
5313fcf3ce44SJohn Forte 				goto EXIT_ABS_DOWNLOAD;
5314fcf3ce44SJohn Forte 			}
5315fcf3ce44SJohn Forte 		}
5316291a2b48SSukumar Swaminathan 
5317fcf3ce44SJohn Forte 		RspProgress = mb->un.varLdArea.progress;
5318fcf3ce44SJohn Forte 
5319fcf3ce44SJohn Forte 		Buffer += DlCount;
5320fcf3ce44SJohn Forte 		DlToAddr += DlCount;
5321fcf3ce44SJohn Forte 	}
5322fcf3ce44SJohn Forte 
53234baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
532482527734SSukumar Swaminathan 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
53254baa2c25SSukumar Swaminathan 	    != DDI_FM_OK) {
53264baa2c25SSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT,
53274baa2c25SSukumar Swaminathan 		    &emlxs_invalid_access_handle_msg, NULL);
53284baa2c25SSukumar Swaminathan 
53294baa2c25SSukumar Swaminathan 		rval = EMLXS_IMAGE_FAILED;
53304baa2c25SSukumar Swaminathan 
53314baa2c25SSukumar Swaminathan 		goto EXIT_ABS_DOWNLOAD;
53324baa2c25SSukumar Swaminathan 	}
53334baa2c25SSukumar Swaminathan #endif  /* FMA_SUPPORT */
53344baa2c25SSukumar Swaminathan 
5335fcf3ce44SJohn Forte 	if (RspProgress != RSP_DOWNLOAD_DONE) {
5336fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5337291a2b48SSukumar Swaminathan 		    "%x: Failed download response received. %x", FileType,
5338291a2b48SSukumar Swaminathan 		    RspProgress);
5339fcf3ce44SJohn Forte 
5340fcf3ce44SJohn Forte 		rval = EMLXS_IMAGE_FAILED;
5341fcf3ce44SJohn Forte 
5342fcf3ce44SJohn Forte 		goto EXIT_ABS_DOWNLOAD;
5343fcf3ce44SJohn Forte 	}
5344291a2b48SSukumar Swaminathan 
5345fcf3ce44SJohn Forte 	if (ParamsChg) {
5346fcf3ce44SJohn Forte 		if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
5347fcf3ce44SJohn Forte 		    &AbsWakeUpParms)) {
5348fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5349fcf3ce44SJohn Forte 			    "%x: Unable to update parms.", FileType);
5350fcf3ce44SJohn Forte 
5351fcf3ce44SJohn Forte 			rval = EMLXS_IMAGE_FAILED;
5352fcf3ce44SJohn Forte 		}
5353fcf3ce44SJohn Forte 	}
5354291a2b48SSukumar Swaminathan 
5355fcf3ce44SJohn Forte EXIT_ABS_DOWNLOAD:
5356fcf3ce44SJohn Forte 
5357fcf3ce44SJohn Forte 	if (DataBuffer) {
5358fcf3ce44SJohn Forte 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
5359fcf3ce44SJohn Forte 	}
5360291a2b48SSukumar Swaminathan 
5361fcf3ce44SJohn Forte 	if (mbox) {
5362fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
5363fcf3ce44SJohn Forte 	}
5364291a2b48SSukumar Swaminathan 
5365fcf3ce44SJohn Forte 	return (rval);
5366fcf3ce44SJohn Forte 
536782527734SSukumar Swaminathan } /* emlxs_proc_abs_2mb() */
5368fcf3ce44SJohn Forte 
5369fcf3ce44SJohn Forte 
5370fcf3ce44SJohn Forte static void
emlxs_format_load_area_cmd(MAILBOXQ * mbq,uint32_t Base,uint32_t DlByteCount,uint32_t Function,uint32_t Complete,uint32_t DataOffset,uint32_t AreaId,uint8_t MbxCmd,uint32_t StepCmd)537182527734SSukumar Swaminathan emlxs_format_load_area_cmd(MAILBOXQ * mbq,
5372291a2b48SSukumar Swaminathan     uint32_t Base,
5373291a2b48SSukumar Swaminathan     uint32_t DlByteCount,
5374291a2b48SSukumar Swaminathan     uint32_t Function,
5375291a2b48SSukumar Swaminathan     uint32_t Complete,
5376291a2b48SSukumar Swaminathan     uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
5377fcf3ce44SJohn Forte {
537882527734SSukumar Swaminathan 	MAILBOX *mb = (MAILBOX *)mbq;
537982527734SSukumar Swaminathan 
5380fcf3ce44SJohn Forte 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
5381fcf3ce44SJohn Forte 
5382fcf3ce44SJohn Forte 	mb->mbxCommand = MbxCmd;
5383fcf3ce44SJohn Forte 	mb->mbxOwner = OWN_HOST;
5384fcf3ce44SJohn Forte 	mb->un.varLdArea.update_flash = 1;
5385fcf3ce44SJohn Forte 	mb->un.varLdArea.erase_or_prog = Function;
5386fcf3ce44SJohn Forte 	mb->un.varLdArea.dl_to_adr = Base;
5387fcf3ce44SJohn Forte 	mb->un.varLdArea.dl_len = DlByteCount;
5388fcf3ce44SJohn Forte 	mb->un.varLdArea.load_cmplt = Complete;
5389fcf3ce44SJohn Forte 	mb->un.varLdArea.method = DL_FROM_SLIM;
5390fcf3ce44SJohn Forte 	mb->un.varLdArea.area_id = AreaId;
5391fcf3ce44SJohn Forte 	mb->un.varLdArea.step = StepCmd;
5392fcf3ce44SJohn Forte 	mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
539382527734SSukumar Swaminathan 	mbq->mbox_cmpl = NULL;
5394fcf3ce44SJohn Forte 
539582527734SSukumar Swaminathan } /* emlxs_format_load_area_cmd() */
5396fcf3ce44SJohn Forte 
5397fcf3ce44SJohn Forte 
5398291a2b48SSukumar Swaminathan /* ARGSUSED */
5399fcf3ce44SJohn Forte static uint32_t
emlxs_build_parms_2mb_bwc(emlxs_hba_t * hba,PAIF_HDR AifHdr,uint32_t extType,PWAKE_UP_PARMS AbsWakeUpParms)5400291a2b48SSukumar Swaminathan emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
5401291a2b48SSukumar Swaminathan     PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
5402fcf3ce44SJohn Forte {
5403fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5404fcf3ce44SJohn Forte 	uint32_t pId[2];
5405fcf3ce44SJohn Forte 	uint32_t returnStat;
5406fcf3ce44SJohn Forte 
5407fcf3ce44SJohn Forte 	/* Read wakeup paramters */
5408fcf3ce44SJohn Forte 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
54096a573d82SSukumar Swaminathan 	    (uint32_t)CFG_DATA_NO_REGION) {
5410fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5411fcf3ce44SJohn Forte 		    "Unable to get BWC parameters.");
5412fcf3ce44SJohn Forte 		return (FALSE);
5413fcf3ce44SJohn Forte 	}
5414291a2b48SSukumar Swaminathan 
5415fcf3ce44SJohn Forte 	pId[0] = AifHdr->AVersion;
5416fcf3ce44SJohn Forte 	pId[1] = 0;
5417fcf3ce44SJohn Forte 
5418fcf3ce44SJohn Forte 	if (extType == BWCext) {
5419fcf3ce44SJohn Forte 		AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
5420fcf3ce44SJohn Forte 		AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
5421fcf3ce44SJohn Forte 		AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5422fcf3ce44SJohn Forte 		AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5423291a2b48SSukumar Swaminathan 	}
5424291a2b48SSukumar Swaminathan 
5425291a2b48SSukumar Swaminathan 	else if (extType == ALLext) {
5426fcf3ce44SJohn Forte 		if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
5427fcf3ce44SJohn Forte 			/* case of EROM inactive */
5428fcf3ce44SJohn Forte 			AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5429fcf3ce44SJohn Forte 			AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5430fcf3ce44SJohn Forte 		} else {
5431fcf3ce44SJohn Forte 			/* case of EROM active */
5432fcf3ce44SJohn Forte 			if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
5433fcf3ce44SJohn Forte 				/* same ID */
5434fcf3ce44SJohn Forte 				AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
5435fcf3ce44SJohn Forte 				AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
5436fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5437fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5438fcf3ce44SJohn Forte 			} else {
5439fcf3ce44SJohn Forte 				/* different ID */
5440fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5441fcf3ce44SJohn Forte 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5442fcf3ce44SJohn Forte 
5443291a2b48SSukumar Swaminathan 				returnStat =
5444291a2b48SSukumar Swaminathan 				    emlxs_update_exp_rom(hba, AbsWakeUpParms);
5445fcf3ce44SJohn Forte 
5446fcf3ce44SJohn Forte 				if (returnStat) {
5447fcf3ce44SJohn Forte 					AbsWakeUpParms->u0.boot_bios_wd[0] =
5448fcf3ce44SJohn Forte 					    pId[0];
5449fcf3ce44SJohn Forte 					AbsWakeUpParms->u0.boot_bios_wd[1] =
5450fcf3ce44SJohn Forte 					    pId[1];
5451fcf3ce44SJohn Forte 				}
5452fcf3ce44SJohn Forte 			}
5453fcf3ce44SJohn Forte 		}
5454fcf3ce44SJohn Forte 	}
5455291a2b48SSukumar Swaminathan 
5456fcf3ce44SJohn Forte 	return (TRUE);
5457fcf3ce44SJohn Forte 
545882527734SSukumar Swaminathan } /* emlxs_build_parms_2mb_bwc() */
5459fcf3ce44SJohn Forte 
5460fcf3ce44SJohn Forte 
5461fcf3ce44SJohn Forte extern uint32_t
emlxs_get_max_sram(emlxs_hba_t * hba,uint32_t * MaxRbusSize,uint32_t * MaxIbusSize)5462fcf3ce44SJohn Forte emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
5463fcf3ce44SJohn Forte     uint32_t *MaxIbusSize)
5464fcf3ce44SJohn Forte {
5465fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5466fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
5467fcf3ce44SJohn Forte 	MAILBOX *mb;
5468fcf3ce44SJohn Forte 	uint32_t *Uptr;
5469fcf3ce44SJohn Forte 	uint32_t rval = 0;
5470fcf3ce44SJohn Forte 
54716a573d82SSukumar Swaminathan 	if (MaxRbusSize) {
54726a573d82SSukumar Swaminathan 		*MaxRbusSize = 0;
54736a573d82SSukumar Swaminathan 	}
54746a573d82SSukumar Swaminathan 
54756a573d82SSukumar Swaminathan 	if (MaxIbusSize) {
54766a573d82SSukumar Swaminathan 		*MaxIbusSize = 0;
54776a573d82SSukumar Swaminathan 	}
54786a573d82SSukumar Swaminathan 
5479291a2b48SSukumar Swaminathan 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
5480291a2b48SSukumar Swaminathan 	    KM_NOSLEEP)) == NULL) {
5481fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5482fcf3ce44SJohn Forte 		    "Unable to allocate mailbox buffer.");
5483fcf3ce44SJohn Forte 
5484fcf3ce44SJohn Forte 		return (1);
5485fcf3ce44SJohn Forte 	}
5486291a2b48SSukumar Swaminathan 
5487fcf3ce44SJohn Forte 	mb = (MAILBOX *)mbox;
5488fcf3ce44SJohn Forte 
548982527734SSukumar Swaminathan 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
5490fcf3ce44SJohn Forte 
549182527734SSukumar Swaminathan 	if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) !=
5492291a2b48SSukumar Swaminathan 	    MBX_SUCCESS) {
5493fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5494fcf3ce44SJohn Forte 		    "Unable to get SRAM size: Mailbox cmd=%x status=%x",
5495fcf3ce44SJohn Forte 		    mb->mbxCommand, mb->mbxStatus);
5496fcf3ce44SJohn Forte 
5497fcf3ce44SJohn Forte 		rval = 1;
5498fcf3ce44SJohn Forte 
5499fcf3ce44SJohn Forte 		goto Exit_Function;
5500fcf3ce44SJohn Forte 	}
5501291a2b48SSukumar Swaminathan 
550282527734SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
550382527734SSukumar Swaminathan 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
550482527734SSukumar Swaminathan 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
550582527734SSukumar Swaminathan 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
550682527734SSukumar Swaminathan 	} else {
550782527734SSukumar Swaminathan 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
550882527734SSukumar Swaminathan 	}
5509fcf3ce44SJohn Forte 
55106a573d82SSukumar Swaminathan 	if (MaxRbusSize) {
55116a573d82SSukumar Swaminathan 		*MaxRbusSize = Uptr[0];
55126a573d82SSukumar Swaminathan 	}
55136a573d82SSukumar Swaminathan 
55146a573d82SSukumar Swaminathan 	if (MaxIbusSize) {
55156a573d82SSukumar Swaminathan 		*MaxIbusSize = Uptr[1];
55166a573d82SSukumar Swaminathan 	}
5517fcf3ce44SJohn Forte 
5518fcf3ce44SJohn Forte Exit_Function:
5519fcf3ce44SJohn Forte 
5520fcf3ce44SJohn Forte 	if (mbox) {
5521fcf3ce44SJohn Forte 		kmem_free(mbox, sizeof (MAILBOXQ));
5522fcf3ce44SJohn Forte 	}
5523291a2b48SSukumar Swaminathan 
5524b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
5525b3660a96SSukumar Swaminathan 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5526b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba,
5527b3660a96SSukumar Swaminathan 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
5528b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
5529b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
5530*8f23e9faSHans Rosenfeld 			    "get_max_sram: hdl=%p",
5531b3660a96SSukumar Swaminathan 			    hba->sli.sli4.dump_region.dma_handle);
5532b3660a96SSukumar Swaminathan 			rval = 1;
5533b3660a96SSukumar Swaminathan 		}
5534b3660a96SSukumar Swaminathan 	}
5535b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
5536b3660a96SSukumar Swaminathan 
5537fcf3ce44SJohn Forte 	return (rval);
5538fcf3ce44SJohn Forte 
553982527734SSukumar Swaminathan } /* emlxs_get_max_sram() */
5540fcf3ce44SJohn Forte 
5541fcf3ce44SJohn Forte 
5542fcf3ce44SJohn Forte static uint32_t
emlxs_kern_check(emlxs_hba_t * hba,uint32_t version)5543fcf3ce44SJohn Forte emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
5544fcf3ce44SJohn Forte {
5545fcf3ce44SJohn Forte 	uint8_t *ptr;
5546fcf3ce44SJohn Forte 	uint8_t ver;
5547fcf3ce44SJohn Forte 
5548fcf3ce44SJohn Forte 	ver = version & 0xff;
5549fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_FF;
5550fcf3ce44SJohn Forte 
5551fcf3ce44SJohn Forte 	while (*ptr) {
5552fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5553fcf3ce44SJohn Forte 			return (1);
5554fcf3ce44SJohn Forte 		}
5555fcf3ce44SJohn Forte 	}
5556fcf3ce44SJohn Forte 
5557fcf3ce44SJohn Forte 	return (0);
5558fcf3ce44SJohn Forte 
555982527734SSukumar Swaminathan } /* emlxs_kern_check() */
5560fcf3ce44SJohn Forte 
5561fcf3ce44SJohn Forte static uint32_t
emlxs_stub_check(emlxs_hba_t * hba,uint32_t version)5562fcf3ce44SJohn Forte emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
5563fcf3ce44SJohn Forte {
5564fcf3ce44SJohn Forte 	uint8_t *ptr;
5565fcf3ce44SJohn Forte 	uint8_t ver;
5566fcf3ce44SJohn Forte 
5567fcf3ce44SJohn Forte 	ver = version & 0xff;
5568fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_2;
5569fcf3ce44SJohn Forte 
5570fcf3ce44SJohn Forte 	while (*ptr) {
5571fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5572fcf3ce44SJohn Forte 			return (1);
5573fcf3ce44SJohn Forte 		}
5574fcf3ce44SJohn Forte 	}
5575fcf3ce44SJohn Forte 
5576fcf3ce44SJohn Forte 	return (0);
5577fcf3ce44SJohn Forte 
557882527734SSukumar Swaminathan } /* emlxs_stub_check() */
5579fcf3ce44SJohn Forte 
5580fcf3ce44SJohn Forte static uint32_t
emlxs_bios_check(emlxs_hba_t * hba,uint32_t version)5581fcf3ce44SJohn Forte emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
5582fcf3ce44SJohn Forte {
5583fcf3ce44SJohn Forte 	uint8_t *ptr;
5584fcf3ce44SJohn Forte 	uint8_t ver;
5585fcf3ce44SJohn Forte 
5586fcf3ce44SJohn Forte 	ver = version & 0xff;
5587fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_3;
5588fcf3ce44SJohn Forte 
5589fcf3ce44SJohn Forte 	while (*ptr) {
5590fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5591fcf3ce44SJohn Forte 			return (1);
5592fcf3ce44SJohn Forte 		}
5593fcf3ce44SJohn Forte 	}
5594fcf3ce44SJohn Forte 
5595fcf3ce44SJohn Forte 	return (0);
5596fcf3ce44SJohn Forte 
559782527734SSukumar Swaminathan } /* emlxs_bios_check() */
5598fcf3ce44SJohn Forte 
5599fcf3ce44SJohn Forte static uint32_t
emlxs_sli1_check(emlxs_hba_t * hba,uint32_t version)5600fcf3ce44SJohn Forte emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
5601fcf3ce44SJohn Forte {
5602fcf3ce44SJohn Forte 	uint8_t *ptr;
5603fcf3ce44SJohn Forte 	uint8_t ver;
5604fcf3ce44SJohn Forte 
5605fcf3ce44SJohn Forte 	ver = version & 0xff;
5606fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_6;
5607fcf3ce44SJohn Forte 
5608fcf3ce44SJohn Forte 	while (*ptr) {
5609fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5610fcf3ce44SJohn Forte 			return (1);
5611fcf3ce44SJohn Forte 		}
5612fcf3ce44SJohn Forte 	}
5613fcf3ce44SJohn Forte 
5614fcf3ce44SJohn Forte 	return (0);
5615fcf3ce44SJohn Forte 
561682527734SSukumar Swaminathan } /* emlxs_sli1_check() */
5617fcf3ce44SJohn Forte 
5618fcf3ce44SJohn Forte static uint32_t
emlxs_sli2_check(emlxs_hba_t * hba,uint32_t version)5619fcf3ce44SJohn Forte emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version)
5620fcf3ce44SJohn Forte {
5621fcf3ce44SJohn Forte 	uint8_t *ptr;
5622fcf3ce44SJohn Forte 	uint8_t ver;
5623fcf3ce44SJohn Forte 
5624fcf3ce44SJohn Forte 	ver = version & 0xff;
5625fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_7;
5626fcf3ce44SJohn Forte 
5627fcf3ce44SJohn Forte 	while (*ptr) {
5628fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5629fcf3ce44SJohn Forte 			return (1);
5630fcf3ce44SJohn Forte 		}
5631fcf3ce44SJohn Forte 	}
5632fcf3ce44SJohn Forte 
5633fcf3ce44SJohn Forte 	return (0);
5634fcf3ce44SJohn Forte 
563582527734SSukumar Swaminathan } /* emlxs_sli2_check() */
5636fcf3ce44SJohn Forte 
5637fcf3ce44SJohn Forte static uint32_t
emlxs_sli3_check(emlxs_hba_t * hba,uint32_t version)5638fcf3ce44SJohn Forte emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
5639fcf3ce44SJohn Forte {
5640fcf3ce44SJohn Forte 	uint8_t *ptr;
5641fcf3ce44SJohn Forte 	uint8_t ver;
5642fcf3ce44SJohn Forte 
5643fcf3ce44SJohn Forte 	ver = version & 0xff;
5644fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_B;
5645fcf3ce44SJohn Forte 
5646fcf3ce44SJohn Forte 	while (*ptr) {
5647fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5648fcf3ce44SJohn Forte 			return (1);
5649fcf3ce44SJohn Forte 		}
5650fcf3ce44SJohn Forte 	}
5651fcf3ce44SJohn Forte 
5652fcf3ce44SJohn Forte 	return (0);
5653fcf3ce44SJohn Forte 
565482527734SSukumar Swaminathan } /* emlxs_sli3_check() */
5655fcf3ce44SJohn Forte 
5656fcf3ce44SJohn Forte 
5657fcf3ce44SJohn Forte static uint32_t
emlxs_sli4_check(emlxs_hba_t * hba,uint32_t version)5658fcf3ce44SJohn Forte emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
5659fcf3ce44SJohn Forte {
5660fcf3ce44SJohn Forte 	uint8_t *ptr;
5661fcf3ce44SJohn Forte 	uint8_t ver;
5662fcf3ce44SJohn Forte 
5663fcf3ce44SJohn Forte 	ver = version & 0xff;
5664fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_E;
5665fcf3ce44SJohn Forte 
5666fcf3ce44SJohn Forte 	while (*ptr) {
5667fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5668fcf3ce44SJohn Forte 			return (1);
5669fcf3ce44SJohn Forte 		}
5670fcf3ce44SJohn Forte 	}
5671fcf3ce44SJohn Forte 
5672fcf3ce44SJohn Forte 	return (0);
5673fcf3ce44SJohn Forte 
567482527734SSukumar Swaminathan } /* emlxs_sli4_check() */
5675fcf3ce44SJohn Forte 
5676fcf3ce44SJohn Forte 
5677fcf3ce44SJohn Forte static uint32_t
emlxs_sbus_fcode_check(emlxs_hba_t * hba,uint32_t version)5678fcf3ce44SJohn Forte emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
5679fcf3ce44SJohn Forte {
5680fcf3ce44SJohn Forte 	uint8_t *ptr;
5681fcf3ce44SJohn Forte 	uint8_t ver;
5682fcf3ce44SJohn Forte 
5683fcf3ce44SJohn Forte 	ver = version & 0xff;
5684fcf3ce44SJohn Forte 	ptr = hba->model_info.pt_A;
5685fcf3ce44SJohn Forte 
5686fcf3ce44SJohn Forte 	while (*ptr) {
5687fcf3ce44SJohn Forte 		if (*ptr++ == ver) {
5688fcf3ce44SJohn Forte 			return (1);
5689fcf3ce44SJohn Forte 		}
5690fcf3ce44SJohn Forte 	}
5691fcf3ce44SJohn Forte 
5692fcf3ce44SJohn Forte 	return (0);
5693fcf3ce44SJohn Forte 
569482527734SSukumar Swaminathan } /* emlxs_sbus_fcode_check() */
5695fcf3ce44SJohn Forte 
5696a9800bebSGarrett D'Amore 
5697fcf3ce44SJohn Forte static uint32_t
emlxs_type_check(uint32_t type)5698fcf3ce44SJohn Forte emlxs_type_check(uint32_t type)
5699fcf3ce44SJohn Forte {
5700fcf3ce44SJohn Forte 	if (type == 0xff) {
5701fcf3ce44SJohn Forte 		return (KERNEL_CODE);
5702fcf3ce44SJohn Forte 	}
5703291a2b48SSukumar Swaminathan 
5704fcf3ce44SJohn Forte 	if (type >= MAX_PROG_TYPES) {
5705fcf3ce44SJohn Forte 		return (RESERVED_D);
5706fcf3ce44SJohn Forte 	}
5707291a2b48SSukumar Swaminathan 
5708fcf3ce44SJohn Forte 	return (type);
5709fcf3ce44SJohn Forte 
571082527734SSukumar Swaminathan } /* emlxs_type_check() */
5711fcf3ce44SJohn Forte 
5712fcf3ce44SJohn Forte 
5713291a2b48SSukumar Swaminathan extern int32_t
emlxs_boot_code_disable(emlxs_hba_t * hba)5714fcf3ce44SJohn Forte emlxs_boot_code_disable(emlxs_hba_t *hba)
5715fcf3ce44SJohn Forte {
5716fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5717fcf3ce44SJohn Forte 	PROG_ID Id;
5718fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
5719*8f23e9faSHans Rosenfeld 	uint8_t boot_state = 0;
5720fcf3ce44SJohn Forte 
5721fcf3ce44SJohn Forte 	vpd = &VPD;
5722fcf3ce44SJohn Forte 
5723*8f23e9faSHans Rosenfeld 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
5724fe199829SSukumar Swaminathan 		return (EMLXS_OP_NOT_SUP);
5725fe199829SSukumar Swaminathan 	}
5726fe199829SSukumar Swaminathan 
5727*8f23e9faSHans Rosenfeld 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5728*8f23e9faSHans Rosenfeld 		/* Read Boot Config */
5729*8f23e9faSHans Rosenfeld 		if (emlxs_get_boot_config(hba, &boot_state)) {
5730*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5731*8f23e9faSHans Rosenfeld 			    "boot_code_enable: Unable to get boot config.");
5732fcf3ce44SJohn Forte 
5733*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5734*8f23e9faSHans Rosenfeld 		}
5735291a2b48SSukumar Swaminathan 
5736*8f23e9faSHans Rosenfeld 		/* Check if boot code is already disabled */
5737*8f23e9faSHans Rosenfeld 		if (! boot_state) {
5738*8f23e9faSHans Rosenfeld 			return (FC_SUCCESS);
5739*8f23e9faSHans Rosenfeld 		}
5740291a2b48SSukumar Swaminathan 
5741*8f23e9faSHans Rosenfeld 		/* Disable boot code */
5742*8f23e9faSHans Rosenfeld 		boot_state = 0;
5743*8f23e9faSHans Rosenfeld 		if (emlxs_set_boot_config(hba, boot_state)) {
5744*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5745*8f23e9faSHans Rosenfeld 			    "boot_code_enable: Unable to set boot config.");
5746291a2b48SSukumar Swaminathan 
5747*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5748*8f23e9faSHans Rosenfeld 		}
5749fcf3ce44SJohn Forte 
5750*8f23e9faSHans Rosenfeld 		/* Now read the boot config again to verify */
5751*8f23e9faSHans Rosenfeld 		if (emlxs_get_boot_config(hba, &boot_state)) {
5752*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5753*8f23e9faSHans Rosenfeld 			    "boot_code_enable: Unable to get boot config.");
5754fcf3ce44SJohn Forte 
5755*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5756*8f23e9faSHans Rosenfeld 		}
5757*8f23e9faSHans Rosenfeld 
5758*8f23e9faSHans Rosenfeld 		/* return the result */
5759*8f23e9faSHans Rosenfeld 		return ((boot_state == 0) ? FC_SUCCESS : FC_FAILURE);
5760*8f23e9faSHans Rosenfeld 	} else {
5761*8f23e9faSHans Rosenfeld 		if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5762*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5763*8f23e9faSHans Rosenfeld 			    "boot_code_disable: Unable to read wake up parms.");
5764*8f23e9faSHans Rosenfeld 
5765*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5766*8f23e9faSHans Rosenfeld 		}
5767*8f23e9faSHans Rosenfeld 
5768*8f23e9faSHans Rosenfeld 		/* Check if boot code is already disabled */
5769*8f23e9faSHans Rosenfeld 		if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
5770*8f23e9faSHans Rosenfeld 			return (FC_SUCCESS);
5771*8f23e9faSHans Rosenfeld 		}
5772*8f23e9faSHans Rosenfeld 
5773*8f23e9faSHans Rosenfeld 		/* Make sure EROM entry has copy of boot bios entry */
5774*8f23e9faSHans Rosenfeld 		if (!(hba->model_info.chip &
5775*8f23e9faSHans Rosenfeld 		    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
5776*8f23e9faSHans Rosenfeld 		    (hba->wakeup_parms.u0.boot_bios_wd[0] !=
5777*8f23e9faSHans Rosenfeld 		    hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
5778*8f23e9faSHans Rosenfeld 		    (hba->wakeup_parms.u0.boot_bios_wd[1] !=
5779*8f23e9faSHans Rosenfeld 		    hba->wakeup_parms.u1.EROM_prog_wd[1])) {
5780*8f23e9faSHans Rosenfeld 			(void) emlxs_update_boot_wakeup_parms(hba,
5781*8f23e9faSHans Rosenfeld 			    &hba->wakeup_parms,
5782*8f23e9faSHans Rosenfeld 			    &hba->wakeup_parms.u0.boot_bios_id, 1);
5783*8f23e9faSHans Rosenfeld 		}
5784*8f23e9faSHans Rosenfeld 
5785*8f23e9faSHans Rosenfeld 		/* Update the bios id with a zero id */
5786*8f23e9faSHans Rosenfeld 		/* Don't load the EROM this time */
5787*8f23e9faSHans Rosenfeld 		bzero(&Id, sizeof (PROG_ID));
5788*8f23e9faSHans Rosenfeld 		(void) emlxs_update_boot_wakeup_parms(hba,
5789*8f23e9faSHans Rosenfeld 		    &hba->wakeup_parms, &Id, 0);
5790*8f23e9faSHans Rosenfeld 
5791*8f23e9faSHans Rosenfeld 		/* Now read the parms again to verify */
5792*8f23e9faSHans Rosenfeld 		(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5793*8f23e9faSHans Rosenfeld 		emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5794*8f23e9faSHans Rosenfeld 		    vpd->boot_version, sizeof (vpd->boot_version));
5795*8f23e9faSHans Rosenfeld 		/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5796*8f23e9faSHans Rosenfeld 
5797*8f23e9faSHans Rosenfeld 		/* Return the result */
5798*8f23e9faSHans Rosenfeld 		return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
5799*8f23e9faSHans Rosenfeld 		    FC_SUCCESS : FC_FAILURE);
5800*8f23e9faSHans Rosenfeld 	}
5801fcf3ce44SJohn Forte 
580282527734SSukumar Swaminathan } /* emlxs_boot_code_disable() */
5803fcf3ce44SJohn Forte 
5804fcf3ce44SJohn Forte 
5805291a2b48SSukumar Swaminathan extern int32_t
emlxs_boot_code_enable(emlxs_hba_t * hba)5806fcf3ce44SJohn Forte emlxs_boot_code_enable(emlxs_hba_t *hba)
5807fcf3ce44SJohn Forte {
5808fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5809fcf3ce44SJohn Forte 	emlxs_vpd_t *vpd;
5810fcf3ce44SJohn Forte 	PROG_ID load_list[MAX_LOAD_ENTRY];
5811fcf3ce44SJohn Forte 	uint32_t i;
58126a573d82SSukumar Swaminathan 	uint32_t count;
5813*8f23e9faSHans Rosenfeld 	uint8_t boot_state = 0;
5814fcf3ce44SJohn Forte 
5815fcf3ce44SJohn Forte 	vpd = &VPD;
5816fcf3ce44SJohn Forte 
5817*8f23e9faSHans Rosenfeld 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
5818fe199829SSukumar Swaminathan 		return (FC_SUCCESS);
5819fe199829SSukumar Swaminathan 	}
5820fe199829SSukumar Swaminathan 
5821*8f23e9faSHans Rosenfeld 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5822*8f23e9faSHans Rosenfeld 		/* Read Boot Config */
5823*8f23e9faSHans Rosenfeld 		if (emlxs_get_boot_config(hba, &boot_state)) {
5824*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5825*8f23e9faSHans Rosenfeld 			    "boot_code_enable: Unable to get boot config.");
5826fcf3ce44SJohn Forte 
5827*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5828*8f23e9faSHans Rosenfeld 		}
5829291a2b48SSukumar Swaminathan 
5830*8f23e9faSHans Rosenfeld 		/* Check if boot code is already enabled */
5831*8f23e9faSHans Rosenfeld 		if (boot_state) {
5832*8f23e9faSHans Rosenfeld 			return (FC_SUCCESS);
5833*8f23e9faSHans Rosenfeld 		}
5834291a2b48SSukumar Swaminathan 
5835*8f23e9faSHans Rosenfeld 		/* Enable boot code */
5836*8f23e9faSHans Rosenfeld 		boot_state = 1;
5837*8f23e9faSHans Rosenfeld 		if (emlxs_set_boot_config(hba, boot_state)) {
5838*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5839*8f23e9faSHans Rosenfeld 			    "boot_code_enable: Unable to set boot config.");
5840*8f23e9faSHans Rosenfeld 
5841*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5842fcf3ce44SJohn Forte 		}
5843291a2b48SSukumar Swaminathan 
5844*8f23e9faSHans Rosenfeld 		/* Now read the boot config again to verify */
5845*8f23e9faSHans Rosenfeld 		if (emlxs_get_boot_config(hba, &boot_state)) {
5846*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5847*8f23e9faSHans Rosenfeld 			    "boot_code_enable: Unable to get boot config.");
5848291a2b48SSukumar Swaminathan 
5849*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5850*8f23e9faSHans Rosenfeld 		}
5851*8f23e9faSHans Rosenfeld 
5852*8f23e9faSHans Rosenfeld 		/* return the result */
5853*8f23e9faSHans Rosenfeld 		return ((boot_state != 0) ? FC_SUCCESS : FC_FAILURE);
5854*8f23e9faSHans Rosenfeld 	} else {
5855*8f23e9faSHans Rosenfeld 		/* Read the wakeup parms */
5856*8f23e9faSHans Rosenfeld 		if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5857*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5858*8f23e9faSHans Rosenfeld 			    "boot_code_enable: Unable to read wake up parms.");
58596a573d82SSukumar Swaminathan 
5860291a2b48SSukumar Swaminathan 			return (FC_FAILURE);
5861fcf3ce44SJohn Forte 		}
5862291a2b48SSukumar Swaminathan 
5863*8f23e9faSHans Rosenfeld 		/* Check if boot code is already enabled */
5864*8f23e9faSHans Rosenfeld 		if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
5865*8f23e9faSHans Rosenfeld 			return (FC_SUCCESS);
5866*8f23e9faSHans Rosenfeld 		}
5867fcf3ce44SJohn Forte 
5868*8f23e9faSHans Rosenfeld 		if (!(hba->model_info.chip &
5869*8f23e9faSHans Rosenfeld 		    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
5870*8f23e9faSHans Rosenfeld 			if (hba->wakeup_parms.u1.EROM_prog_id.Type
5871*8f23e9faSHans Rosenfeld 			    != BOOT_BIOS) {
5872*8f23e9faSHans Rosenfeld 				return (EMLXS_NO_BOOT_CODE);
5873*8f23e9faSHans Rosenfeld 			}
5874*8f23e9faSHans Rosenfeld 
5875*8f23e9faSHans Rosenfeld 			/* Update the parms with the boot image id */
5876*8f23e9faSHans Rosenfeld 			/* Don't load the EROM this time */
5877*8f23e9faSHans Rosenfeld 			(void) emlxs_update_boot_wakeup_parms(hba,
5878*8f23e9faSHans Rosenfeld 			    &hba->wakeup_parms,
5879*8f23e9faSHans Rosenfeld 			    &hba->wakeup_parms.u1.EROM_prog_id, 0);
5880*8f23e9faSHans Rosenfeld 		} else { /* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
5881*8f23e9faSHans Rosenfeld 
5882*8f23e9faSHans Rosenfeld 			count = emlxs_get_load_list(hba, load_list);
5883*8f23e9faSHans Rosenfeld 
5884*8f23e9faSHans Rosenfeld 			if (!count) {
5885*8f23e9faSHans Rosenfeld 				return (FC_FAILURE);
5886*8f23e9faSHans Rosenfeld 			}
5887*8f23e9faSHans Rosenfeld 
5888*8f23e9faSHans Rosenfeld 			/* Scan load list for a boot image */
5889*8f23e9faSHans Rosenfeld 			for (i = 0; i < count; i++) {
5890*8f23e9faSHans Rosenfeld 				if (load_list[i].Type == BOOT_BIOS) {
5891*8f23e9faSHans Rosenfeld 					/*
5892*8f23e9faSHans Rosenfeld 					 * Update the parms with boot image id
5893*8f23e9faSHans Rosenfeld 					 * Don't load the EROM this time
5894*8f23e9faSHans Rosenfeld 					 */
5895*8f23e9faSHans Rosenfeld 					(void) emlxs_update_boot_wakeup_parms(
5896*8f23e9faSHans Rosenfeld 					    hba, &hba->wakeup_parms,
5897*8f23e9faSHans Rosenfeld 					    &load_list[i], 0);
5898*8f23e9faSHans Rosenfeld 
5899*8f23e9faSHans Rosenfeld 					break;
5900*8f23e9faSHans Rosenfeld 				}
5901fcf3ce44SJohn Forte 			}
5902fcf3ce44SJohn Forte 
5903*8f23e9faSHans Rosenfeld 			if (i == count) {
5904*8f23e9faSHans Rosenfeld 				return (EMLXS_NO_BOOT_CODE);
5905*8f23e9faSHans Rosenfeld 			}
5906fcf3ce44SJohn Forte 		}
5907fcf3ce44SJohn Forte 
5908*8f23e9faSHans Rosenfeld 		/* Now read the parms again to verify */
5909*8f23e9faSHans Rosenfeld 		(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5910*8f23e9faSHans Rosenfeld 		emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5911*8f23e9faSHans Rosenfeld 		    vpd->boot_version, sizeof (vpd->boot_version));
5912*8f23e9faSHans Rosenfeld 		/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5913fcf3ce44SJohn Forte 
5914*8f23e9faSHans Rosenfeld 		/* return the result */
5915*8f23e9faSHans Rosenfeld 		return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5916*8f23e9faSHans Rosenfeld 		    FC_SUCCESS : FC_FAILURE);
5917*8f23e9faSHans Rosenfeld 	}
5918fcf3ce44SJohn Forte 
591982527734SSukumar Swaminathan } /* emlxs_boot_code_enable() */
5920fcf3ce44SJohn Forte 
5921fcf3ce44SJohn Forte 
5922fcf3ce44SJohn Forte 
5923291a2b48SSukumar Swaminathan extern int32_t
emlxs_boot_code_state(emlxs_hba_t * hba)5924fcf3ce44SJohn Forte emlxs_boot_code_state(emlxs_hba_t *hba)
5925fcf3ce44SJohn Forte {
5926fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
5927*8f23e9faSHans Rosenfeld 	uint8_t boot_state = 0;
5928fcf3ce44SJohn Forte 
5929*8f23e9faSHans Rosenfeld 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
5930fe199829SSukumar Swaminathan 		return (FC_SUCCESS);
5931fe199829SSukumar Swaminathan 	}
5932fe199829SSukumar Swaminathan 
5933*8f23e9faSHans Rosenfeld 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5934*8f23e9faSHans Rosenfeld 		/* Read Boot Config */
5935*8f23e9faSHans Rosenfeld 		if (emlxs_get_boot_config(hba, &boot_state)) {
5936*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5937*8f23e9faSHans Rosenfeld 			    "boot_code_state: Unable to read boot config.");
5938fcf3ce44SJohn Forte 
5939*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5940*8f23e9faSHans Rosenfeld 		}
5941*8f23e9faSHans Rosenfeld 
5942*8f23e9faSHans Rosenfeld 		return ((boot_state != 0) ? FC_SUCCESS : FC_FAILURE);
5943*8f23e9faSHans Rosenfeld 	} else {
5944*8f23e9faSHans Rosenfeld 		/* Read the wakeup parms */
5945*8f23e9faSHans Rosenfeld 		if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
5946*8f23e9faSHans Rosenfeld 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5947*8f23e9faSHans Rosenfeld 			    "boot_code_state: Unable to read wake up parms.");
5948291a2b48SSukumar Swaminathan 
5949*8f23e9faSHans Rosenfeld 			return (FC_FAILURE);
5950*8f23e9faSHans Rosenfeld 		}
5951*8f23e9faSHans Rosenfeld 
5952*8f23e9faSHans Rosenfeld 		/* return the result */
5953*8f23e9faSHans Rosenfeld 		return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5954*8f23e9faSHans Rosenfeld 		    FC_SUCCESS : FC_FAILURE);
5955*8f23e9faSHans Rosenfeld 	}
5956fcf3ce44SJohn Forte 
595782527734SSukumar Swaminathan } /* emlxs_boot_code_state() */
5958