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