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;
508