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