1890 Updated emlxs driver from Emulex
[unleashed.git] / usr / src / uts / common / io / fibre-channel / fca / emlxs / emlxs_download.c
blob80539daed3aa8dbe06b4fa8ffbcfbdd8daf049ad
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2010 Emulex. All rights reserved.
24 * Use is subject to license terms.
28 #include <emlxs.h>
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C);
33 #define MAX_BOOTID 10
35 static uint32_t emlxs_erase_fcode_flash(emlxs_hba_t *hba);
37 static uint32_t emlxs_write_fcode_flash(emlxs_hba_t *hba,
38 PIMAGE_HDR ImageHdr, caddr_t Buffer);
40 static int32_t emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
41 uint32_t BufferSize, PAIF_HDR AifHeader);
42 static uint32_t emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
43 uint32_t Size, emlxs_fw_image_t *fw_image);
44 static void emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq,
45 uint32_t Type, uint32_t RegionId, uint32_t WordCnt,
46 uint32_t BaseAddr);
47 static uint32_t emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
48 caddr_t Buffer, uint32_t len,
49 PWAKE_UP_PARMS WakeUpParms);
50 static uint32_t emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
51 uint32_t len, uint32_t offline,
52 emlxs_fw_image_t *fw_image);
53 static uint32_t emlxs_proc_abs_2mb(emlxs_hba_t *hba,
54 caddr_t EntireBuffer, uint32_t FileType,
55 uint32_t extType);
56 static void emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base,
57 uint32_t DlByteCount, uint32_t Function,
58 uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
59 uint8_t MbxCmd, uint32_t StepCmd);
60 static uint32_t emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
61 uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
62 static uint32_t emlxs_update_exp_rom(emlxs_hba_t *hba,
63 PWAKE_UP_PARMS WakeUpParms);
64 extern uint32_t emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
65 uint32_t *MaxIbusSize);
66 static void emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base,
67 uint32_t DlByteCount, uint32_t Function,
68 uint32_t Complete, uint32_t BdeAddress,
69 uint32_t BdeSize, PROG_ID *ProgId, uint32_t keep);
70 static void emlxs_format_update_parms(MAILBOXQ *mbq,
71 PWAKE_UP_PARMS WakeUpParms);
72 static void emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
73 uint32_t region_id, uint32_t size);
74 static uint32_t emlxs_update_wakeup_parms(emlxs_hba_t *hba,
75 PWAKE_UP_PARMS AbsWakeUpParms,
76 PWAKE_UP_PARMS WakeUpParms);
77 static uint32_t emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba,
78 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id,
79 uint32_t proc_erom);
80 static uint32_t emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba,
81 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
82 static uint32_t emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba,
83 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
84 static uint32_t emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba,
85 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
86 static uint32_t emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba,
87 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
88 static uint32_t emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba,
89 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
90 static uint32_t emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
91 caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
92 uint32_t dwc_flag);
93 static uint32_t emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
95 static uint32_t emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
97 static void emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr);
99 static void emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
102 static uint32_t emlxs_type_check(uint32_t type);
104 static uint32_t emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
106 static uint32_t emlxs_stub_check(emlxs_hba_t *hba, uint32_t version);
108 static uint32_t emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version);
110 static uint32_t emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version);
112 static uint32_t emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version);
114 static uint32_t emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version);
116 static uint32_t emlxs_bios_check(emlxs_hba_t *hba, uint32_t version);
118 static uint32_t emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version);
120 static uint32_t emlxs_validate_version(emlxs_hba_t *hba,
121 emlxs_fw_file_t *file, uint32_t id, uint32_t type,
122 char *file_type);
123 static uint32_t emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
124 uint32_t len, emlxs_be_fw_image_t *fw_image);
125 static uint32_t emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
126 uint32_t len, emlxs_be_fw_image_t *fw_image);
129 static int32_t emlxs_sli4_verify_crc(emlxs_hba_t *hba,
130 emlxs_be_fw_file_t *file,
131 MAILBOXQ *mbq, MATCHMAP *mp);
132 static int32_t emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
133 emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp);
134 static int32_t emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer,
135 uint32_t len, uint32_t offline);
136 static uint32_t emlxs_be_version(caddr_t buffer, uint32_t size,
137 uint32_t *plus_flag);
138 static uint32_t emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer,
139 emlxs_fw_image_t *fw_image);
140 static uint32_t emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId);
142 static void emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *image);
144 static uint32_t emlxs_clean_flash(emlxs_hba_t *hba,
145 PWAKE_UP_PARMS OldWakeUpParms,
146 PWAKE_UP_PARMS NewWakeUpParms);
148 /* ************************************************************************* */
150 extern int32_t
151 emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
152 uint32_t offline)
154 emlxs_port_t *port = &PPORT;
155 uint32_t *Uptr;
156 IMAGE_HDR ImageHdr;
157 AIF_HDR AifHdr;
158 uint32_t ImageType;
159 WAKE_UP_PARMS WakeUpParms;
160 uint32_t rval = 0;
161 emlxs_fw_image_t fw_image;
162 uint32_t i;
164 #ifdef EMLXS_LITTLE_ENDIAN
165 caddr_t local_buffer;
166 uint32_t *bptr1;
167 uint32_t *bptr2;
168 #endif /* EMLXS_LITTLE_ENDIAN */
170 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
171 rval = emlxs_sli4_fw_download(hba, buffer, len, offline);
172 return (rval);
175 if (buffer == NULL || len == 0) {
176 return (EMLXS_IMAGE_BAD);
179 #ifdef EMLXS_LITTLE_ENDIAN
180 /* We need to swap the image buffer before we start */
183 * Use KM_SLEEP to allocate a temporary buffer
185 local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
187 /* Perform a 32 bit swap of the image */
188 bptr1 = (uint32_t *)local_buffer;
189 bptr2 = (uint32_t *)buffer;
190 for (i = 0; i < (len / 4); i++) {
191 *bptr1 = LE_SWAP32(*bptr2);
192 bptr1++;
193 bptr2++;
196 /* Replace the original buffer */
197 buffer = local_buffer;
198 #endif /* EMLXS_LITTLE_ENDIAN */
200 bzero(&fw_image, sizeof (emlxs_fw_image_t));
201 for (i = 0; i < MAX_PROG_TYPES; i++) {
202 (void) strcpy(fw_image.prog[i].label, "none");
205 /* Validate image */
206 if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) {
207 goto done;
210 /* Verify image */
211 emlxs_verify_image(hba, &fw_image);
213 /* Get image type */
214 Uptr = (uint32_t *)buffer;
215 ImageType = *Uptr;
218 * Pegasus and beyond FW download is done differently
219 * for absolute download.
222 /* Check for absolute image */
223 if ((ImageType == NOP_IMAGE_TYPE) &&
224 !(hba->model_info.chip &
225 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
227 * Because 2Mb flash download file format is different from
228 * 512k, it needs to be handled differently
230 if (rval = emlxs_start_abs_download_2mb(hba, buffer, len,
231 offline, &fw_image)) {
232 goto done;
235 /* Offline already handled */
236 offline = 0;
238 goto SLI_DOWNLOAD_EXIT;
241 /* Pre-pegasus adapters only */
243 /* Initialize headers */
244 if (ImageType == NOP_IMAGE_TYPE) {
245 bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
246 bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
247 } else { /* PRG file */
248 bzero((void *)&AifHdr, sizeof (AIF_HDR));
249 bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
252 /* Everything checks out, now to just do it */
254 if (offline) {
255 if (emlxs_offline(hba) != FC_SUCCESS) {
256 offline = 0;
258 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
259 "Unable to take adapter offline.");
261 rval = EMLXS_OFFLINE_FAILED;
262 goto SLI_DOWNLOAD_EXIT;
265 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
266 offline = 0;
268 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
269 "Unable to restart adapter.");
271 rval = EMLXS_OFFLINE_FAILED;
272 goto SLI_DOWNLOAD_EXIT;
276 /* Pre-pegasus adapters */
278 if (ImageHdr.Id.Type == SBUS_FCODE) {
279 /* Erase Flash */
280 if (emlxs_erase_fcode_flash(hba)) {
281 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
282 "Unable to erase flash.");
284 rval = EMLXS_IMAGE_FAILED;
285 goto SLI_DOWNLOAD_EXIT;
288 /* Write FCODE */
289 if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) {
290 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
291 "Unable to write flash.");
293 rval = EMLXS_IMAGE_FAILED;
294 goto SLI_DOWNLOAD_EXIT;
297 goto SLI_DOWNLOAD_EXIT;
300 /* Pre-pegasus PCI adapters */
302 if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
303 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
304 "Unable to get parameters.");
306 rval = EMLXS_IMAGE_FAILED;
308 goto SLI_DOWNLOAD_EXIT;
311 if (ImageType == NOP_IMAGE_TYPE) {
312 if (emlxs_start_abs_download(hba, &AifHdr,
313 buffer, len, &WakeUpParms)) {
314 EMLXS_MSGF(EMLXS_CONTEXT,
315 &emlxs_download_failed_msg,
316 "Failed to program flash.");
318 rval = EMLXS_IMAGE_FAILED;
320 goto SLI_DOWNLOAD_EXIT;
323 } else { /* Relative PRG file */
324 if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
325 &WakeUpParms, 0)) {
326 EMLXS_MSGF(EMLXS_CONTEXT,
327 &emlxs_download_failed_msg,
328 "Failed to program flash.");
330 rval = EMLXS_IMAGE_FAILED;
332 goto SLI_DOWNLOAD_EXIT;
336 SLI_DOWNLOAD_EXIT:
338 if (offline) {
339 (void) emlxs_online(hba);
342 if (rval == 0) {
343 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
344 "Status good.");
347 done:
349 #ifdef EMLXS_LITTLE_ENDIAN
350 /* Free the local buffer */
351 kmem_free(local_buffer, len);
352 #endif /* EMLXS_LITTLE_ENDIAN */
354 return (rval);
356 } /* emlxs_fw_download */
359 extern void
360 emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size)
362 while (size--) {
363 *buffer++ = value;
366 } /* emlxs_memset () */
369 static int32_t
370 emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer,
371 emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
373 emlxs_port_t *port = &PPORT;
374 uint8_t *image_ptr;
375 uint32_t *wptr;
376 uint8_t *payload;
377 MAILBOX4 *mb;
378 IOCTL_COMMON_FLASHROM *flashrom;
379 mbox_req_hdr_t *hdr_req;
380 uint32_t image_size;
381 uint32_t block_size;
382 uint32_t xfer_size;
383 uint32_t block_offset;
384 uint32_t count;
385 uint32_t rval = 0;
387 if (file->image_size == 0) {
388 return (0);
391 image_ptr = (uint8_t *)buffer + file->image_offset;
392 image_size = file->image_size;
393 block_size = file->block_size;
394 block_offset = 0;
395 mb = (MAILBOX4*)mbq;
397 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
398 "%s: Downloading...", file->label);
400 while (block_size) {
401 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
402 bzero((void *) mp->virt, mp->size);
404 xfer_size = min(BE_MAX_XFER_SIZE, block_size);
406 mb->un.varSLIConfig.be.embedded = 0;
407 mbq->nonembed = (void *)mp;
408 mbq->mbox_cmpl = NULL;
410 mb->mbxCommand = MBX_SLI_CONFIG;
411 mb->mbxOwner = OWN_HOST;
413 hdr_req = (mbox_req_hdr_t *)mp->virt;
414 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
415 hdr_req->opcode = COMMON_OPCODE_WRITE_FLASHROM;
416 hdr_req->timeout = 0;
417 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
418 xfer_size;
420 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
421 flashrom->params.opcode = ((block_size == xfer_size)?
422 MGMT_FLASHROM_OPCODE_FLASH:MGMT_FLASHROM_OPCODE_SAVE);
423 flashrom->params.optype = file->type;
424 flashrom->params.data_buffer_size = xfer_size;
425 flashrom->params.offset = block_offset;
427 /* Build data buffer payload */
428 payload = (uint8_t *)(&flashrom->params.data_buffer);
429 emlxs_memset(payload, 0xff, xfer_size);
431 /* Copy remaining image into payload */
432 if (image_size) {
433 count = min(image_size, xfer_size);
434 BE_SWAP32_BCOPY(image_ptr, payload, count);
435 image_size -= count;
436 image_ptr += count;
439 if (flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) {
440 wptr = (uint32_t *)&payload[(xfer_size - 12)];
442 wptr[0] = file->load_address;
443 wptr[1] = file->image_size;
444 wptr[2] = file->block_crc;
447 /* Send write request */
448 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
449 MBX_SUCCESS) {
450 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
451 "%s: Unable to download image. status=%x",
452 file->label, mb->mbxStatus);
453 rval = EMLXS_IMAGE_FAILED;
454 goto done;
457 block_size -= xfer_size;
458 block_offset += xfer_size;
461 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
462 "%s: Download complete.", file->label);
463 done:
465 return (rval);
467 } /* emlxs_sli4_flash_image() */
472 static int32_t
473 emlxs_sli4_verify_crc(emlxs_hba_t *hba,
474 emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
476 emlxs_port_t *port = &PPORT;
477 uint32_t *wptr;
478 uint8_t *payload;
479 MAILBOX4 *mb;
480 IOCTL_COMMON_FLASHROM *flashrom;
481 mbox_req_hdr_t *hdr_req;
482 uint32_t xfer_size;
483 uint32_t block_offset;
484 uint32_t rval = 0;
485 uint32_t value;
487 xfer_size = 8;
488 block_offset = file->block_size - xfer_size;
489 mb = (MAILBOX4*)mbq;
491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
492 "%s: Verifying CRC...", file->label);
494 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
495 bzero((void *) mp->virt, mp->size);
497 mb->un.varSLIConfig.be.embedded = 0;
498 mbq->nonembed = (void *)mp;
499 mbq->mbox_cmpl = NULL;
501 mb->mbxCommand = MBX_SLI_CONFIG;
502 mb->mbxOwner = OWN_HOST;
504 hdr_req = (mbox_req_hdr_t *)mp->virt;
505 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
506 hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
507 hdr_req->timeout = 0;
508 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
509 xfer_size;
511 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
512 flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
513 flashrom->params.optype = file->type;
514 flashrom->params.data_buffer_size = xfer_size;
515 flashrom->params.offset = block_offset;
517 /* Send read request */
518 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
519 MBX_SUCCESS) {
520 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
521 "%s: Unable to read CRC. status=%x",
522 file->label, mb->mbxStatus);
524 rval = 2;
525 goto done;
528 payload = (uint8_t *)(&flashrom->params.data_buffer);
529 wptr = (uint32_t *)(payload + xfer_size - 8);
531 /* Verify image size */
532 value = *wptr++;
533 if (value != file->image_size) {
534 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
535 "%s: Image size mismatch. %08x != %08x",
536 file->label, value, file->image_size);
538 rval = 1;
539 goto done;
542 /* Verify block crc */
543 value = *wptr;
544 if (value != file->block_crc) {
545 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
546 "%s: CRC mismatch. %08x != %08x",
547 file->label, value, file->block_crc);
548 rval = 1;
551 done:
553 if (rval == 0) {
554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
555 "%s: CRC verified.", file->label);
558 return (rval);
560 } /* emlxs_sli4_verify_crc() */
563 extern int32_t
564 emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw)
566 emlxs_port_t *port = &PPORT;
567 MAILBOXQ *mbq = NULL;
568 MATCHMAP *mp = NULL;
569 MAILBOX4 *mb;
570 uint32_t *wptr;
571 uint8_t *payload;
572 IOCTL_COMMON_FLASHROM *flashrom;
573 mbox_req_hdr_t *hdr_req;
574 uint32_t xfer_size;
575 uint32_t block_offset;
576 uint32_t rval = 0;
578 bzero((void *) fw, sizeof (emlxs_firmware_t));
580 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
581 KM_SLEEP)) == NULL) {
582 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
583 "read_fw_version: Unable to allocate mailbox buffer.");
585 rval = 1;
586 goto done;
589 if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
590 sizeof (IOCTL_COMMON_FLASHROM) + 32))) == NULL) {
591 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
592 "read_fw_version: Unable to allocate payload buffer.");
594 rval = EMLXS_IMAGE_FAILED;
595 goto done;
598 mb = (MAILBOX4*)mbq;
600 /* Read CRC and size */
601 xfer_size = 8;
602 block_offset = 0x140000 - xfer_size;
604 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
605 bzero((void *) mp->virt, mp->size);
607 mb->un.varSLIConfig.be.embedded = 0;
608 mbq->nonembed = (void *)mp;
609 mbq->mbox_cmpl = NULL;
611 mb->mbxCommand = MBX_SLI_CONFIG;
612 mb->mbxOwner = OWN_HOST;
614 hdr_req = (mbox_req_hdr_t *)mp->virt;
615 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
616 hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
617 hdr_req->timeout = 0;
618 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
619 xfer_size;
621 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
622 flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
623 flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
624 flashrom->params.data_buffer_size = xfer_size;
625 flashrom->params.offset = block_offset;
627 /* Send read request */
628 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
629 MBX_SUCCESS) {
630 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
631 "read_fw_version: Unable to read CRC. status=%x",
632 mb->mbxStatus);
634 rval = 1;
635 goto done;
638 payload = (uint8_t *)(&flashrom->params.data_buffer);
640 wptr = (uint32_t *)payload;
641 fw->size = *wptr++; /* image size */
642 fw->sli4 = *wptr; /* block crc */
643 fw->kern = *wptr;
644 fw->stub = *wptr;
646 /* Read version label */
647 xfer_size = 32;
648 block_offset = 0x30;
650 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
651 bzero((void *) mp->virt, mp->size);
653 mb->un.varSLIConfig.be.embedded = 0;
654 mbq->nonembed = (void *)mp;
655 mbq->mbox_cmpl = NULL;
657 mb->mbxCommand = MBX_SLI_CONFIG;
658 mb->mbxOwner = OWN_HOST;
660 hdr_req = (mbox_req_hdr_t *)mp->virt;
661 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
662 hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
663 hdr_req->timeout = 0;
664 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
665 xfer_size;
667 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
668 flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
669 flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
670 flashrom->params.data_buffer_size = xfer_size;
671 flashrom->params.offset = block_offset;
673 /* Send read request */
674 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
675 MBX_SUCCESS) {
676 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
677 "read_fw_version: Unable to read version string. status=%x",
678 mb->mbxStatus);
680 rval = 1;
681 goto done;
684 payload = (uint8_t *)(&flashrom->params.data_buffer);
685 BE_SWAP32_BCOPY(payload, (uint8_t *)fw->label, 32);
687 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
688 "FCOE FIRMWARE: size=%x version=%s (0x%08x)",
689 fw->size, fw->label, fw->sli4);
691 done:
693 if (mbq) {
694 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
697 if (mp) {
698 emlxs_mem_buf_free(hba, mp);
701 return (rval);
703 } /* emlxs_sli4_read_fw_version() */
706 static uint32_t
707 emlxs_be_version(caddr_t buffer, uint32_t size, uint32_t *plus_flag)
709 emlxs_be2_ufi_header_t *ufi_hdr;
710 char signature[BE2_SIGNATURE_SIZE];
711 uint32_t be_version = 0;
713 if (size < sizeof (emlxs_be2_ufi_header_t)) {
714 return (0);
716 ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
718 (void) sprintf(signature, "%s+", BE_SIGNATURE);
720 /* Check if this is a UFI image */
721 if (strncmp(signature, (char *)ufi_hdr->signature,
722 strlen(BE_SIGNATURE)) != 0) {
723 return (0);
726 /* Check if this is a UFI plus image */
727 if (plus_flag) {
728 /* Check if this is a UFI plus image */
729 if (strncmp(signature, (char *)ufi_hdr->signature,
730 strlen(BE_SIGNATURE)+1) == 0) {
731 *plus_flag = 1;
732 } else {
733 *plus_flag = 0;
737 if ((ufi_hdr->build[0] >= '1') && (ufi_hdr->build[0] <= '9')) {
738 be_version = ufi_hdr->build[0] - '0';
741 return (be_version);
743 } /* emlxs_be_version() */
746 static uint32_t
747 emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
748 uint32_t len, emlxs_be_fw_image_t *fw_image)
750 emlxs_port_t *port = &PPORT;
751 emlxs_be2_ufi_header_t *ufi_hdr;
752 emlxs_be2_flash_dir_t *flash_dir;
753 emlxs_be2_flash_entry_t *entry;
754 uint8_t *bptr;
755 uint32_t *wptr;
756 uint32_t i;
757 uint32_t k;
758 uint32_t mask;
759 uint32_t value;
760 uint32_t image_size;
761 emlxs_be_fw_file_t *file;
762 emlxs_be_fw_file_t *file2;
763 uint32_t ufi_plus = 0;
764 uint32_t be_version = 0;
765 uint32_t found;
767 bzero(fw_image, sizeof (emlxs_be_fw_image_t));
769 if (hba->model_info.chip != EMLXS_BE2_CHIP) {
770 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
771 "Invalid adapter model.");
772 return (EMLXS_IMAGE_INCOMPATIBLE);
775 if (len < (sizeof (emlxs_be2_ufi_header_t) +
776 sizeof (emlxs_be2_flash_dir_t))) {
777 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
778 "Image too small. (%d < %d)",
779 len, (sizeof (emlxs_be2_ufi_header_t) +
780 sizeof (emlxs_be2_flash_dir_t)));
781 return (EMLXS_IMAGE_BAD);
784 be_version = emlxs_be_version(buffer, len, &ufi_plus);
786 /* Check if this is a standard BE2 image */
787 if (be_version != 2) {
788 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
789 "Invalid image provided.");
790 return (EMLXS_IMAGE_INCOMPATIBLE);
793 ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
795 #ifdef EMLXS_BIG_ENDIAN
796 /* Big Endian Swapping */
797 /* Swap ufi header */
798 ufi_hdr->checksum =
799 SWAP32(ufi_hdr->checksum);
800 ufi_hdr->antidote =
801 SWAP32(ufi_hdr->antidote);
802 ufi_hdr->controller.vendor_id =
803 SWAP32(ufi_hdr->controller.vendor_id);
804 ufi_hdr->controller.device_id =
805 SWAP32(ufi_hdr->controller.device_id);
806 ufi_hdr->controller.sub_vendor_id =
807 SWAP32(ufi_hdr->controller.sub_vendor_id);
808 ufi_hdr->controller.sub_device_id =
809 SWAP32(ufi_hdr->controller.sub_device_id);
810 ufi_hdr->file_length =
811 SWAP32(ufi_hdr->file_length);
812 ufi_hdr->chunk_num =
813 SWAP32(ufi_hdr->chunk_num);
814 ufi_hdr->chunk_cnt =
815 SWAP32(ufi_hdr->chunk_cnt);
816 ufi_hdr->image_cnt =
817 SWAP32(ufi_hdr->image_cnt);
818 #endif /* EMLXS_BIG_ENDIAN */
820 if (len != ufi_hdr->file_length) {
821 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
822 "Invalid image size (%d != %d)",
823 len, ufi_hdr->file_length);
825 return (EMLXS_IMAGE_BAD);
828 /* Scan for flash dir signature */
829 bptr = (uint8_t *)buffer;
830 flash_dir = NULL;
831 for (i = 0; i < len; i++, bptr++) {
832 if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
833 sizeof (BE_DIR_SIGNATURE)) == 0) {
834 flash_dir = (emlxs_be2_flash_dir_t *)bptr;
835 break;
839 if (!flash_dir) {
840 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
841 "Unable to find flash directory.");
843 return (EMLXS_IMAGE_BAD);
846 #ifdef EMLXS_BIG_ENDIAN
847 /* Big Endian Swapping */
848 /* Swap flash dir */
849 flash_dir->header.format_rev =
850 SWAP32(flash_dir->header.format_rev);
851 flash_dir->header.checksum =
852 SWAP32(flash_dir->header.checksum);
853 flash_dir->header.antidote =
854 SWAP32(flash_dir->header.antidote);
855 flash_dir->header.build_num =
856 SWAP32(flash_dir->header.build_num);
857 flash_dir->header.active_entry_mask =
858 SWAP32(flash_dir->header.active_entry_mask);
859 flash_dir->header.valid_entry_mask =
860 SWAP32(flash_dir->header.valid_entry_mask);
861 flash_dir->header.orig_content_mask =
862 SWAP32(flash_dir->header.orig_content_mask);
863 flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
864 flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
865 flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
866 flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
867 flash_dir->header.resv4 = SWAP32(flash_dir->header.resv4);
869 for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
870 flash_dir->header.controller[i].vendor_id =
871 SWAP32(flash_dir->header.controller[i].vendor_id);
872 flash_dir->header.controller[i].device_id =
873 SWAP32(flash_dir->header.controller[i].device_id);
874 flash_dir->header.controller[i].sub_vendor_id =
875 SWAP32(flash_dir->header.controller[i].sub_vendor_id);
876 flash_dir->header.controller[i].sub_device_id =
877 SWAP32(flash_dir->header.controller[i].sub_device_id);
880 for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) {
882 if (!(flash_dir->header.valid_entry_mask & mask)) {
883 continue;
886 entry = &flash_dir->entry[i];
888 if ((entry->type == 0) ||
889 (entry->type == (uint32_t)-1) ||
890 (entry->image_size == 0)) {
891 continue;
894 flash_dir->entry[i].type =
895 SWAP32(flash_dir->entry[i].type);
896 flash_dir->entry[i].offset =
897 SWAP32(flash_dir->entry[i].offset);
898 flash_dir->entry[i].pad_size =
899 SWAP32(flash_dir->entry[i].pad_size);
900 flash_dir->entry[i].image_size =
901 SWAP32(flash_dir->entry[i].image_size);
902 flash_dir->entry[i].checksum =
903 SWAP32(flash_dir->entry[i].checksum);
904 flash_dir->entry[i].entry_point =
905 SWAP32(flash_dir->entry[i].entry_point);
906 flash_dir->entry[i].resv0 =
907 SWAP32(flash_dir->entry[i].resv0);
908 flash_dir->entry[i].resv1 =
909 SWAP32(flash_dir->entry[i].resv1);
911 #endif /* EMLXS_BIG_ENDIAN */
913 /* Verify adapter model */
914 found = 0;
915 for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
916 if (flash_dir->header.controller[i].device_id ==
917 hba->model_info.device_id) {
918 found = 1;
922 if (!found) {
923 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
924 "Invalid adapter device id=0x%x.",
925 hba->model_info.device_id);
926 return (EMLXS_IMAGE_INCOMPATIBLE);
929 /* Build fw_image table */
930 fw_image->be_version = 2;
931 fw_image->ufi_plus = ufi_plus;
932 for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) {
934 if (!(flash_dir->header.valid_entry_mask & mask)) {
935 continue;
938 entry = &flash_dir->entry[i];
940 if ((entry->type == 0) ||
941 (entry->type == (uint32_t)-1) ||
942 (entry->image_size == 0)) {
943 continue;
946 switch (entry->type) {
947 case BE_FLASHTYPE_REDBOOT:
948 file = &fw_image->file[REDBOOT_FLASHTYPE];
949 (void) strcpy(file->label, "REDBOOT");
950 file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
951 break;
952 case BE_FLASHTYPE_ISCSI_BIOS:
953 file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
954 (void) strcpy(file->label, "ISCSI BIOS");
955 file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
956 break;
957 case BE_FLASHTYPE_PXE_BIOS:
958 file = &fw_image->file[PXE_BIOS_FLASHTYPE];
959 (void) strcpy(file->label, "PXE BIOS");
960 file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
961 break;
962 case BE_FLASHTYPE_FCOE_BIOS:
963 file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
964 (void) strcpy(file->label, "FCOE BIOS");
965 file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
966 break;
967 case BE_FLASHTYPE_ISCSI_FIRMWARE:
968 file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
969 (void) strcpy(file->label, "ISCSI FIRMWARE");
970 file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
971 break;
972 case BE_FLASHTYPE_FCOE_FIRMWARE:
973 file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
974 (void) strcpy(file->label, "FCOE FIRMWARE");
975 file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
976 break;
977 case BE_FLASHTYPE_FCOE_BACKUP:
978 case BE_FLASHTYPE_ISCSI_BACKUP:
979 continue;
981 default:
982 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
983 "Unknown image type found. type=%x",
984 entry->type);
985 continue;
988 file->be_version = fw_image->be_version;
989 file->ufi_plus = fw_image->ufi_plus;
990 file->image_size = entry->image_size;
991 image_size = BE_SWAP32(entry->image_size);
993 if (ufi_plus) {
994 file->image_offset = entry->offset;
995 file->block_size = entry->pad_size;
996 file->block_crc = entry->checksum;
997 file->load_address = entry->entry_point;
999 } else {
1000 file->image_offset = entry->offset +
1001 sizeof (emlxs_be2_ufi_header_t);
1003 /* Get entry block size and crc */
1004 k = file->image_offset + file->image_size;
1005 k &= 0xFFFFFFFC;
1007 wptr = (uint32_t *)(buffer + k);
1008 for (; k < len; k += 4) {
1009 if (*wptr++ == image_size) {
1010 /* Calculate block_size */
1011 file->block_size = (k + 8) -
1012 file->image_offset;
1014 /* Read load_address */
1015 value = *(wptr - 2);
1016 file->load_address = BE_SWAP32(value);
1018 /* Read block_crc */
1019 value = *wptr;
1020 file->block_crc = BE_SWAP32(value);
1022 break;
1026 if (k >= len) {
1027 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1028 "%s: End of block not found. offset=%x",
1029 file->label, file->image_offset);
1031 bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1032 return (EMLXS_IMAGE_BAD);
1036 /* Make sure image will fit in block specified */
1037 if (file->image_size + 12 > file->block_size) {
1038 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1039 "%s: Image too large for block. image=%x block=%x",
1040 file->label, file->image_size, file->block_size);
1042 bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1043 return (EMLXS_IMAGE_BAD);
1046 /* Automatically create a backup file entry for firmware */
1047 if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1048 file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1050 bcopy((uint8_t *)file, (uint8_t *)file2,
1051 sizeof (emlxs_be_fw_file_t));
1052 file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1053 (void) strcpy(file2->label, "FCOE BACKUP");
1055 /* Save FCOE version info */
1056 bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1057 (void) strncpy(fw_image->fcoe_label, (char *)bptr,
1058 BE_VERSION_SIZE);
1059 fw_image->fcoe_version = file->block_crc;
1061 } else if (file->type ==
1062 MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1063 file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1065 bcopy((uint8_t *)file, (uint8_t *)file2,
1066 sizeof (emlxs_be_fw_file_t));
1067 file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1068 (void) strcpy(file2->label, "ISCSI BACKUP");
1070 /* Save ISCSI version info */
1071 bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1072 (void) strncpy(fw_image->iscsi_label, (char *)bptr,
1073 BE_VERSION_SIZE);
1074 fw_image->iscsi_version = file->block_crc;
1078 if (fw_image->fcoe_version == 0) {
1079 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1080 "Unable to find FCOE firmware component.");
1082 bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1083 return (EMLXS_IMAGE_BAD);
1086 /* Display contents */
1087 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1088 "BE2 UFI Image: %08x, %s", fw_image->fcoe_version,
1089 fw_image->fcoe_label);
1091 for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1092 file = &fw_image->file[i];
1094 if (file->image_size == 0) {
1095 continue;
1098 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1099 "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1100 "load=%x",
1101 file->label, file->be_version, (file->ufi_plus)?"+":"",
1102 file->type, file->block_size, file->image_size,
1103 file->image_offset, file->block_crc, file->load_address);
1106 return (0);
1108 } /* emlxs_be2_validate_image() */
1111 static uint32_t
1112 emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
1113 uint32_t len, emlxs_be_fw_image_t *fw_image)
1115 emlxs_port_t *port = &PPORT;
1116 emlxs_be3_ufi_header_t *ufi_hdr;
1117 emlxs_be3_flash_dir_t *flash_dir;
1118 emlxs_be3_flash_entry_t *entry;
1119 emlxs_be3_image_header_t *flash_image_hdr;
1120 emlxs_be3_image_header_t *image_hdr;
1121 uint8_t *bptr;
1122 uint32_t *wptr;
1123 uint32_t i;
1124 uint32_t value;
1125 emlxs_be_fw_file_t *file;
1126 emlxs_be_fw_file_t *file2;
1127 uint32_t ufi_plus = 0;
1128 uint32_t be_version = 0;
1129 uint32_t found;
1131 bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1133 if (hba->model_info.chip != EMLXS_BE3_CHIP) {
1134 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1135 "Invalid adapter model.");
1136 return (EMLXS_IMAGE_INCOMPATIBLE);
1139 if (len < (sizeof (emlxs_be3_ufi_header_t) +
1140 sizeof (emlxs_be3_flash_dir_t))) {
1141 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1142 "Image too small. (%d < %d)",
1143 len, (sizeof (emlxs_be3_ufi_header_t) +
1144 sizeof (emlxs_be3_flash_dir_t)));
1145 return (EMLXS_IMAGE_BAD);
1148 be_version = emlxs_be_version(buffer, len, &ufi_plus);
1150 /* Check if this is a standard BE3 image */
1151 if (be_version != 3) {
1152 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1153 "Invalid image provided.");
1154 return (EMLXS_IMAGE_INCOMPATIBLE);
1157 ufi_hdr = (emlxs_be3_ufi_header_t *)buffer;
1159 #ifdef EMLXS_BIG_ENDIAN
1160 /* Big Endian Swapping */
1161 /* Swap ufi header */
1162 ufi_hdr->ufi_version =
1163 SWAP32(ufi_hdr->ufi_version);
1164 ufi_hdr->file_length =
1165 SWAP32(ufi_hdr->file_length);
1166 ufi_hdr->checksum =
1167 SWAP32(ufi_hdr->checksum);
1168 ufi_hdr->antidote =
1169 SWAP32(ufi_hdr->antidote);
1170 ufi_hdr->image_cnt =
1171 SWAP32(ufi_hdr->image_cnt);
1172 #endif /* EMLXS_BIG_ENDIAN */
1174 if (len != ufi_hdr->file_length) {
1175 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1176 "Invalid image size (%d != %d)",
1177 len, ufi_hdr->file_length);
1179 return (EMLXS_IMAGE_BAD);
1182 flash_image_hdr = NULL;
1183 image_hdr = (emlxs_be3_image_header_t *)(buffer +
1184 sizeof (emlxs_be3_ufi_header_t));
1185 for (i = 0; i < ufi_hdr->image_cnt; i++, image_hdr++) {
1186 #ifdef EMLXS_BIG_ENDIAN
1187 image_hdr->id = SWAP32(image_hdr->id);
1188 image_hdr->offset = SWAP32(image_hdr->offset);
1189 image_hdr->length = SWAP32(image_hdr->length);
1190 image_hdr->checksum = SWAP32(image_hdr->checksum);
1191 #endif /* EMLXS_BIG_ENDIAN */
1193 if (image_hdr->id == UFI_BE3_FLASH_ID) {
1194 flash_image_hdr = image_hdr;
1198 if (!flash_image_hdr) {
1199 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1200 "No flash image found.");
1202 return (EMLXS_IMAGE_BAD);
1205 /* Scan for flash dir signature */
1206 bptr = (uint8_t *)buffer + flash_image_hdr->offset;
1207 flash_dir = NULL;
1208 for (i = 0; i < flash_image_hdr->length; i++, bptr++) {
1209 if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
1210 sizeof (BE_DIR_SIGNATURE)) == 0) {
1211 flash_dir = (emlxs_be3_flash_dir_t *)bptr;
1212 break;
1216 if (!flash_dir) {
1217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1218 "Unable to find flash directory.");
1220 return (EMLXS_IMAGE_BAD);
1223 #ifdef EMLXS_BIG_ENDIAN
1224 /* Big Endian Swapping */
1225 /* Swap flash dir */
1226 flash_dir->header.format_rev =
1227 SWAP32(flash_dir->header.format_rev);
1228 flash_dir->header.checksum =
1229 SWAP32(flash_dir->header.checksum);
1230 flash_dir->header.antidote =
1231 SWAP32(flash_dir->header.antidote);
1232 flash_dir->header.entry_count =
1233 SWAP32(flash_dir->header.entry_count);
1234 flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
1235 flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
1236 flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
1237 flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
1239 for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1240 flash_dir->header.controller[i].vendor_id =
1241 SWAP32(flash_dir->header.controller[i].vendor_id);
1242 flash_dir->header.controller[i].device_id =
1243 SWAP32(flash_dir->header.controller[i].device_id);
1244 flash_dir->header.controller[i].sub_vendor_id =
1245 SWAP32(flash_dir->header.controller[i].sub_vendor_id);
1246 flash_dir->header.controller[i].sub_device_id =
1247 SWAP32(flash_dir->header.controller[i].sub_device_id);
1250 for (i = 0; i < flash_dir->header.entry_count; i++) {
1251 entry = &flash_dir->entry[i];
1253 if ((entry->type == 0) ||
1254 (entry->type == (uint32_t)-1) ||
1255 (entry->image_size == 0)) {
1256 continue;
1259 flash_dir->entry[i].type =
1260 SWAP32(flash_dir->entry[i].type);
1261 flash_dir->entry[i].offset =
1262 SWAP32(flash_dir->entry[i].offset);
1263 flash_dir->entry[i].block_size =
1264 SWAP32(flash_dir->entry[i].block_size);
1265 flash_dir->entry[i].image_size =
1266 SWAP32(flash_dir->entry[i].image_size);
1267 flash_dir->entry[i].checksum =
1268 SWAP32(flash_dir->entry[i].checksum);
1269 flash_dir->entry[i].entry_point =
1270 SWAP32(flash_dir->entry[i].entry_point);
1271 flash_dir->entry[i].resv0 =
1272 SWAP32(flash_dir->entry[i].resv0);
1273 flash_dir->entry[i].resv1 =
1274 SWAP32(flash_dir->entry[i].resv1);
1276 #endif /* EMLXS_BIG_ENDIAN */
1278 /* Verify image checksum */
1279 if (flash_dir->header.checksum != flash_image_hdr->checksum) {
1280 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1281 "Invalid flash directory checksum. (%x != %x)\n",
1282 flash_dir->header.checksum, flash_image_hdr->checksum);
1283 return (EMLXS_IMAGE_BAD);
1286 /* Verify adapter model */
1287 found = 0;
1288 for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1289 if (flash_dir->header.controller[i].device_id ==
1290 hba->model_info.device_id) {
1291 found = 1;
1295 if (!found) {
1296 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1297 "Invalid adapter device id=0x%x.",
1298 hba->model_info.device_id);
1299 return (EMLXS_IMAGE_INCOMPATIBLE);
1302 /* Build fw_image table */
1303 fw_image->be_version = 3;
1304 fw_image->ufi_plus = ufi_plus;
1305 for (i = 0; i < flash_dir->header.entry_count; i++) {
1306 entry = &flash_dir->entry[i];
1308 if ((entry->type == 0) ||
1309 (entry->type == (uint32_t)-1) ||
1310 (entry->image_size == 0)) {
1311 continue;
1314 switch (entry->type) {
1315 case BE_FLASHTYPE_REDBOOT:
1316 file = &fw_image->file[REDBOOT_FLASHTYPE];
1317 (void) strcpy(file->label, "REDBOOT");
1318 file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
1319 break;
1320 case BE_FLASHTYPE_ISCSI_BIOS:
1321 file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1322 (void) strcpy(file->label, "ISCSI BIOS");
1323 file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
1324 break;
1325 case BE_FLASHTYPE_PXE_BIOS:
1326 file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1327 (void) strcpy(file->label, "PXE BIOS");
1328 file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
1329 break;
1330 case BE_FLASHTYPE_FCOE_BIOS:
1331 file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1332 (void) strcpy(file->label, "FCOE BIOS");
1333 file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
1334 break;
1335 case BE_FLASHTYPE_ISCSI_FIRMWARE:
1336 file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1337 (void) strcpy(file->label, "ISCSI FIRMWARE");
1338 file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
1339 break;
1340 case BE_FLASHTYPE_FCOE_FIRMWARE:
1341 file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1342 (void) strcpy(file->label, "FCOE FIRMWARE");
1343 file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
1344 break;
1345 case BE_FLASHTYPE_NCSI_FIRMWARE:
1346 file = &fw_image->file[NCSI_FIRMWARE_FLASHTYPE];
1347 (void) strcpy(file->label, "NCSI FIRMWARE");
1348 file->type = MGMT_FLASHROM_OPTYPE_NCSI_FIRMWARE;
1349 break;
1350 case BE_FLASHTYPE_FLASH_ISM:
1351 case BE_FLASHTYPE_FCOE_BACKUP:
1352 case BE_FLASHTYPE_ISCSI_BACKUP:
1353 continue;
1355 default:
1356 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1357 "Unknown image type found. type=%x",
1358 entry->type);
1359 continue;
1362 file->be_version = fw_image->be_version;
1363 file->ufi_plus = fw_image->ufi_plus;
1364 file->image_size = entry->image_size;
1366 if (ufi_plus) {
1367 file->image_offset = entry->offset;
1368 file->block_size = entry->block_size;
1369 file->block_crc = entry->checksum;
1370 file->load_address = entry->entry_point;
1371 } else {
1372 file->image_offset = entry->offset +
1373 flash_image_hdr->offset;
1374 file->block_size = entry->block_size;
1376 wptr = (uint32_t *)(buffer + file->image_offset +
1377 file->block_size);
1379 /* Read load address */
1380 value = *(wptr - 3);
1381 file->load_address = BE_SWAP32(value);
1383 /* Read block_crc */
1384 value = *(wptr - 1);
1385 file->block_crc = BE_SWAP32(value);
1388 /* Make sure image will fit in block specified */
1389 if (file->image_size + 12 > file->block_size) {
1390 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1391 "%s: Image too large for block. image=%x block=%x",
1392 file->label, file->image_size, file->block_size);
1394 bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1395 return (EMLXS_IMAGE_BAD);
1398 /* Automatically create a backup file entry for firmware */
1399 if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1400 file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1402 bcopy((uint8_t *)file, (uint8_t *)file2,
1403 sizeof (emlxs_be_fw_file_t));
1404 file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1405 (void) strcpy(file2->label, "FCOE BACKUP");
1407 /* Save FCOE version info */
1408 bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1409 (void) strncpy(fw_image->fcoe_label, (char *)bptr,
1410 BE_VERSION_SIZE);
1411 fw_image->fcoe_version = file->block_crc;
1413 } else if (file->type ==
1414 MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1415 file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1417 bcopy((uint8_t *)file, (uint8_t *)file2,
1418 sizeof (emlxs_be_fw_file_t));
1419 file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1420 (void) strcpy(file2->label, "ISCSI BACKUP");
1422 /* Save ISCSI version info */
1423 bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1424 (void) strncpy(fw_image->iscsi_label, (char *)bptr,
1425 BE_VERSION_SIZE);
1426 fw_image->iscsi_version = file->block_crc;
1430 if (fw_image->fcoe_version == 0) {
1431 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1432 "Unable to find FCOE firmware component.");
1434 bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1435 return (EMLXS_IMAGE_BAD);
1438 /* Display contents */
1439 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1440 "BE3 UFI Image: %08x, %s", fw_image->fcoe_version,
1441 fw_image->fcoe_label);
1443 for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1444 file = &fw_image->file[i];
1446 if (file->image_size == 0) {
1447 continue;
1450 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1451 "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1452 "load=%x",
1453 file->label, file->be_version, (file->ufi_plus)? "+":"",
1454 file->type, file->block_size, file->image_size,
1455 file->image_offset, file->block_crc, file->load_address);
1458 return (0);
1460 } /* emlxs_be3_validate_image() */
1463 static int32_t
1464 emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
1465 uint32_t offline)
1467 emlxs_port_t *port = &PPORT;
1468 uint32_t i;
1469 uint32_t update = 0;
1470 uint32_t rval = 0;
1471 MAILBOXQ *mbq = NULL;
1472 MATCHMAP *mp = NULL;
1473 emlxs_be_fw_image_t fw_image;
1474 emlxs_be_fw_file_t *file;
1475 uint32_t be_version;
1477 /* For now we will not take the driver offline during a download */
1478 offline = 0;
1480 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
1481 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1482 "Invalid sli_mode. mode=%d", hba->sli_mode);
1483 return (EMLXS_IMAGE_INCOMPATIBLE);
1486 if (buffer == NULL || len == 0) {
1487 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1488 "Empty buffer provided. buf=%p size=%d", buffer, len);
1489 return (EMLXS_IMAGE_BAD);
1492 be_version = emlxs_be_version(buffer, len, 0);
1494 switch (be_version) {
1495 case 0:
1496 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1497 "Invalid image provided. Non-UFI format.");
1498 return (EMLXS_IMAGE_INCOMPATIBLE);
1499 case 2:
1500 rval = emlxs_be2_validate_image(hba, buffer, len, &fw_image);
1501 if (rval) {
1502 return (rval);
1504 break;
1505 case 3:
1506 rval = emlxs_be3_validate_image(hba, buffer, len, &fw_image);
1507 if (rval) {
1508 return (rval);
1510 break;
1511 default:
1512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1513 "Invalid image provided. Unknown BE version. (%x)",
1514 be_version);
1515 return (EMLXS_IMAGE_INCOMPATIBLE);
1518 /* Allocate resources */
1520 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1521 KM_SLEEP)) == NULL) {
1522 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1523 "Unable to allocate mailbox buffer.");
1525 offline = 0;
1526 rval = EMLXS_IMAGE_FAILED;
1527 goto done;
1530 if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
1531 sizeof (IOCTL_COMMON_FLASHROM) + BE_MAX_XFER_SIZE))) == NULL) {
1532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1533 "Unable to allocate flash buffer.");
1535 offline = 0;
1536 rval = EMLXS_IMAGE_FAILED;
1537 goto done;
1540 /* Check if update is required */
1541 for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1542 file = &fw_image.file[i];
1544 if (file->image_size == 0) {
1545 continue;
1548 rval = emlxs_sli4_verify_crc(hba, file, mbq, mp);
1550 if (rval == 0) {
1551 /* Do not update */
1552 file->image_size = 0;
1553 continue;
1556 update++;
1559 if (!update) {
1560 offline = 0;
1561 rval = 0;
1562 goto done;
1566 * Everything checks out, now to just do it
1568 if (offline) {
1569 if (emlxs_offline(hba) != FC_SUCCESS) {
1571 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1572 "Unable to take adapter offline.");
1574 offline = 0;
1575 rval = EMLXS_OFFLINE_FAILED;
1576 goto done;
1580 /* Download entries which require update */
1581 for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1582 file = &fw_image.file[i];
1584 if (file->image_size == 0) {
1585 continue;
1588 rval = emlxs_sli4_flash_image(hba, buffer, file, mbq, mp);
1590 if (rval != 0) {
1591 goto done;
1595 done:
1596 if (mbq) {
1597 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
1600 if (mp) {
1601 emlxs_mem_buf_free(hba, mp);
1604 if (offline) {
1605 (void) emlxs_online(hba);
1608 if (rval == 0) {
1609 if (update) {
1610 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1611 "Status good.");
1613 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
1614 "Please reboot system or power cycle adapter "
1615 "to activate new firmware: %s",
1616 fw_image.fcoe_label);
1618 } else {
1619 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1620 "No firmware update required.");
1624 return (rval);
1626 } /* emlxs_sli4_fw_download() */
1629 extern int32_t
1630 emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer,
1631 uint32_t len)
1633 emlxs_port_t *port = &PPORT;
1634 MAILBOXQ *mbox = NULL;
1635 MAILBOX *mb;
1636 uint32_t rval = 0;
1637 uint32_t region_id;
1638 uint32_t id;
1639 #ifdef EMLXS_BIG_ENDIAN
1640 caddr_t local_buffer;
1641 uint32_t *bptr1;
1642 uint32_t *bptr2;
1643 uint32_t i;
1644 #endif /* EMLXS_BIG_ENDIAN */
1646 if (buffer == NULL || len == 0) {
1647 return (EMLXS_IMAGE_BAD);
1650 #ifdef EMLXS_BIG_ENDIAN
1651 /* We need to swap the image buffer before we start */
1654 * Use KM_SLEEP to allocate a temporary buffer
1656 local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
1658 /* Perform a 32 bit swap of the image */
1659 bptr1 = (uint32_t *)local_buffer;
1660 bptr2 = (uint32_t *)buffer;
1662 for (i = 0; i < (len / 4); i++) {
1663 *bptr1 = SWAP32(*bptr2);
1664 bptr1++;
1665 bptr2++;
1668 /* Replace the original buffer */
1669 buffer = local_buffer;
1671 #endif /* EMLXS_BIG_ENDIAN */
1673 if (len > 128) {
1674 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1675 "Invalid image length: 0x%x > 128", len);
1677 return (EMLXS_IMAGE_BAD);
1680 /* Check the region number */
1681 if ((region > 2) && (region != 0xff)) {
1682 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1683 "Invalid region id: 0x%x", region);
1685 return (EMLXS_IMAGE_BAD);
1689 /* Check the image vendor id */
1690 id = *(int32_t *)buffer;
1691 if ((id & 0xffff) != 0x10df) {
1692 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1693 "Invalid image id: 0x%x", id);
1695 return (EMLXS_IMAGE_BAD);
1698 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1699 KM_NOSLEEP)) == NULL) {
1700 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1701 "Unable to allocate mailbox buffer.");
1703 rval = 1;
1705 goto done;
1708 mb = (MAILBOX *)mbox;
1711 * Everything checks out, now to just do it
1713 if (emlxs_offline(hba) != FC_SUCCESS) {
1714 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1715 "Unable to take HBA offline.");
1717 rval = EMLXS_OFFLINE_FAILED;
1719 goto done;
1722 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
1723 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1724 "Unable to restart adapter.");
1726 rval = EMLXS_OFFLINE_FAILED;
1728 goto done;
1731 /* Check if default region is requested */
1732 if (region == 0xff) {
1734 * Sun-branded Helios and Zypher have different
1735 * default PCI region
1737 if ((hba->model_info.flags & EMLXS_SUN_BRANDED) &&
1738 (hba->model_info.chip &
1739 (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
1740 region = 2;
1741 } else {
1742 region = 0;
1746 /* Set region id based on PCI region requested */
1747 region_id = DEF_PCI_CFG_REGION_ID + region;
1749 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1750 "PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
1751 region_id, id, len);
1753 /* Copy the data buffer to SLIM */
1754 WRITE_SLIM_COPY(hba, (uint32_t *)buffer,
1755 (volatile uint32_t *)((volatile char *)hba->sli.sli3.slim_addr +
1756 sizeof (MAILBOX)), (len / sizeof (uint32_t)));
1758 #ifdef FMA_SUPPORT
1759 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
1760 != DDI_FM_OK) {
1761 EMLXS_MSGF(EMLXS_CONTEXT,
1762 &emlxs_invalid_access_handle_msg, NULL);
1763 rval = 1;
1765 #endif /* FMA_SUPPORT */
1767 emlxs_format_update_pci_cfg(hba, mbox, region_id, len);
1769 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
1770 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1771 "Unable to update PCI configuration: Mailbox cmd=%x "
1772 "status=%x info=%d", mb->mbxCommand, mb->mbxStatus,
1773 mb->un.varUpdateCfg.rsp_info);
1775 rval = 1;
1778 (void) emlxs_online(hba);
1780 if (rval == 0) {
1781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1782 "Status good.");
1785 done:
1787 if (mbox) {
1788 kmem_free(mbox, sizeof (MAILBOXQ));
1791 #ifdef EMLXS_BIG_ENDIAN
1792 /* Free the local buffer */
1793 kmem_free(local_buffer, len);
1794 #endif /* EMLXS_BIG_ENDIAN */
1796 return (rval);
1798 } /* emlxs_cfl_download */
1801 static uint32_t
1802 emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr)
1804 uint32_t Temp;
1805 uint32_t CkSum;
1807 EndAddr++;
1808 CkSum = SLI_CKSUM_SEED;
1810 CkSum = (CkSum >> 1) | (CkSum << 31);
1811 while (StartAddr != EndAddr) {
1812 CkSum = (CkSum << 1) | (CkSum >> 31);
1813 Temp = *StartAddr;
1815 CkSum ^= Temp;
1816 StartAddr++;
1819 return (CkSum << 1) | (CkSum >> 31);
1821 } /* emlxs_valid_cksum() */
1824 static void
1825 emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr)
1827 emlxs_port_t *port = &PPORT;
1829 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: ");
1830 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1831 "AIF Header: compress_br = 0x%x", AifHdr->CompressBr);
1832 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1833 "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr);
1834 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1835 "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr);
1836 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1837 "AIF Header: entry_br = 0x%x", AifHdr->EntryBr);
1838 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1839 "AIF Header: area_id = 0x%x", AifHdr->Area_ID);
1840 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1841 "AIF Header: rosize = 0x%x", AifHdr->RoSize);
1842 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1843 "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize);
1844 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1845 "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize);
1846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1847 "AIF Header: dbgtype = 0x%x", AifHdr->DbgType);
1848 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1849 "AIF Header: imagebase = 0x%x", AifHdr->ImageBase);
1850 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1851 "AIF Header: area_size = 0x%x", AifHdr->Area_Size);
1852 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1853 "AIF Header: address_mode = 0x%x", AifHdr->AddressMode);
1854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1855 "AIF Header: database = 0x%x", AifHdr->DataBase);
1856 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1857 "AIF Header: aversion = 0x%x", AifHdr->AVersion);
1858 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1859 "AIF Header: spare2 = 0x%x", AifHdr->Spare2);
1860 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1861 "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi);
1862 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1863 "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]);
1864 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1865 "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]);
1867 } /* emlxs_disp_aif_header() */
1871 static void
1872 emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image)
1874 emlxs_port_t *port = &PPORT;
1876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: ");
1877 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1878 "Img Header: BlockSize = 0x%x", image->BlockSize);
1879 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1880 "Img Header: PROG_ID Type = 0x%x", image->Id.Type);
1881 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1882 "Img Header: PROG_ID Id = 0x%x", image->Id.Id);
1883 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1884 "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver);
1885 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1886 "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev);
1887 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1888 "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp);
1889 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1890 "Img Header: Flags = 0x%x", image->Flags);
1891 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1892 "Img Header: EntryAdr = 0x%x", image->EntryAdr);
1893 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1894 "Img Header: InitAdr = 0x%x", image->InitAdr);
1895 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1896 "Img Header: ExitAdr = 0x%x", image->ExitAdr);
1897 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1898 "Img Header: ImageBase = 0x%x", image->ImageBase);
1899 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1900 "Img Header: ImageSize = 0x%x", image->ImageSize);
1901 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1902 "Img Header: ZinitSize = 0x%x", image->ZinitSize);
1903 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1904 "Img Header: RelocSize = 0x%x", image->RelocSize);
1905 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1906 "Img Header: HdrCks = 0x%x", image->HdrCks);
1908 } /* emlxs_dump_image_header() */
1911 static void
1912 emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t Type,
1913 uint32_t RegionId, uint32_t WordCount, uint32_t BaseAddr)
1916 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1917 MAILBOX4 *mb = (MAILBOX4 *)mbq;
1919 /* Clear the local dump_region */
1920 bzero(hba->sli.sli4.dump_region.virt,
1921 hba->sli.sli4.dump_region.size);
1923 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1925 mb->mbxCommand = MBX_DUMP_MEMORY;
1926 mb->un.varDmp4.type = Type;
1927 mb->un.varDmp4.entry_index = BaseAddr;
1928 mb->un.varDmp4.region_id = RegionId;
1930 mb->un.varDmp4.available_cnt = min((WordCount*4),
1931 hba->sli.sli4.dump_region.size);
1932 mb->un.varDmp4.addrHigh =
1933 PADDR_HI(hba->sli.sli4.dump_region.phys);
1934 mb->un.varDmp4.addrLow =
1935 PADDR_LO(hba->sli.sli4.dump_region.phys);
1936 mb->un.varDmp4.rsp_cnt = 0;
1938 mb->mbxOwner = OWN_HOST;
1940 } else {
1941 MAILBOX *mb = (MAILBOX *)mbq;
1943 bzero((void *)mb, MAILBOX_CMD_BSIZE);
1945 mb->mbxCommand = MBX_DUMP_MEMORY;
1946 mb->un.varDmp.type = Type;
1947 mb->un.varDmp.region_id = RegionId;
1948 mb->un.varDmp.word_cnt = WordCount;
1949 mb->un.varDmp.base_adr = BaseAddr;
1950 mb->mbxOwner = OWN_HOST;
1953 mbq->mbox_cmpl = NULL; /* no cmpl needed */
1955 return;
1957 } /* emlxs_format_dump() */
1960 /* ARGSUSED */
1961 static uint32_t
1962 emlxs_start_abs_download(emlxs_hba_t *hba,
1963 PAIF_HDR AifHdr,
1964 caddr_t Buffer,
1965 uint32_t len,
1966 PWAKE_UP_PARMS WakeUpParms)
1968 emlxs_port_t *port = &PPORT;
1969 uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
1970 uint32_t *Src;
1971 uint32_t *Dst;
1972 caddr_t DataBuffer = NULL;
1973 MAILBOXQ *mbox;
1974 MAILBOX *mb;
1975 uint32_t rval = 1;
1976 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
1977 uint32_t DlToAddr = AifHdr->ImageBase;
1978 uint32_t DlCount;
1979 uint32_t i;
1980 WAKE_UP_PARMS AbsWakeUpParms;
1981 int32_t AbsChangeParams;
1983 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1984 "Performing absolute download...");
1986 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
1987 KM_NOSLEEP)) == NULL) {
1988 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1989 "Unable to allocate data buffer.");
1991 return (rval);
1994 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1995 KM_NOSLEEP)) == NULL) {
1996 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1997 "Unable to allocate mailbox buffer.");
1999 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2001 return (rval);
2003 mb = (MAILBOX *)mbox;
2005 AbsChangeParams = emlxs_build_parms(Buffer,
2006 &AbsWakeUpParms, len, AifHdr);
2008 Buffer += sizeof (AIF_HDR);
2010 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Erasing flash...");
2012 if (AifHdr->ImageBase == 0x20000) {
2013 /* DWC File */
2014 emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0,
2015 0, 0, NULL, 0);
2016 } else {
2017 emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount,
2018 ERASE_FLASH, 0, 0, 0, NULL, 0);
2021 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2022 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2023 "Unable to erase Flash: Mailbox cmd=%x status=%x",
2024 mb->mbxCommand, mb->mbxStatus);
2026 rval = 1;
2028 goto EXIT_ABS_DOWNLOAD;
2031 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2032 "Programming flash...");
2034 while (DlByteCount) {
2036 if (DlByteCount > SegSize) {
2037 DlCount = SegSize;
2038 } else {
2039 DlCount = DlByteCount;
2041 DlByteCount -= DlCount;
2043 Dst = (uint32_t *)DataBuffer;
2044 Src = (uint32_t *)Buffer;
2046 for (i = 0; i < (DlCount / 4); i++) {
2047 *Dst = *Src;
2048 Dst++;
2049 Src++;
2052 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
2053 (volatile uint32_t *)
2054 ((volatile char *)hba->sli.sli3.slim_addr +
2055 sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2057 emlxs_format_prog_flash(mbox, DlToAddr, DlCount,
2058 PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL, 0);
2060 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2061 MBX_SUCCESS) {
2062 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2063 "Unable to program Flash: Mailbox cmd=%x status=%x",
2064 mb->mbxCommand, mb->mbxStatus);
2066 rval = 1;
2068 goto EXIT_ABS_DOWNLOAD;
2071 Buffer += DlCount;
2072 DlToAddr += DlCount;
2075 #ifdef FMA_SUPPORT
2076 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2077 != DDI_FM_OK) {
2078 EMLXS_MSGF(EMLXS_CONTEXT,
2079 &emlxs_invalid_access_handle_msg, NULL);
2081 rval = 1;
2083 goto EXIT_ABS_DOWNLOAD;
2085 #endif /* FMA_SUPPORT */
2087 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
2089 if (AbsChangeParams) {
2090 rval =
2091 emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
2092 WakeUpParms);
2095 EXIT_ABS_DOWNLOAD:
2096 if (DataBuffer) {
2097 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2100 if (mbox) {
2101 kmem_free(mbox, sizeof (MAILBOXQ));
2104 return (rval);
2106 } /* emlxs_start_abs_download() */
2109 /* ARGSUSED */
2110 static void
2111 emlxs_format_prog_flash(MAILBOXQ *mbq,
2112 uint32_t Base,
2113 uint32_t DlByteCount,
2114 uint32_t Function,
2115 uint32_t Complete,
2116 uint32_t BdeAddress,
2117 uint32_t BdeSize,
2118 PROG_ID *ProgId,
2119 uint32_t keep)
2121 MAILBOX *mb = (MAILBOX *)mbq;
2123 bzero((void *)mb, MAILBOX_CMD_BSIZE);
2125 if (ProgId) {
2126 mb->mbxCommand = MBX_DOWN_LOAD;
2127 } else {
2128 mb->mbxCommand = MBX_LOAD_SM;
2131 mb->un.varLdSM.load_cmplt = Complete;
2132 mb->un.varLdSM.method = DL_FROM_SLIM;
2133 mb->un.varLdSM.update_flash = 1;
2134 mb->un.varLdSM.erase_or_prog = Function;
2135 mb->un.varLdSM.dl_to_adr = Base;
2136 mb->un.varLdSM.dl_len = DlByteCount;
2137 mb->un.varLdSM.keep = keep;
2139 if (BdeSize) {
2140 mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
2141 } else if (ProgId) {
2142 mb->un.varLdSM.un.prog_id = *ProgId;
2143 } else {
2144 mb->un.varLdSM.un.dl_from_slim_offset = 0;
2147 mb->mbxOwner = OWN_HOST;
2148 mbq->mbox_cmpl = NULL;
2150 } /* emlxs_format_prog_flash() */
2153 static void
2154 emlxs_format_update_parms(MAILBOXQ *mbq, PWAKE_UP_PARMS WakeUpParms)
2156 MAILBOX *mb = (MAILBOX *)mbq;
2158 bzero((void *)mb, MAILBOX_CMD_BSIZE);
2160 mb->mbxCommand = MBX_UPDATE_CFG;
2161 mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2162 mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID;
2163 mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS);
2164 mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS);
2166 bcopy((caddr_t)WakeUpParms,
2167 (caddr_t)&(mb->un.varUpdateCfg.cfg_data),
2168 sizeof (WAKE_UP_PARMS));
2169 mbq->mbox_cmpl = NULL;
2171 } /* emlxs_format_update_parms () */
2174 /* ARGSUSED */
2175 static void
2176 emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
2177 uint32_t region_id, uint32_t size)
2179 MAILBOX *mb = (MAILBOX *)mbq;
2181 bzero((void *)mb, MAILBOX_CMD_BSIZE);
2183 mb->mbxCommand = MBX_UPDATE_CFG;
2184 mb->un.varUpdateCfg.Vbit = 1;
2185 mb->un.varUpdateCfg.Obit = 1;
2186 mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET;
2187 mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2188 mb->un.varUpdateCfg.region_id = region_id;
2189 mb->un.varUpdateCfg.entry_len = size;
2190 mb->un.varUpdateCfg.byte_len = size;
2191 mbq->mbox_cmpl = NULL;
2193 } /* emlxs_format_update_pci_cfg() */
2197 static uint32_t
2198 emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2199 PROG_ID * prog_id, uint32_t proc_erom)
2201 emlxs_port_t *port = &PPORT;
2202 MAILBOX *mb;
2203 MAILBOXQ *mbox;
2204 uint32_t rval = 0;
2205 PROG_ID old_prog_id;
2207 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2208 KM_NOSLEEP)) == NULL) {
2209 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2210 "Unable to allocate mailbox buffer.");
2212 return (1);
2215 mb = (MAILBOX *)mbox;
2217 if (proc_erom && !(hba->model_info.chip &
2218 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2219 WakeUpParms->u1.EROM_prog_id = *prog_id;
2220 (void) emlxs_update_exp_rom(hba, WakeUpParms);
2223 old_prog_id = WakeUpParms->u0.boot_bios_id;
2224 WakeUpParms->u0.boot_bios_id = *prog_id;
2226 emlxs_format_update_parms(mbox, WakeUpParms);
2228 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2229 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2230 "Unable to update boot wakeup parms: Mailbox cmd=%x "
2231 "status=%x", mb->mbxCommand, mb->mbxStatus);
2233 WakeUpParms->u0.boot_bios_id = old_prog_id;
2234 rval = 1;
2237 if (mbox) {
2238 kmem_free(mbox, sizeof (MAILBOXQ));
2241 return (rval);
2243 } /* emlxs_update_boot_wakeup_parms() */
2247 static uint32_t
2248 emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2249 PROG_ID *prog_id)
2251 emlxs_port_t *port = &PPORT;
2252 uint32_t rval = 0;
2253 MAILBOXQ *mbox;
2254 MAILBOX *mb;
2255 PROG_ID old_prog_id;
2257 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2258 KM_NOSLEEP)) == NULL) {
2259 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2260 "Unable to allocate mailbox buffer.");
2262 return (1);
2265 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2266 "FF: Updating parms...");
2268 mb = (MAILBOX *)mbox;
2270 old_prog_id = WakeUpParms->prog_id;
2271 WakeUpParms->prog_id = *prog_id;
2273 emlxs_format_update_parms(mbox, WakeUpParms);
2275 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2277 "Unable to update wakeup parameters: Mailbox cmd=%x "
2278 "status=%x", mb->mbxCommand, mb->mbxStatus);
2280 WakeUpParms->prog_id = old_prog_id;
2281 rval = 1;
2284 if (mbox) {
2285 kmem_free(mbox, sizeof (MAILBOXQ));
2288 return (rval);
2290 } /* emlxs_update_ff_wakeup_parms() */
2293 static uint32_t
2294 emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2295 PROG_ID * prog_id)
2297 emlxs_port_t *port = &PPORT;
2298 uint32_t rval = 0;
2299 MAILBOXQ *mbox;
2300 MAILBOX *mb;
2301 PROG_ID old_prog_id;
2303 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2304 KM_NOSLEEP)) == NULL) {
2305 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2306 "Unable to allocate mailbox buffer.");
2308 return (1);
2311 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2312 "SLI1: Updating parms...");
2314 mb = (MAILBOX *)mbox;
2316 old_prog_id = WakeUpParms->sli1_prog_id;
2317 WakeUpParms->sli1_prog_id = *prog_id;
2319 emlxs_format_update_parms(mbox, WakeUpParms);
2321 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2322 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2323 "Unable to update wakeup parameters. Mailbox cmd=%x "
2324 "status=%x", mb->mbxCommand, mb->mbxStatus);
2326 WakeUpParms->sli1_prog_id = old_prog_id;
2327 rval = 1;
2330 if (mbox) {
2331 kmem_free(mbox, sizeof (MAILBOXQ));
2334 return (rval);
2336 } /* emlxs_update_sli1_wakeup_parms() */
2339 static uint32_t
2340 emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2341 PROG_ID * prog_id)
2343 emlxs_port_t *port = &PPORT;
2344 uint32_t rval = 0;
2345 MAILBOXQ *mbox;
2346 MAILBOX *mb;
2347 PROG_ID old_prog_id;
2349 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2350 KM_NOSLEEP)) == NULL) {
2351 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2352 "Unable to allocate mailbox buffer.");
2354 return (1);
2357 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2358 "SLI2: Updating parms...");
2360 mb = (MAILBOX *)mbox;
2362 old_prog_id = WakeUpParms->sli2_prog_id;
2363 WakeUpParms->sli2_prog_id = *prog_id;
2365 emlxs_format_update_parms(mbox, WakeUpParms);
2367 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2368 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2369 "Unable to update wakeup parameters. Mailbox cmd=%x "
2370 "status=%x", mb->mbxCommand, mb->mbxStatus);
2372 WakeUpParms->sli2_prog_id = old_prog_id;
2373 rval = 1;
2376 if (mbox) {
2377 kmem_free(mbox, sizeof (MAILBOXQ));
2380 return (rval);
2382 } /* emlxs_update_sli2_wakeup_parms() */
2385 static uint32_t
2386 emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2387 PROG_ID *prog_id)
2389 emlxs_port_t *port = &PPORT;
2390 uint32_t rval = 0;
2391 MAILBOXQ *mbox;
2392 MAILBOX *mb;
2393 PROG_ID old_prog_id;
2395 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2396 KM_NOSLEEP)) == NULL) {
2397 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2398 "Unable to allocate mailbox buffer.");
2400 return (1);
2403 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2404 "SLI3: Updating parms...");
2406 mb = (MAILBOX *)mbox;
2408 old_prog_id = WakeUpParms->sli3_prog_id;
2409 WakeUpParms->sli3_prog_id = *prog_id;
2411 emlxs_format_update_parms(mbox, WakeUpParms);
2413 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2414 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2415 "Unable to update wakeup parameters. Mailbox cmd=%x "
2416 "status=%x", mb->mbxCommand, mb->mbxStatus);
2418 WakeUpParms->sli3_prog_id = old_prog_id;
2419 rval = 1;
2422 if (mbox) {
2423 kmem_free(mbox, sizeof (MAILBOXQ));
2426 return (rval);
2428 } /* emlxs_update_sli3_wakeup_parms() */
2431 static uint32_t
2432 emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2433 PROG_ID *prog_id)
2435 emlxs_port_t *port = &PPORT;
2436 uint32_t rval = 0;
2437 MAILBOXQ *mbox;
2438 MAILBOX *mb;
2439 PROG_ID old_prog_id;
2441 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2442 KM_NOSLEEP)) == NULL) {
2443 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2444 "Unable to allocate mailbox buffer.");
2446 return (1);
2449 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2450 "SLI4: Updating parms...");
2452 mb = (MAILBOX *)mbox;
2454 old_prog_id = WakeUpParms->sli4_prog_id;
2455 WakeUpParms->sli4_prog_id = *prog_id;
2457 emlxs_format_update_parms(mbox, WakeUpParms);
2459 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2460 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2461 "Unable to update wakeup parameters. Mailbox cmd=%x "
2462 "status=%x", mb->mbxCommand, mb->mbxStatus);
2464 WakeUpParms->sli4_prog_id = old_prog_id;
2465 rval = 1;
2468 if (mbox) {
2469 kmem_free(mbox, sizeof (MAILBOXQ));
2472 return (rval);
2474 } /* emlxs_update_sli4_wakeup_parms() */
2477 static uint32_t
2478 emlxs_clean_flash(emlxs_hba_t *hba,
2479 PWAKE_UP_PARMS OldWakeUpParms, PWAKE_UP_PARMS NewWakeUpParms)
2481 emlxs_port_t *port = &PPORT;
2482 PROG_ID load_list[MAX_LOAD_ENTRY];
2483 PROG_ID *wakeup_list[MAX_LOAD_ENTRY];
2484 uint32_t count;
2485 uint32_t i;
2486 uint32_t j;
2487 uint32_t k = 0;
2488 uint32_t *wptr;
2490 if (!NewWakeUpParms) {
2491 return (1);
2494 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2495 "Cleaning flash...");
2497 /* If old wakeup parameter list is available, */
2498 /* then cleanup old entries */
2499 if (OldWakeUpParms) {
2500 if (bcmp(&OldWakeUpParms->prog_id, &NewWakeUpParms->prog_id,
2501 sizeof (PROG_ID))) {
2503 wptr = (uint32_t *)&OldWakeUpParms->prog_id;
2504 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2505 "OLD: prog_id: 0x%08x 0x%08x Removing.",
2506 wptr[0], wptr[1]);
2508 (void) emlxs_delete_load_entry(hba,
2509 &OldWakeUpParms->prog_id);
2512 if (bcmp(&OldWakeUpParms->u0.boot_bios_id,
2513 &NewWakeUpParms->u0.boot_bios_id, sizeof (PROG_ID))) {
2515 wptr = (uint32_t *)&OldWakeUpParms->u0.boot_bios_id;
2516 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2517 "OLD: boot_bios_id: 0x%08x 0x%08x Removing.",
2518 wptr[0], wptr[1]);
2520 (void) emlxs_delete_load_entry(hba,
2521 &OldWakeUpParms->u0.boot_bios_id);
2524 if (bcmp(&OldWakeUpParms->sli1_prog_id,
2525 &NewWakeUpParms->sli1_prog_id, sizeof (PROG_ID))) {
2527 wptr = (uint32_t *)&OldWakeUpParms->sli1_prog_id;
2528 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2529 "OLD: sli1_prog_id: 0x%08x 0x%08x Removing.",
2530 wptr[0], wptr[1]);
2532 (void) emlxs_delete_load_entry(hba,
2533 &OldWakeUpParms->sli1_prog_id);
2536 if (bcmp(&OldWakeUpParms->sli2_prog_id,
2537 &NewWakeUpParms->sli2_prog_id, sizeof (PROG_ID))) {
2539 wptr = (uint32_t *)&OldWakeUpParms->sli2_prog_id;
2540 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2541 "OLD: sli2_prog_id: 0x%08x 0x%08x Removing.",
2542 wptr[0], wptr[1]);
2544 (void) emlxs_delete_load_entry(hba,
2545 &OldWakeUpParms->sli2_prog_id);
2548 if (bcmp(&OldWakeUpParms->sli3_prog_id,
2549 &NewWakeUpParms->sli3_prog_id, sizeof (PROG_ID))) {
2551 wptr = (uint32_t *)&OldWakeUpParms->sli3_prog_id;
2552 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2553 "OLD: sli3_prog_id: 0x%08x 0x%08x Removing.",
2554 wptr[0], wptr[1]);
2556 (void) emlxs_delete_load_entry(hba,
2557 &OldWakeUpParms->sli3_prog_id);
2560 if (bcmp(&OldWakeUpParms->sli4_prog_id,
2561 &NewWakeUpParms->sli4_prog_id, sizeof (PROG_ID))) {
2563 wptr = (uint32_t *)&OldWakeUpParms->sli4_prog_id;
2564 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2565 "OLD: sli4_prog_id: 0x%08x 0x%08x Removing.",
2566 wptr[0], wptr[1]);
2568 (void) emlxs_delete_load_entry(hba,
2569 &OldWakeUpParms->sli4_prog_id);
2572 return (0);
2575 /* Otherwise use the current load list */
2576 count = emlxs_get_load_list(hba, load_list);
2578 if (!count) {
2579 return (1);
2582 /* Init the wakeup list */
2583 wptr = (uint32_t *)&NewWakeUpParms->prog_id;
2584 if (*wptr) {
2585 wakeup_list[k++] = &NewWakeUpParms->prog_id;
2588 wptr = (uint32_t *)&NewWakeUpParms->u0.boot_bios_id;
2589 if (*wptr) {
2590 wakeup_list[k++] = &NewWakeUpParms->u0.boot_bios_id;
2593 wptr = (uint32_t *)&NewWakeUpParms->sli1_prog_id;
2594 if (*wptr) {
2595 wakeup_list[k++] = &NewWakeUpParms->sli1_prog_id;
2598 wptr = (uint32_t *)&NewWakeUpParms->sli2_prog_id;
2599 if (*wptr) {
2600 wakeup_list[k++] = &NewWakeUpParms->sli2_prog_id;
2603 wptr = (uint32_t *)&NewWakeUpParms->sli3_prog_id;
2604 if (*wptr) {
2605 wakeup_list[k++] = &NewWakeUpParms->sli3_prog_id;
2608 wptr = (uint32_t *)&NewWakeUpParms->sli4_prog_id;
2609 if (*wptr) {
2610 wakeup_list[k++] = &NewWakeUpParms->sli4_prog_id;
2613 if (k == 0) {
2614 return (0);
2617 /* Match load list to wakeup list */
2618 for (i = 0; i < count; i++) {
2620 wptr = (uint32_t *)&load_list[i];
2622 for (j = 0; j < k; j++) {
2623 if (bcmp((uint8_t *)wakeup_list[j],
2624 (uint8_t *)&load_list[i], sizeof (PROG_ID)) == 0) {
2625 break;
2629 /* No match */
2630 if (j == k) {
2631 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2632 "Load List[%d]: %08x %08x Removing.",
2633 i, wptr[0], wptr[1]);
2635 (void) emlxs_delete_load_entry(hba, &load_list[i]);
2636 } else {
2637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2638 "Load List[%d]: %08x %08x Preserving.",
2639 i, wptr[0], wptr[1]);
2643 return (0);
2645 } /* emlxs_clean_flash() */
2648 /* ARGSUSED */
2649 static uint32_t
2650 emlxs_start_rel_download(emlxs_hba_t *hba,
2651 PIMAGE_HDR ImageHdr,
2652 caddr_t Buffer,
2653 PWAKE_UP_PARMS WakeUpParms,
2654 uint32_t dwc_flag)
2656 emlxs_port_t *port = &PPORT;
2657 MAILBOXQ *mbox;
2658 MAILBOX *mb;
2659 uint32_t *Src;
2660 uint32_t *Dst;
2661 caddr_t DataBuffer = NULL;
2662 uint32_t rval = 0;
2663 uint32_t DlByteCount;
2664 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
2665 uint32_t DlCount;
2666 uint32_t i;
2667 uint32_t *wptr;
2669 wptr = (uint32_t *)&ImageHdr->Id;
2670 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2671 "Relative download: %08x %08x", wptr[0], wptr[1]);
2673 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
2674 KM_NOSLEEP)) == NULL) {
2675 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2676 "Unable to allocate data buffer.");
2678 return (1);
2681 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2682 KM_NOSLEEP)) == NULL) {
2683 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2684 "Unable to allocate mailbox buffer.");
2686 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2688 return (1);
2691 mb = (MAILBOX *)mbox;
2693 DlByteCount = ImageHdr->BlockSize;
2695 emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
2696 &ImageHdr->Id, 0);
2698 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2699 " Erasing flash...");
2701 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
2703 if (rval) {
2704 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2705 "Unable to erase flash. Mailbox cmd=%x status=%x",
2706 mb->mbxCommand, mb->mbxStatus);
2708 goto EXIT_REL_DOWNLOAD;
2711 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2712 " Programming flash...");
2714 while (DlByteCount) {
2715 if (DlByteCount > SegSize) {
2716 DlCount = SegSize;
2717 } else {
2718 DlCount = DlByteCount;
2720 DlByteCount -= DlCount;
2722 Dst = (uint32_t *)DataBuffer;
2723 Src = (uint32_t *)Buffer;
2725 for (i = 0; i < (DlCount / 4); i++) {
2726 *Dst = *Src;
2727 Dst++;
2728 Src++;
2731 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
2732 (volatile uint32_t *)
2733 ((volatile char *)hba->sli.sli3.slim_addr +
2734 sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2736 emlxs_format_prog_flash(mbox,
2738 DlCount,
2739 PROGRAM_FLASH,
2740 (DlByteCount) ? 0 : 1,
2741 0, DlCount, &ImageHdr->Id, dwc_flag);
2743 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
2745 if (rval) {
2746 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2747 "Unable to program flash. Mailbox cmd=%x status=%x",
2748 mb->mbxCommand, mb->mbxStatus);
2750 goto EXIT_REL_DOWNLOAD;
2753 Buffer += DlCount;
2756 #ifdef FMA_SUPPORT
2757 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2758 != DDI_FM_OK) {
2759 EMLXS_MSGF(EMLXS_CONTEXT,
2760 &emlxs_invalid_access_handle_msg, NULL);
2762 rval = 1;
2764 goto EXIT_REL_DOWNLOAD;
2766 #endif /* FMA_SUPPORT */
2768 /* Update wakeup parameters */
2769 switch (ImageHdr->Id.Type) {
2770 case TEST_PROGRAM:
2771 break;
2773 case FUNC_FIRMWARE:
2774 if (!dwc_flag) {
2775 rval = emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
2776 &ImageHdr->Id);
2777 } else {
2778 WakeUpParms->prog_id = ImageHdr->Id;
2780 break;
2782 case BOOT_BIOS:
2783 if (!dwc_flag) {
2784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2785 "BOOT: Updating parms...");
2787 rval = emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
2788 &ImageHdr->Id, 1);
2789 } else {
2790 if (hba->wakeup_parms.u0.boot_bios_wd[0]) {
2791 WakeUpParms->u0.boot_bios_id = ImageHdr->Id;
2794 if (!(hba->model_info.chip &
2795 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2796 WakeUpParms->u1.EROM_prog_id = ImageHdr->Id;
2799 break;
2801 case SLI1_OVERLAY:
2802 if (!dwc_flag) {
2803 rval = emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
2804 &ImageHdr->Id);
2805 } else {
2806 WakeUpParms->sli1_prog_id = ImageHdr->Id;
2808 break;
2810 case SLI2_OVERLAY:
2811 if (!dwc_flag) {
2812 rval = emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
2813 &ImageHdr->Id);
2814 } else {
2815 WakeUpParms->sli2_prog_id = ImageHdr->Id;
2817 break;
2819 case SLI3_OVERLAY:
2820 if (!dwc_flag) {
2821 rval = emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
2822 &ImageHdr->Id);
2823 } else {
2824 WakeUpParms->sli3_prog_id = ImageHdr->Id;
2826 break;
2828 case SLI4_OVERLAY:
2829 if (!dwc_flag) {
2830 rval = emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
2831 &ImageHdr->Id);
2832 } else {
2833 WakeUpParms->sli4_prog_id = ImageHdr->Id;
2835 break;
2837 default:
2838 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2839 "Image type not supported. Type=%x", ImageHdr->Id.Type);
2841 break;
2844 EXIT_REL_DOWNLOAD:
2845 if (DataBuffer) {
2846 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2849 if (mbox) {
2850 kmem_free(mbox, sizeof (MAILBOXQ));
2853 return (rval);
2855 } /* emlxs_start_rel_download() */
2858 static uint32_t
2859 emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer, emlxs_fw_image_t *fw_image)
2861 emlxs_port_t *port = &PPORT;
2862 uint32_t rval = 0;
2863 WAKE_UP_PARMS RelWakeUpParms;
2864 WAKE_UP_PARMS WakeUpParms;
2865 uint32_t i;
2866 IMAGE_HDR ImageHdr;
2867 caddr_t bptr;
2868 uint32_t flash_cleaned = 0;
2870 if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 0)) {
2871 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2872 "Unable to get wakeup parameters.");
2874 return (EMLXS_IMAGE_FAILED);
2877 download:
2879 bcopy(&WakeUpParms, &RelWakeUpParms, sizeof (WAKE_UP_PARMS));
2881 for (i = 0; i < MAX_PROG_TYPES; i++) {
2882 if (!fw_image->prog[i].version) {
2883 continue;
2886 bptr = buffer + fw_image->prog[i].offset;
2888 bcopy(bptr, &ImageHdr, sizeof (IMAGE_HDR));
2890 rval = emlxs_start_rel_download(hba, &ImageHdr, bptr,
2891 &RelWakeUpParms, 1);
2893 if (rval) {
2894 EMLXS_MSGF(EMLXS_CONTEXT,
2895 &emlxs_download_failed_msg,
2896 "Failed to program flash.");
2898 if ((rval == NO_FLASH_MEM_AVAIL) && !flash_cleaned) {
2899 /* Cleanup using current load list */
2900 (void) emlxs_clean_flash(hba, 0, &WakeUpParms);
2902 flash_cleaned = 1;
2903 goto download;
2906 return (EMLXS_IMAGE_FAILED);
2910 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2911 "Updating wakeup parameters.");
2913 if (emlxs_update_wakeup_parms(hba, &RelWakeUpParms,
2914 &RelWakeUpParms)) {
2915 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2916 "Unable to update parameters.");
2918 return (EMLXS_IMAGE_FAILED);
2921 /* Cleanup using old wakeup paramters */
2922 (void) emlxs_clean_flash(hba, &WakeUpParms, &RelWakeUpParms);
2924 return (0);
2926 } /* emlxs_proc_rel_2mb() */
2929 #define FLASH_POLLING_BIT 0x80
2930 #define FLASH_ERROR_BIT 0x20
2932 typedef struct _flash_t
2934 uint32_t offset;
2935 uint8_t val;
2936 } flash_t;
2940 static uint32_t
2941 emlxs_write_fcode_flash(emlxs_hba_t *hba,
2942 PIMAGE_HDR ImageHdr, caddr_t Buffer)
2944 emlxs_port_t *port = &PPORT;
2945 uint8_t bb;
2946 uint8_t cc;
2947 uint8_t *src;
2948 uint32_t DlByteCount = ImageHdr->BlockSize;
2949 uint32_t i;
2950 uint32_t j;
2951 uint32_t k;
2953 flash_t wr[3] = {
2954 {0x555, 0xaa},
2955 {0x2aa, 0x55},
2956 {0x555, 0xa0}
2959 /* Load Fcode */
2960 src = (uint8_t *)Buffer + sizeof (IMAGE_HDR);
2961 for (i = 0; i < DlByteCount; i++) {
2962 for (k = 0; k < 3; k++) {
2963 SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
2966 /* Reverse Endian word alignment */
2967 j = (i & 3) ^ 3;
2969 bb = src[j];
2971 if (j == 0) {
2972 src += 4;
2975 SBUS_WRITE_FLASH_COPY(hba, i, bb);
2977 /* check for complete */
2978 for (;;) {
2979 DELAYUS(20);
2981 cc = SBUS_READ_FLASH_COPY(hba, i);
2983 /* If data matches then continue */
2984 if (cc == bb) {
2985 break;
2988 /* Polling bit will be inverse final value */
2989 /* while active */
2990 if ((cc ^ bb) & FLASH_POLLING_BIT) {
2991 /* Still busy */
2993 /* Check for error bit */
2994 if (cc & FLASH_ERROR_BIT) {
2995 /* Read data one more time */
2996 cc = SBUS_READ_FLASH_COPY(hba, i);
2998 /* Check if data matches */
2999 if (cc == bb) {
3000 break;
3003 EMLXS_MSGF(EMLXS_CONTEXT,
3004 &emlxs_download_failed_msg,
3005 "FCode write error: offset:%x "
3006 "wrote:%x read:%x\n", i, bb, cc);
3008 return (1);
3014 /* Load Header */
3015 src = (uint8_t *)ImageHdr;
3017 for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) {
3018 for (k = 0; k < 3; k++) {
3019 SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
3022 /* Reverse Endian word alignment */
3023 j = (i & 3) ^ 3;
3025 bb = src[j];
3027 if (j == 0) {
3028 src += 4;
3031 SBUS_WRITE_FLASH_COPY(hba, i, bb);
3033 /* check for complete */
3034 for (;;) {
3035 DELAYUS(20);
3037 cc = SBUS_READ_FLASH_COPY(hba, i);
3039 /* If data matches then continue */
3040 if (cc == bb) {
3041 break;
3044 /* Polling bit will be inverse final value */
3045 /* while active */
3046 if ((cc ^ bb) & FLASH_POLLING_BIT) {
3047 /* Still busy */
3049 /* Check for error bit */
3050 if (cc & FLASH_ERROR_BIT) {
3051 /* Read data one more time */
3052 cc = SBUS_READ_FLASH_COPY(hba, i);
3054 /* Check if data matches */
3055 if (cc == bb) {
3056 break;
3059 EMLXS_MSGF(EMLXS_CONTEXT,
3060 &emlxs_download_failed_msg,
3061 "FCode write error: offset:%x "
3062 "wrote:%x read:%x\n", i, bb, cc);
3064 return (1);
3070 #ifdef FMA_SUPPORT
3071 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
3072 != DDI_FM_OK) {
3073 EMLXS_MSGF(EMLXS_CONTEXT,
3074 &emlxs_invalid_access_handle_msg, NULL);
3075 return (1);
3077 #endif /* FMA_SUPPORT */
3079 return (0);
3081 } /* emlxs_write_fcode_flash() */
3085 static uint32_t
3086 emlxs_erase_fcode_flash(emlxs_hba_t *hba)
3088 emlxs_port_t *port = &PPORT;
3089 int32_t i, j;
3090 uint8_t cc;
3091 uint32_t offset;
3093 flash_t ef[6] = {
3094 {0x555, 0xaa},
3095 {0x2aa, 0x55},
3096 {0x555, 0x80},
3097 {0x555, 0xaa},
3098 {0x2aa, 0x55},
3099 {0x555, 0x10}
3102 /* Auto select */
3103 flash_t as[3] = {
3104 {0x555, 0xaa},
3105 {0x2aa, 0x55},
3106 {0x555, 0x90}
3110 /* Check Manufacturers Code */
3111 for (i = 0; i < 3; i++) {
3112 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3115 cc = SBUS_READ_FLASH_COPY(hba, 0);
3117 /* Check Device Code */
3118 for (i = 0; i < 3; i++) {
3119 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3122 cc = SBUS_READ_FLASH_COPY(hba, 1);
3125 /* Check block protections (up to 4 16K blocks = 64K) */
3126 for (j = 0; j < 4; j++) {
3127 for (i = 0; i < 3; i++) {
3128 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3131 offset = (j << 14) | 0x2;
3133 cc = SBUS_READ_FLASH_COPY(hba, offset);
3135 if (cc == 0x01) {
3136 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3137 "Block %d is protected and can't be erased.", j);
3141 /* Write erase flash sequence */
3142 for (i = 0; i < 6; i++) {
3143 SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val);
3146 /* check for complete */
3147 for (;;) {
3148 /* Delay 3 seconds */
3149 DELAYMS(3000);
3151 cc = SBUS_READ_FLASH_COPY(hba, 0);
3154 /* If data matches then continue; */
3155 if (cc == 0xff) {
3156 break;
3159 /* Polling bit will be inverse final value while active */
3160 if ((cc ^ 0xff) & FLASH_POLLING_BIT) {
3161 /* Still busy */
3163 /* Check for error bit */
3164 if (cc & FLASH_ERROR_BIT) {
3165 /* Read data one more time */
3166 cc = SBUS_READ_FLASH_COPY(hba, 0);
3168 /* Check if data matches */
3169 if (cc == 0xff) {
3170 break;
3173 EMLXS_MSGF(EMLXS_CONTEXT,
3174 &emlxs_download_failed_msg,
3175 "FCode write error: offset:%x wrote:%x "
3176 "read:%x\n", i, 0xff, cc);
3178 return (1);
3183 #ifdef FMA_SUPPORT
3184 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
3185 != DDI_FM_OK) {
3186 EMLXS_MSGF(EMLXS_CONTEXT,
3187 &emlxs_invalid_access_handle_msg, NULL);
3188 return (1);
3190 #endif /* FMA_SUPPORT */
3192 return (0);
3194 } /* emlxs_erase_fcode_flash() */
3197 static uint32_t
3198 emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId)
3200 emlxs_port_t *port = &PPORT;
3201 MAILBOXQ *mbox = NULL;
3202 MAILBOX *mb;
3203 uint32_t rval = 0;
3205 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3206 KM_NOSLEEP)) == NULL) {
3207 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3208 "Unable to allocate mailbox buffer.");
3210 return (1);
3213 mb = (MAILBOX *)mbox;
3214 mb->mbxCommand = MBX_DEL_LD_ENTRY;
3215 mb->un.varDelLdEntry.list_req = FLASH_LOAD_LIST;
3216 mb->un.varDelLdEntry.prog_id = *progId;
3218 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3219 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3220 "Unable to delete load entry: Mailbox cmd=%x status=%x",
3221 mb->mbxCommand, mb->mbxStatus);
3223 rval = 1;
3226 done:
3228 if (mbox) {
3229 kmem_free(mbox, sizeof (MAILBOXQ));
3232 return (rval);
3234 } /* emlxs_delete_load_entry() */
3237 extern uint32_t
3238 emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
3240 emlxs_port_t *port = &PPORT;
3241 LOAD_ENTRY *LoadEntry;
3242 LOAD_LIST *LoadList = NULL;
3243 uint32_t i;
3244 uint32_t count = 0;
3246 bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
3248 if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST),
3249 KM_NOSLEEP)) == NULL) {
3250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3251 "Unable to allocate LOADLIST buffer.");
3253 goto done;
3256 if (emlxs_read_load_list(hba, LoadList)) {
3257 goto done;
3260 for (i = 0; i < LoadList->entry_cnt; i++) {
3261 LoadEntry = &LoadList->load_entry[i];
3262 if ((LoadEntry->un.wd[0] != 0) &&
3263 (LoadEntry->un.wd[0] != 0xffffffff)) {
3264 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3265 "Load List[%d]: %08x %08x", count,
3266 LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
3268 load_list[count++] = LoadEntry->un.id;
3272 done:
3274 if (LoadList) {
3275 kmem_free(LoadList, sizeof (LOAD_LIST));
3278 return (count);
3280 } /* emlxs_get_load_list() */
3283 extern uint32_t
3284 emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
3285 uint32_t verbose)
3287 emlxs_port_t *port = &PPORT;
3288 MAILBOXQ *mbox;
3289 MAILBOX *mb;
3290 uint32_t rval = 0;
3291 uint32_t *wd;
3293 bzero(WakeUpParms, sizeof (WAKE_UP_PARMS));
3295 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3296 KM_NOSLEEP)) == NULL) {
3297 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3298 "Unable to allocate mailbox buffer.");
3300 return (1);
3303 mb = (MAILBOX *)mbox;
3305 emlxs_format_dump(hba, mbox,
3306 DMP_NV_PARAMS,
3307 WAKE_UP_PARMS_REGION_ID,
3308 sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
3310 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3311 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3312 "Unable to get parameters: Mailbox cmd=%x status=%x",
3313 mb->mbxCommand, mb->mbxStatus);
3315 if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) {
3316 rval = (uint32_t)CFG_DATA_NO_REGION;
3317 } else {
3318 rval = 1;
3320 } else {
3321 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3322 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
3323 0, hba->sli.sli4.dump_region.size,
3324 DDI_DMA_SYNC_FORKERNEL);
3326 bcopy((caddr_t)hba->sli.sli4.dump_region.virt,
3327 (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
3328 } else {
3329 bcopy((caddr_t)&mb->un.varDmp.resp_offset,
3330 (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
3333 if (verbose) {
3334 wd = (uint32_t *)&WakeUpParms->prog_id;
3335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3336 "Wakeup: prog_id=%08x %08x", wd[0], wd[1]);
3338 wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id;
3339 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3340 "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]);
3342 wd = (uint32_t *)&WakeUpParms->sli1_prog_id;
3343 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3344 "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]);
3346 wd = (uint32_t *)&WakeUpParms->sli2_prog_id;
3347 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3348 "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]);
3350 wd = (uint32_t *)&WakeUpParms->sli3_prog_id;
3351 if (wd[0] || wd[1]) {
3352 EMLXS_MSGF(EMLXS_CONTEXT,
3353 &emlxs_init_debug_msg,
3354 "Wakeup: sli3_prog_id=%08x %08x", wd[0],
3355 wd[1]);
3358 wd = (uint32_t *)&WakeUpParms->sli4_prog_id;
3359 if (wd[0] || wd[1]) {
3360 EMLXS_MSGF(EMLXS_CONTEXT,
3361 &emlxs_init_debug_msg,
3362 "Wakeup: sli4_prog_id=%08x %08x", wd[0],
3363 wd[1]);
3366 wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id;
3367 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3368 "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]);
3370 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3371 "Wakeup: pci_cfg_rsvd=%x",
3372 WakeUpParms->pci_cfg_rsvd);
3373 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3374 "Wakeup: use_hdw_def=%x",
3375 WakeUpParms->use_hdw_def);
3376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3377 "Wakeup: pci_cfg_sel=%x",
3378 WakeUpParms->pci_cfg_sel);
3379 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3380 "Wakeup: cfg_lookup=%x",
3381 WakeUpParms->pci_cfg_lookup_sel);
3385 done:
3387 if (mbox) {
3388 kmem_free(mbox, sizeof (MAILBOXQ));
3391 #ifdef FMA_SUPPORT
3392 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3393 if (emlxs_fm_check_dma_handle(hba,
3394 hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3395 EMLXS_MSGF(EMLXS_CONTEXT,
3396 &emlxs_invalid_dma_handle_msg,
3397 "emlxs_read_wakeup_parms: hdl=%p",
3398 hba->sli.sli4.dump_region.dma_handle);
3399 rval = 1;
3402 #endif /* FMA_SUPPORT */
3404 return (rval);
3406 } /* emlxs_read_wakeup_parms() */
3409 static uint32_t
3410 emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
3412 emlxs_port_t *port = &PPORT;
3413 LOAD_ENTRY *LoadEntry;
3414 uint32_t *Uptr;
3415 uint32_t CurEntryAddr;
3416 MAILBOXQ *mbox = NULL;
3417 MAILBOX *mb;
3419 bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
3421 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3422 KM_NOSLEEP)) == NULL) {
3423 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3424 "Unable to allocate mailbox buffer.");
3426 return (1);
3429 mb = (MAILBOX *)mbox;
3431 emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
3433 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3434 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3435 "Unable to get load list: Mailbox cmd=%x status=%x",
3436 mb->mbxCommand, mb->mbxStatus);
3438 goto done;
3441 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3442 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
3443 hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
3444 Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
3445 } else {
3446 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
3449 LoadList->head = Uptr[0];
3450 LoadList->tail = Uptr[1];
3452 CurEntryAddr = LoadList->head;
3454 while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
3455 (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
3456 LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
3457 LoadList->entry_cnt++;
3459 emlxs_format_dump(hba, mbox,
3460 DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
3462 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3463 MBX_SUCCESS) {
3464 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3465 "Unable to get load list (%d): Mailbox cmd=%x "
3466 "status=%x", LoadList->entry_cnt, mb->mbxCommand,
3467 mb->mbxStatus);
3469 goto done;
3472 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3473 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
3474 0, hba->sli.sli4.dump_region.size,
3475 DDI_DMA_SYNC_FORKERNEL);
3476 Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
3477 } else {
3478 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
3481 LoadEntry->next = Uptr[0];
3482 LoadEntry->prev = Uptr[1];
3483 LoadEntry->start_adr = Uptr[2];
3484 LoadEntry->len = Uptr[3];
3485 LoadEntry->un.wd[0] = Uptr[4];
3486 LoadEntry->un.wd[1] = Uptr[5];
3488 /* update next current load entry address */
3489 CurEntryAddr = LoadEntry->next;
3491 } /* end of while (not end of list) */
3493 done:
3495 if (mbox) {
3496 kmem_free(mbox, sizeof (MAILBOXQ));
3499 #ifdef FMA_SUPPORT
3500 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3501 if (emlxs_fm_check_dma_handle(hba,
3502 hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3503 EMLXS_MSGF(EMLXS_CONTEXT,
3504 &emlxs_invalid_dma_handle_msg,
3505 "emlxs_read_load_list: hdl=%p",
3506 hba->sli.sli4.dump_region.dma_handle);
3507 return (1);
3510 #endif /* FMA_SUPPORT */
3512 return (0);
3514 } /* emlxs_read_load_list() */
3519 static int
3520 emlxs_build_parms(caddr_t Buffer,
3521 PWAKE_UP_PARMS AbsWakeUpParms,
3522 uint32_t BufferSize, PAIF_HDR AifHeader)
3524 IMAGE_HDR ImageHdr;
3525 uint32_t NextImage;
3526 uint32_t i;
3527 int32_t ChangeParams = FALSE;
3528 caddr_t Sptr;
3529 caddr_t Dptr;
3531 bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
3533 if ((AifHeader->ImageBase != 0x20000) &&
3534 ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
3535 return (FALSE);
3538 NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
3540 while (BufferSize > NextImage) {
3541 Sptr = &Buffer[NextImage];
3542 Dptr = (caddr_t)&ImageHdr;
3543 for (i = 0; i < sizeof (IMAGE_HDR); i++) {
3544 Dptr[i] = Sptr[i];
3547 if (ImageHdr.BlockSize == 0xffffffff)
3548 break;
3550 switch (ImageHdr.Id.Type) {
3551 case TEST_PROGRAM:
3552 break;
3553 case FUNC_FIRMWARE:
3554 AbsWakeUpParms->prog_id = ImageHdr.Id;
3555 ChangeParams = TRUE;
3556 break;
3557 case BOOT_BIOS:
3558 AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
3559 ChangeParams = TRUE;
3560 break;
3561 case SLI1_OVERLAY:
3562 AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
3563 ChangeParams = TRUE;
3564 break;
3565 case SLI2_OVERLAY:
3566 AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
3567 ChangeParams = TRUE;
3568 break;
3569 case SLI3_OVERLAY:
3570 AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
3571 ChangeParams = TRUE;
3572 break;
3573 case SLI4_OVERLAY:
3574 AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
3575 ChangeParams = TRUE;
3576 break;
3577 default:
3578 break;
3581 NextImage += ImageHdr.BlockSize;
3584 return (ChangeParams);
3586 } /* emlxs_build_parms() */
3589 static uint32_t
3590 emlxs_update_wakeup_parms(emlxs_hba_t *hba,
3591 PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
3593 emlxs_port_t *port = &PPORT;
3594 MAILBOX *mb;
3595 MAILBOXQ *mbox;
3596 uint32_t rval = 0;
3598 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3599 KM_NOSLEEP)) == NULL) {
3600 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3601 "Unable to allocate mailbox buffer.");
3603 return (1);
3606 mb = (MAILBOX *)mbox;
3608 WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
3609 WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
3610 WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
3611 WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
3612 WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
3613 WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
3615 emlxs_format_update_parms(mbox, WakeUpParms);
3617 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3618 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3619 "Unable to update wakeup parameters: Mailbox cmd=%x "
3620 "status=%x", mb->mbxCommand, mb->mbxStatus);
3622 rval = 1;
3625 if (mbox) {
3626 kmem_free(mbox, sizeof (MAILBOXQ));
3629 return (rval);
3631 } /* emlxs_update_wakeup_parms() */
3634 static uint32_t
3635 emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
3636 uint32_t type, char *file_type)
3638 emlxs_port_t *port = &PPORT;
3640 /* Create the version label */
3641 emlxs_decode_version(file->version, file->label);
3643 /* Process the DWC type */
3644 switch (type) {
3645 case TEST_PROGRAM:
3647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3648 "%s: TEST: offset=%08x version=%08x, %s", file_type,
3649 file->offset, file->version, file->label);
3651 break;
3653 case BOOT_BIOS:
3655 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3656 "%s: BOOT: offset=%08x version=%08x, %s", file_type,
3657 file->offset, file->version, file->label);
3659 if (!emlxs_bios_check(hba, id)) {
3660 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3661 "BOOT Check: Image not compatible with %s. id=%02x",
3662 hba->model_info.model, id);
3664 return (EMLXS_IMAGE_INCOMPATIBLE);
3667 break;
3669 case FUNC_FIRMWARE: /* Stub */
3671 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3672 "%s: STUB: offset=%08x version=%08x, %s", file_type,
3673 file->offset, file->version, file->label);
3675 if (!emlxs_stub_check(hba, id)) {
3676 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3677 "STUB Check: Image not compatible with %s. id=%02x",
3678 hba->model_info.model, id);
3680 return (EMLXS_IMAGE_INCOMPATIBLE);
3683 break;
3685 case SLI1_OVERLAY:
3687 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3688 "%s: SLI1: offset=%08x version=%08x, %s", file_type,
3689 file->offset, file->version, file->label);
3691 if (!emlxs_sli1_check(hba, id)) {
3692 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3693 "SLI1 Check: Image not compatible with %s. id=%02x",
3694 hba->model_info.model, id);
3696 return (EMLXS_IMAGE_INCOMPATIBLE);
3699 break;
3701 case SLI2_OVERLAY:
3703 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3704 "%s: SLI2: offset=%08x version=%08x, %s", file_type,
3705 file->offset, file->version, file->label);
3707 if (!emlxs_sli2_check(hba, id)) {
3708 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3709 "SLI2 Check: Image not compatible with %s. id=%02x",
3710 hba->model_info.model, id);
3712 return (EMLXS_IMAGE_INCOMPATIBLE);
3715 break;
3717 case SLI3_OVERLAY:
3719 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3720 "%s: SLI3: offset=%08x version=%08x, %s", file_type,
3721 file->offset, file->version, file->label);
3723 if (!emlxs_sli3_check(hba, id)) {
3724 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3725 "SLI3 Check: Image not compatible with %s. id=%02x",
3726 hba->model_info.model, id);
3728 return (EMLXS_IMAGE_INCOMPATIBLE);
3731 break;
3733 case SLI4_OVERLAY:
3735 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3736 "%s: SLI4: offset=%08x version=%08x, %s", file_type,
3737 file->offset, file->version, file->label);
3739 if (!emlxs_sli4_check(hba, id)) {
3740 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3741 "SLI4 Check: Image not compatible with %s. id=%02x",
3742 hba->model_info.model, id);
3744 return (EMLXS_IMAGE_INCOMPATIBLE);
3747 break;
3749 case SBUS_FCODE:
3751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3752 "%s: SBUS FCODE: offset=%08x version=%08x, %s",
3753 file_type, file->offset, file->version, file->label);
3755 if (!emlxs_sbus_fcode_check(hba, id)) {
3756 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3757 "SBUS FCODE Check: Image not compatible with %s. "
3758 "id=%02x", hba->model_info.model, id);
3760 return (EMLXS_IMAGE_INCOMPATIBLE);
3763 break;
3765 case KERNEL_CODE:
3767 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3768 "%s: KERN: offset=%08x version=%08x, %s", file_type,
3769 file->offset, file->version, file->label);
3771 if (!emlxs_kern_check(hba, id)) {
3772 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3773 "KERN Check: Image not compatible with %s. id=%02x",
3774 hba->model_info.model, id);
3776 return (EMLXS_IMAGE_INCOMPATIBLE);
3779 break;
3781 default:
3782 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
3783 "%s: Image type not supported. type=%x", file_type, type);
3785 return (EMLXS_IMAGE_BAD);
3788 return (0);
3790 } /* emlxs_validate_version() */
3793 static void
3794 emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *fw_image)
3796 emlxs_port_t *port = &PPORT;
3797 emlxs_vpd_t *vpd = &VPD;
3798 uint32_t i;
3799 uint32_t count;
3801 /* Check for AWC file */
3802 if (fw_image->awc.version) {
3803 if (fw_image->awc.version == vpd->postKernRev) {
3804 fw_image->awc.version = 0;
3807 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3808 "AWC file: KERN: old=%s new=%s %s.",
3809 vpd->postKernName,
3810 fw_image->awc.label,
3811 (fw_image->awc.version)? "Update":"Skip");
3814 /* Check for BWC file */
3815 if (fw_image->bwc.version) {
3816 if (strcmp(vpd->fcode_version, fw_image->bwc.label) == 0) {
3817 fw_image->bwc.version = 0;
3820 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3821 "BWC file: BOOT: old=%s new=%s %s.",
3822 vpd->fcode_version,
3823 fw_image->bwc.label,
3824 (fw_image->bwc.version)? "Update":"Skip");
3827 /* Check for DWC file */
3828 if (fw_image->dwc.version) {
3829 /* Check for program files */
3830 count = 0;
3831 for (i = 0; i < MAX_PROG_TYPES; i++) {
3832 if (!fw_image->prog[i].version) {
3833 continue;
3836 /* Skip components that don't need updating */
3837 switch (i) {
3838 case TEST_PROGRAM:
3839 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3840 "DWC file: TEST: new=%s "
3841 "Update.",
3842 fw_image->prog[i].label);
3843 break;
3845 case BOOT_BIOS:
3846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3847 "DWC file: BOOT: new=%s "
3848 "Update.",
3849 fw_image->prog[i].label);
3850 break;
3852 case FUNC_FIRMWARE:
3853 if (vpd->opFwRev &&
3854 (fw_image->prog[i].version ==
3855 vpd->opFwRev)) {
3856 fw_image->prog[i].version = 0;
3859 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3860 "DWC file: STUB: old=%s new=%s %s.",
3861 vpd->opFwName,
3862 fw_image->prog[i].label,
3863 (fw_image->prog[i].version)?
3864 "Update":"Skip");
3865 break;
3867 case SLI1_OVERLAY:
3868 if (vpd->sli1FwRev &&
3869 (fw_image->prog[i].version ==
3870 vpd->sli1FwRev)) {
3871 fw_image->prog[i].version = 0;
3874 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3875 "DWC file: SLI1: old=%s new=%s %s.",
3876 vpd->sli1FwName,
3877 fw_image->prog[i].label,
3878 (fw_image->prog[i].version)?
3879 "Update":"Skip");
3880 break;
3882 case SLI2_OVERLAY:
3883 if (vpd->sli2FwRev &&
3884 (fw_image->prog[i].version ==
3885 vpd->sli2FwRev)) {
3886 fw_image->prog[i].version = 0;
3889 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3890 "DWC file: SLI2: old=%s new=%s %s.",
3891 vpd->sli2FwName,
3892 fw_image->prog[i].label,
3893 (fw_image->prog[i].version)?
3894 "Update":"Skip");
3895 break;
3897 case SLI3_OVERLAY:
3898 if (vpd->sli3FwRev &&
3899 (fw_image->prog[i].version ==
3900 vpd->sli3FwRev)) {
3901 fw_image->prog[i].version = 0;
3904 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3905 "DWC file: SLI3: old=%s new=%s %s.",
3906 vpd->sli3FwName,
3907 fw_image->prog[i].label,
3908 (fw_image->prog[i].version)?
3909 "Update":"Skip");
3910 break;
3912 case SLI4_OVERLAY:
3913 if (vpd->sli4FwRev &&
3914 (fw_image->prog[i].version ==
3915 vpd->sli4FwRev)) {
3916 fw_image->prog[i].version = 0;
3919 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3920 "DWC file: SLI4: old=%s new=%s %s.",
3921 vpd->sli4FwRev,
3922 fw_image->prog[i].label,
3923 (fw_image->prog[i].version)?
3924 "Update":"Skip");
3925 break;
3927 default:
3928 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3929 "DWC file: type=%x version=%x label=%s "
3930 "Update.",
3932 fw_image->prog[i].version,
3933 fw_image->prog[i].label);
3936 if (fw_image->prog[i].version) {
3937 count++;
3941 if (!count) {
3942 fw_image->dwc.version = 0;
3946 return;
3948 } /* emlxs_verify_image() */
3951 static uint32_t
3952 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
3953 emlxs_fw_image_t *image)
3955 emlxs_port_t *port = &PPORT;
3956 uint32_t ImageType;
3957 AIF_HDR AifHdr;
3958 IMAGE_HDR ImageHdr;
3959 uint32_t NextImage;
3960 uint32_t count;
3961 uint32_t FileType;
3962 uint32_t FileLen = 0;
3963 uint32_t TotalLen = 0;
3964 uint32_t *CkSumEnd;
3965 uint32_t id;
3966 uint32_t type;
3967 uint32_t ver;
3968 uint32_t ImageLength;
3969 uint32_t BufferSize;
3970 uint32_t rval = 0;
3971 caddr_t bptr;
3972 emlxs_vpd_t *vpd;
3974 vpd = &VPD;
3976 /* Get image type */
3977 ImageType = *((uint32_t *)Buffer);
3979 /* Pegasus and beyond adapters */
3980 if ((ImageType == NOP_IMAGE_TYPE) &&
3981 !(hba->model_info.chip &
3982 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
3983 bptr = Buffer;
3984 TotalLen = sizeof (uint32_t);
3986 while (TotalLen < Size) {
3987 if (Size < sizeof (AIF_HDR)) {
3988 EMLXS_MSGF(EMLXS_CONTEXT,
3989 &emlxs_image_bad_msg,
3990 "Invalid image header length: 0x%x < 0x%x",
3991 Size, sizeof (AIF_HDR));
3993 return (EMLXS_IMAGE_BAD);
3996 bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
3997 emlxs_disp_aif_header(hba, &AifHdr);
3999 ImageLength = AifHdr.RoSize;
4001 /* Validate checksum */
4002 CkSumEnd =
4003 (uint32_t *)(bptr + ImageLength +
4004 sizeof (AIF_HDR));
4005 if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
4006 EMLXS_MSGF(EMLXS_CONTEXT,
4007 &emlxs_image_bad_msg,
4008 "Invalid checksum found.");
4010 return (EMLXS_IMAGE_BAD);
4013 FileType = AifHdr.ZinitBr;
4014 switch (FileType) {
4015 case FILE_TYPE_AWC:
4016 image->awc.offset =
4017 (uint32_t)((uintptr_t)bptr -
4018 (uintptr_t)Buffer);
4019 image->awc.version = AifHdr.AVersion;
4020 image->awc.revcomp = 0;
4022 id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4023 type = emlxs_type_check(
4024 (AifHdr.AVersion & 0xff000000) >> 24);
4026 /* Validate the file version */
4027 if ((rval = emlxs_validate_version(hba,
4028 &image->awc, id, type, "AWC file"))) {
4029 return (rval);
4032 break;
4034 case FILE_TYPE_BWC:
4035 image->bwc.offset =
4036 (uint32_t)((uintptr_t)bptr -
4037 (uintptr_t)Buffer);
4038 image->bwc.version = AifHdr.AVersion;
4039 image->bwc.revcomp = 0;
4041 id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4042 type = emlxs_type_check(
4043 (AifHdr.AVersion & 0xff000000) >> 24);
4045 /* Validate the file version */
4046 if ((rval = emlxs_validate_version(hba,
4047 &image->bwc, id, type, "BWC file"))) {
4048 return (rval);
4051 break;
4053 case FILE_TYPE_DWC:
4054 image->dwc.offset =
4055 (uint32_t)((uintptr_t)bptr -
4056 (uintptr_t)Buffer);
4057 image->dwc.version = AifHdr.AVersion;
4058 image->dwc.revcomp = 0;
4060 id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4061 type = emlxs_type_check(
4062 (AifHdr.AVersion & 0xff000000) >> 24);
4064 /* Validate the file version */
4065 if ((rval = emlxs_validate_version(hba,
4066 &image->dwc, id, type, "DWC file"))) {
4067 return (rval);
4070 /* Scan for program types */
4071 NextImage = sizeof (AIF_HDR) + 4;
4072 BufferSize = AifHdr.RoSize + AifHdr.RwSize;
4074 count = 0;
4075 while (BufferSize > NextImage) {
4076 bcopy(&bptr[NextImage], &ImageHdr,
4077 sizeof (IMAGE_HDR));
4078 emlxs_dump_image_header(hba,
4079 &ImageHdr);
4081 /* Validate block size */
4082 if (ImageHdr.BlockSize == 0xffffffff) {
4083 break;
4086 type = emlxs_type_check(
4087 ImageHdr.Id.Type);
4089 /* Calculate the program offset */
4090 image->prog[type].offset =
4091 (uint32_t)((uintptr_t)
4092 &bptr[NextImage] -
4093 (uintptr_t)Buffer);
4095 /* Acquire the versions */
4096 image->prog[type].version =
4097 (ImageHdr.Id.Type << 24) |
4098 (ImageHdr.Id.Id << 16) |
4099 (ImageHdr.Id.Ver << 8) |
4100 ImageHdr.Id.Rev;
4102 image->prog[type].revcomp =
4103 ImageHdr.Id.un.revcomp;
4105 /* Validate the file version */
4106 if ((rval = emlxs_validate_version(hba,
4107 &image->prog[type], ImageHdr.Id.Id,
4108 type, "DWC prog"))) {
4109 return (rval);
4112 count++;
4113 NextImage += ImageHdr.BlockSize;
4115 } /* while () */
4117 if (count == 0) {
4118 EMLXS_MSGF(EMLXS_CONTEXT,
4119 &emlxs_image_bad_msg,
4120 "DWC file has no PRG images.");
4122 return (EMLXS_IMAGE_BAD);
4125 break;
4128 FileLen =
4129 sizeof (AIF_HDR) + ImageLength +
4130 sizeof (uint32_t);
4131 TotalLen += FileLen;
4132 bptr += FileLen;
4136 /* Pre-pegasus adapters */
4138 else if (ImageType == NOP_IMAGE_TYPE) {
4139 if (Size < sizeof (AIF_HDR)) {
4140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4141 "Invalid image header length: 0x%x < 0x%x", Size,
4142 sizeof (AIF_HDR));
4144 return (EMLXS_IMAGE_BAD);
4147 bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
4148 emlxs_disp_aif_header(hba, &AifHdr);
4150 ImageLength = AifHdr.RoSize + AifHdr.RwSize;
4152 if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
4153 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4154 "Image length incorrect: 0x%x != 0x%x", Size,
4155 sizeof (AIF_HDR) + ImageLength +
4156 sizeof (uint32_t));
4158 return (EMLXS_IMAGE_BAD);
4161 if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
4162 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4163 "Invalid imageBase value %x != 0x20000",
4164 AifHdr.ImageBase);
4166 return (EMLXS_IMAGE_BAD);
4169 CkSumEnd =
4170 (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
4171 if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4172 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4173 "Invalid checksum found.");
4175 return (EMLXS_IMAGE_BAD);
4178 image->dwc.offset = 0;
4179 image->dwc.version = AifHdr.AVersion;
4180 image->dwc.revcomp = 0;
4182 id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4183 type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
4185 /* Validate the file version */
4186 if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
4187 "DWC file"))) {
4188 return (rval);
4191 NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
4192 while (Size > NextImage) {
4193 bcopy(&Buffer[NextImage], &ImageHdr,
4194 sizeof (IMAGE_HDR));
4195 emlxs_dump_image_header(hba, &ImageHdr);
4197 /* Validate block size */
4198 if (ImageHdr.BlockSize == 0xffffffff) {
4199 break;
4202 type = emlxs_type_check(ImageHdr.Id.Type);
4204 /* Calculate the program offset */
4205 image->prog[type].offset = NextImage;
4207 /* Acquire the versions */
4208 image->prog[type].version =
4209 (ImageHdr.Id.Type << 24) |
4210 (ImageHdr.Id.Id << 16) |
4211 (ImageHdr.Id.Ver << 8) |
4212 ImageHdr.Id.Rev;
4214 image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4216 /* Validate the file version */
4217 if ((rval = emlxs_validate_version(hba,
4218 &image->prog[type], ImageHdr.Id.Id, type,
4219 "DWC prog"))) {
4220 return (rval);
4223 NextImage += ImageHdr.BlockSize;
4226 } else { /* PRG File */
4228 /* Precheck image size */
4229 if (Size < sizeof (IMAGE_HDR)) {
4230 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4231 "Invalid image header length: 0x%x < 0x%x", Size,
4232 sizeof (IMAGE_HDR));
4234 return (EMLXS_IMAGE_BAD);
4237 bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
4238 emlxs_dump_image_header(hba, &ImageHdr);
4240 /* Validate block size */
4241 if (ImageHdr.BlockSize == 0xffffffff) {
4242 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4243 "Invalid block size.");
4245 return (EMLXS_IMAGE_BAD);
4248 ImageLength = ImageHdr.BlockSize;
4250 /* Validate image length */
4251 if (Size != ImageLength) {
4252 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4253 "Invalid image length: 0x%x != 0x%x", Size,
4254 ImageLength);
4256 return (EMLXS_IMAGE_BAD);
4259 /* Validate Checksum */
4260 CkSumEnd =
4261 (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
4263 if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4264 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4265 "Invalid checksum found.");
4267 return (EMLXS_IMAGE_BAD);
4270 type = emlxs_type_check(ImageHdr.Id.Type);
4272 /* Calculate the program offset */
4273 image->prog[type].offset = 0;
4275 /* Acquire the versions */
4276 image->prog[type].version =
4277 (ImageHdr.Id.Type << 24) |
4278 (ImageHdr.Id.Id << 16) |
4279 (ImageHdr.Id.Ver << 8) |
4280 ImageHdr.Id.Rev;
4282 image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4284 /* Validate the file version */
4285 if ((rval = emlxs_validate_version(hba, &image->prog[type],
4286 ImageHdr.Id.Id, type, "DWC file"))) {
4287 return (rval);
4292 * This checks if a DragonFly (pre-V2 ASIC) SLI2
4293 * image file is < version 3.8
4295 if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
4296 ver = (image->prog[SLI2_OVERLAY].version &
4297 0x0000ff00) >> 8;
4299 if (ver >= 0x38) {
4300 EMLXS_MSGF(EMLXS_CONTEXT,
4301 &emlxs_image_incompat_msg,
4302 "ASIC Check: Image requires DragonFly "
4303 "V2 ASIC");
4305 return (EMLXS_IMAGE_INCOMPATIBLE);
4309 return (0);
4311 } /* emlxs_validate_image() */
4314 static uint32_t
4315 emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
4317 emlxs_port_t *port = &PPORT;
4318 MAILBOXQ *mbox;
4319 MAILBOX *mb;
4320 uint32_t next_address;
4321 uint32_t rval = 0;
4323 if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
4324 return (1);
4327 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4328 KM_NOSLEEP)) == NULL) {
4329 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4330 "Unable to allocate mailbox buffer.");
4332 return (1);
4335 bzero(mbox, sizeof (MAILBOXQ));
4337 mb = (MAILBOX *)mbox;
4338 mb->mbxCommand = MBX_LOAD_EXP_ROM;
4339 mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
4340 mb->un.varLdExpRom.progress = 0;
4341 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4342 mbox->mbox_cmpl = NULL;
4344 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4345 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4346 "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4347 mb->mbxCommand, mb->mbxStatus);
4349 rval = 1;
4351 goto SLI_DOWNLOAD_EXIT;
4354 if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
4355 (void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4357 rval = 1;
4358 goto SLI_DOWNLOAD_EXIT;
4361 if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
4362 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4363 "Invalid exp ROM progress. progress=%x",
4364 mb->un.varLdExpRom.progress);
4366 rval = 1;
4368 goto SLI_DOWNLOAD_EXIT;
4372 * continue Erase
4374 while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
4376 next_address = mb->un.varLdExpRom.dl_to_adr;
4378 bzero((void *)mb, MAILBOX_CMD_BSIZE);
4380 mb->mbxCommand = MBX_LOAD_EXP_ROM;
4381 mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
4382 mb->un.varLdExpRom.dl_to_adr = next_address;
4383 mb->un.varLdExpRom.progress = 0;
4384 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4385 mbox->mbox_cmpl = NULL;
4387 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4388 MBX_SUCCESS) {
4389 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4390 "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4391 mb->mbxCommand, mb->mbxStatus);
4393 rval = 1;
4394 goto SLI_DOWNLOAD_EXIT;
4399 while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
4400 next_address = mb->un.varLdExpRom.dl_to_adr;
4402 bzero((void *)mb, MAILBOX_CMD_BSIZE);
4404 mb->mbxCommand = MBX_LOAD_EXP_ROM;
4405 mb->un.varLdExpRom.step = EROM_CMD_COPY;
4406 mb->un.varLdExpRom.dl_to_adr = next_address;
4407 mb->un.varLdExpRom.progress = 0;
4408 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4409 mbox->mbox_cmpl = NULL;
4411 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4412 MBX_SUCCESS) {
4413 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4414 "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4415 mb->mbxCommand, mb->mbxStatus);
4417 rval = 1;
4419 goto SLI_DOWNLOAD_EXIT;
4423 rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4425 SLI_DOWNLOAD_EXIT:
4427 if (mbox) {
4428 kmem_free(mbox, sizeof (MAILBOXQ));
4431 return (rval);
4433 } /* emlxs_update_exp_rom() */
4438 * FUNCTION NAME: emlxs_start_abs_download_2mb
4440 * DESCRIPTION: Perform absolute download for 2 MB flash. A incoming
4441 * buffer may consist of more than 1 file. This function
4442 * will parse the buffer to find all the files.
4445 * PARAMETERS:
4448 * RETURNS:
4451 /* ARGSUSED */
4452 static uint32_t
4453 emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
4454 uint32_t offline, emlxs_fw_image_t *fw_image)
4456 emlxs_port_t *port = &PPORT;
4457 uint32_t rval = 0;
4459 /* If nothing to download then quit now */
4460 if (!fw_image->awc.version &&
4461 !fw_image->dwc.version &&
4462 !fw_image->bwc.version) {
4463 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4464 "Nothing new to update. Exiting.");
4465 return (0);
4469 * Everything checks out, now to just do it
4471 if (offline) {
4472 if (emlxs_offline(hba) != FC_SUCCESS) {
4473 return (EMLXS_OFFLINE_FAILED);
4476 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
4477 return (EMLXS_OFFLINE_FAILED);
4481 if (fw_image->awc.version) {
4482 rval = emlxs_proc_abs_2mb(hba,
4483 (buffer + fw_image->awc.offset),
4484 FILE_TYPE_AWC, 0);
4486 if (rval) {
4487 goto SLI_DOWNLOAD_2MB_EXIT;
4491 if (fw_image->bwc.version) {
4492 rval = emlxs_proc_abs_2mb(hba,
4493 (buffer + fw_image->bwc.offset),
4494 FILE_TYPE_BWC,
4495 (fw_image->dwc.version)? ALLext:BWCext);
4497 if (rval) {
4498 goto SLI_DOWNLOAD_2MB_EXIT;
4502 if (fw_image->dwc.version) {
4503 rval = emlxs_proc_rel_2mb(hba, buffer, fw_image);
4505 if (rval) {
4506 goto SLI_DOWNLOAD_2MB_EXIT;
4510 SLI_DOWNLOAD_2MB_EXIT:
4512 if (offline) {
4513 (void) emlxs_online(hba);
4516 return (rval);
4518 } /* emlxs_start_abs_download_2mb() */
4523 * FUNCTION NAME: emlxs_proc_abs_2mb
4525 * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
4526 * the port and download the file with sliIssueMbCommand()
4529 * PARAMETERS:
4532 * RETURNS:
4535 static uint32_t
4536 emlxs_proc_abs_2mb(emlxs_hba_t *hba, caddr_t EntireBuffer,
4537 uint32_t FileType, uint32_t extType)
4539 emlxs_port_t *port = &PPORT;
4540 PAIF_HDR AifHdr;
4541 caddr_t Buffer = NULL;
4542 caddr_t DataBuffer = NULL;
4543 uint32_t *Src;
4544 uint32_t *Dst;
4545 MAILBOXQ *mbox;
4546 MAILBOX *mb;
4547 uint32_t DlByteCount;
4548 uint32_t rval = 0;
4549 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
4550 uint32_t DlToAddr;
4551 uint32_t DlCount;
4552 WAKE_UP_PARMS AbsWakeUpParms;
4553 uint32_t i;
4554 uint32_t NextAddr;
4555 uint32_t EraseByteCount;
4556 uint32_t AreaId;
4557 uint32_t RspProgress = 0;
4558 uint32_t ParamsChg;
4560 AifHdr = (PAIF_HDR)EntireBuffer;
4561 DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
4562 DlToAddr = AifHdr->ImageBase;
4564 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
4565 KM_NOSLEEP)) == NULL) {
4566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4567 "%x: Unable to allocate data buffer.", FileType);
4569 return (EMLXS_IMAGE_FAILED);
4572 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4573 KM_NOSLEEP)) == NULL) {
4574 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4575 "%x: Unable to allocate mailbox buffer.", FileType);
4577 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4579 return (EMLXS_IMAGE_FAILED);
4582 mb = (MAILBOX *)mbox;
4584 Buffer = EntireBuffer + sizeof (AIF_HDR);
4586 switch (FileType) {
4587 case FILE_TYPE_AWC:
4588 ParamsChg = 0;
4589 break;
4591 case FILE_TYPE_BWC:
4592 rval = emlxs_build_parms_2mb_bwc(hba,
4593 AifHdr, extType, &AbsWakeUpParms);
4595 if (rval == FALSE) {
4596 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4597 "BWC build parms failed.");
4599 rval = EMLXS_IMAGE_FAILED;
4601 goto EXIT_ABS_DOWNLOAD;
4603 ParamsChg = 1;
4604 break;
4606 default:
4607 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4608 "Invalid file type: %x", FileType);
4610 rval = EMLXS_IMAGE_BAD;
4612 goto EXIT_ABS_DOWNLOAD;
4615 EraseByteCount = AifHdr->Area_Size;
4616 AreaId = AifHdr->Area_ID;
4618 emlxs_format_load_area_cmd(mbox,
4619 DlToAddr,
4620 EraseByteCount,
4621 ERASE_FLASH,
4622 0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
4624 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4625 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4626 "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
4627 FileType, mb->mbxCommand, mb->mbxStatus);
4629 rval = EMLXS_IMAGE_FAILED;
4631 goto EXIT_ABS_DOWNLOAD;
4634 while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
4635 NextAddr = mb->un.varLdArea.dl_to_adr;
4637 emlxs_format_load_area_cmd(mbox,
4638 NextAddr,
4639 EraseByteCount,
4640 ERASE_FLASH,
4642 DL_FROM_SLIM_OFFSET,
4643 AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
4645 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4646 MBX_SUCCESS) {
4647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4648 "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
4649 "status=%x", FileType, mb->mbxCommand,
4650 mb->mbxStatus);
4652 rval = EMLXS_IMAGE_FAILED;
4654 goto EXIT_ABS_DOWNLOAD;
4658 while (DlByteCount) {
4659 if (DlByteCount >= SegSize)
4660 DlCount = SegSize;
4661 else
4662 DlCount = DlByteCount;
4664 DlByteCount -= DlCount;
4666 Dst = (uint32_t *)DataBuffer;
4667 Src = (uint32_t *)Buffer;
4669 for (i = 0; i < (DlCount / 4); i++) {
4670 *Dst = *Src;
4671 Dst++;
4672 Src++;
4675 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
4676 (volatile uint32_t *)((volatile char *)
4677 hba->sli.sli3.slim_addr + sizeof (MAILBOX)),
4678 (DlCount / sizeof (uint32_t)));
4680 if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
4681 emlxs_format_load_area_cmd(mbox,
4682 DlToAddr,
4683 DlCount,
4684 PROGRAM_FLASH,
4685 (DlByteCount) ? 0 : 1,
4686 DL_FROM_SLIM_OFFSET,
4687 AreaId,
4688 MBX_LOAD_AREA,
4689 (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
4691 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
4692 MBX_SUCCESS) {
4693 EMLXS_MSGF(EMLXS_CONTEXT,
4694 &emlxs_download_failed_msg,
4695 "%x: Could not program 2MB Flash: Mailbox "
4696 "cmd=%x status=%x", FileType,
4697 mb->mbxCommand, mb->mbxStatus);
4699 rval = EMLXS_IMAGE_FAILED;
4701 goto EXIT_ABS_DOWNLOAD;
4705 RspProgress = mb->un.varLdArea.progress;
4707 Buffer += DlCount;
4708 DlToAddr += DlCount;
4711 #ifdef FMA_SUPPORT
4712 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
4713 != DDI_FM_OK) {
4714 EMLXS_MSGF(EMLXS_CONTEXT,
4715 &emlxs_invalid_access_handle_msg, NULL);
4717 rval = EMLXS_IMAGE_FAILED;
4719 goto EXIT_ABS_DOWNLOAD;
4721 #endif /* FMA_SUPPORT */
4723 if (RspProgress != RSP_DOWNLOAD_DONE) {
4724 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4725 "%x: Failed download response received. %x", FileType,
4726 RspProgress);
4728 rval = EMLXS_IMAGE_FAILED;
4730 goto EXIT_ABS_DOWNLOAD;
4733 if (ParamsChg) {
4734 if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
4735 &AbsWakeUpParms)) {
4736 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4737 "%x: Unable to update parms.", FileType);
4739 rval = EMLXS_IMAGE_FAILED;
4743 EXIT_ABS_DOWNLOAD:
4745 if (DataBuffer) {
4746 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
4749 if (mbox) {
4750 kmem_free(mbox, sizeof (MAILBOXQ));
4753 return (rval);
4755 } /* emlxs_proc_abs_2mb() */
4758 static void
4759 emlxs_format_load_area_cmd(MAILBOXQ * mbq,
4760 uint32_t Base,
4761 uint32_t DlByteCount,
4762 uint32_t Function,
4763 uint32_t Complete,
4764 uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
4766 MAILBOX *mb = (MAILBOX *)mbq;
4768 bzero((void *)mb, MAILBOX_CMD_BSIZE);
4770 mb->mbxCommand = MbxCmd;
4771 mb->mbxOwner = OWN_HOST;
4772 mb->un.varLdArea.update_flash = 1;
4773 mb->un.varLdArea.erase_or_prog = Function;
4774 mb->un.varLdArea.dl_to_adr = Base;
4775 mb->un.varLdArea.dl_len = DlByteCount;
4776 mb->un.varLdArea.load_cmplt = Complete;
4777 mb->un.varLdArea.method = DL_FROM_SLIM;
4778 mb->un.varLdArea.area_id = AreaId;
4779 mb->un.varLdArea.step = StepCmd;
4780 mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
4781 mbq->mbox_cmpl = NULL;
4783 } /* emlxs_format_load_area_cmd() */
4786 /* ARGSUSED */
4787 static uint32_t
4788 emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
4789 PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
4791 emlxs_port_t *port = &PPORT;
4792 uint32_t pId[2];
4793 uint32_t returnStat;
4795 /* Read wakeup paramters */
4796 if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
4797 (uint32_t)CFG_DATA_NO_REGION) {
4798 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4799 "Unable to get BWC parameters.");
4800 return (FALSE);
4803 pId[0] = AifHdr->AVersion;
4804 pId[1] = 0;
4806 if (extType == BWCext) {
4807 AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4808 AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4809 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4810 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4813 else if (extType == ALLext) {
4814 if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
4815 /* case of EROM inactive */
4816 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4817 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4818 } else {
4819 /* case of EROM active */
4820 if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
4821 /* same ID */
4822 AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
4823 AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
4824 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4825 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4826 } else {
4827 /* different ID */
4828 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
4829 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
4831 returnStat =
4832 emlxs_update_exp_rom(hba, AbsWakeUpParms);
4834 if (returnStat) {
4835 AbsWakeUpParms->u0.boot_bios_wd[0] =
4836 pId[0];
4837 AbsWakeUpParms->u0.boot_bios_wd[1] =
4838 pId[1];
4844 return (TRUE);
4846 } /* emlxs_build_parms_2mb_bwc() */
4849 extern uint32_t
4850 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
4851 uint32_t *MaxIbusSize)
4853 emlxs_port_t *port = &PPORT;
4854 MAILBOXQ *mbox;
4855 MAILBOX *mb;
4856 uint32_t *Uptr;
4857 uint32_t rval = 0;
4859 if (MaxRbusSize) {
4860 *MaxRbusSize = 0;
4863 if (MaxIbusSize) {
4864 *MaxIbusSize = 0;
4867 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4868 KM_NOSLEEP)) == NULL) {
4869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4870 "Unable to allocate mailbox buffer.");
4872 return (1);
4875 mb = (MAILBOX *)mbox;
4877 emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
4879 if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) !=
4880 MBX_SUCCESS) {
4881 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4882 "Unable to get SRAM size: Mailbox cmd=%x status=%x",
4883 mb->mbxCommand, mb->mbxStatus);
4885 rval = 1;
4887 goto Exit_Function;
4890 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4891 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
4892 hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
4893 Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
4894 } else {
4895 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
4898 if (MaxRbusSize) {
4899 *MaxRbusSize = Uptr[0];
4902 if (MaxIbusSize) {
4903 *MaxIbusSize = Uptr[1];
4906 Exit_Function:
4908 if (mbox) {
4909 kmem_free(mbox, sizeof (MAILBOXQ));
4912 #ifdef FMA_SUPPORT
4913 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4914 if (emlxs_fm_check_dma_handle(hba,
4915 hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
4916 EMLXS_MSGF(EMLXS_CONTEXT,
4917 &emlxs_invalid_dma_handle_msg,
4918 "emlxs_get_max_sram: hdl=%p",
4919 hba->sli.sli4.dump_region.dma_handle);
4920 rval = 1;
4923 #endif /* FMA_SUPPORT */
4925 return (rval);
4927 } /* emlxs_get_max_sram() */
4930 static uint32_t
4931 emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
4933 uint8_t *ptr;
4934 uint8_t ver;
4936 ver = version & 0xff;
4937 ptr = hba->model_info.pt_FF;
4939 while (*ptr) {
4940 if (*ptr++ == ver) {
4941 return (1);
4945 return (0);
4947 } /* emlxs_kern_check() */
4949 static uint32_t
4950 emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
4952 uint8_t *ptr;
4953 uint8_t ver;
4955 ver = version & 0xff;
4956 ptr = hba->model_info.pt_2;
4958 while (*ptr) {
4959 if (*ptr++ == ver) {
4960 return (1);
4964 return (0);
4966 } /* emlxs_stub_check() */
4968 static uint32_t
4969 emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
4971 uint8_t *ptr;
4972 uint8_t ver;
4974 ver = version & 0xff;
4975 ptr = hba->model_info.pt_3;
4977 while (*ptr) {
4978 if (*ptr++ == ver) {
4979 return (1);
4983 return (0);
4985 } /* emlxs_bios_check() */
4987 static uint32_t
4988 emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
4990 uint8_t *ptr;
4991 uint8_t ver;
4993 ver = version & 0xff;
4994 ptr = hba->model_info.pt_6;
4996 while (*ptr) {
4997 if (*ptr++ == ver) {
4998 return (1);
5002 return (0);
5004 } /* emlxs_sli1_check() */
5006 static uint32_t
5007 emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version)
5009 uint8_t *ptr;
5010 uint8_t ver;
5012 ver = version & 0xff;
5013 ptr = hba->model_info.pt_7;
5015 while (*ptr) {
5016 if (*ptr++ == ver) {
5017 return (1);
5021 return (0);
5023 } /* emlxs_sli2_check() */
5025 static uint32_t
5026 emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
5028 uint8_t *ptr;
5029 uint8_t ver;
5031 ver = version & 0xff;
5032 ptr = hba->model_info.pt_B;
5034 while (*ptr) {
5035 if (*ptr++ == ver) {
5036 return (1);
5040 return (0);
5042 } /* emlxs_sli3_check() */
5045 static uint32_t
5046 emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
5048 uint8_t *ptr;
5049 uint8_t ver;
5051 ver = version & 0xff;
5052 ptr = hba->model_info.pt_E;
5054 while (*ptr) {
5055 if (*ptr++ == ver) {
5056 return (1);
5060 return (0);
5062 } /* emlxs_sli4_check() */
5065 static uint32_t
5066 emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
5068 uint8_t *ptr;
5069 uint8_t ver;
5071 ver = version & 0xff;
5072 ptr = hba->model_info.pt_A;
5074 while (*ptr) {
5075 if (*ptr++ == ver) {
5076 return (1);
5080 return (0);
5082 } /* emlxs_sbus_fcode_check() */
5085 static uint32_t
5086 emlxs_type_check(uint32_t type)
5088 if (type == 0xff) {
5089 return (KERNEL_CODE);
5092 if (type >= MAX_PROG_TYPES) {
5093 return (RESERVED_D);
5096 return (type);
5098 } /* emlxs_type_check() */
5101 extern int32_t
5102 emlxs_boot_code_disable(emlxs_hba_t *hba)
5104 emlxs_port_t *port = &PPORT;
5105 PROG_ID Id;
5106 emlxs_vpd_t *vpd;
5108 vpd = &VPD;
5110 if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5111 (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5112 return (EMLXS_OP_NOT_SUP);
5115 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5116 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5117 "emlxs_boot_code_disable: Unable to read wake up parms.");
5119 return (FC_FAILURE);
5122 /* Check if boot code is already disabled */
5123 if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
5124 return (FC_SUCCESS);
5127 /* Make sure EROM entry has copy of boot bios entry */
5128 if (!(hba->model_info.chip &
5129 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
5130 (hba->wakeup_parms.u0.boot_bios_wd[0] !=
5131 hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
5132 (hba->wakeup_parms.u0.boot_bios_wd[1] !=
5133 hba->wakeup_parms.u1.EROM_prog_wd[1])) {
5134 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
5135 &hba->wakeup_parms.u0.boot_bios_id, 1);
5138 /* Update the bios id with a zero id */
5139 /* Don't load the EROM this time */
5140 bzero(&Id, sizeof (PROG_ID));
5141 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0);
5143 /* Now read the parms again to verify */
5144 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5145 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5146 vpd->boot_version);
5147 /* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5149 /* Return the result */
5150 return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
5151 FC_SUCCESS : FC_FAILURE);
5153 } /* emlxs_boot_code_disable() */
5156 extern int32_t
5157 emlxs_boot_code_enable(emlxs_hba_t *hba)
5159 emlxs_port_t *port = &PPORT;
5160 emlxs_vpd_t *vpd;
5161 PROG_ID load_list[MAX_LOAD_ENTRY];
5162 uint32_t i;
5163 uint32_t count;
5165 vpd = &VPD;
5167 if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5168 (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5169 return (FC_SUCCESS);
5172 /* Read the wakeup parms */
5173 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5174 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5175 "emlxs_boot_code_enable: Unable to read wake up parms.");
5177 return (FC_FAILURE);
5180 /* Check if boot code is already enabled */
5181 if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
5182 return (FC_SUCCESS);
5185 if (!(hba->model_info.chip &
5186 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
5187 if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) {
5188 return (EMLXS_NO_BOOT_CODE);
5191 /* Update the parms with the boot image id */
5192 /* Don't load the EROM this time */
5193 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms,
5194 &hba->wakeup_parms.u1.EROM_prog_id, 0);
5195 } else { /* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
5197 count = emlxs_get_load_list(hba, load_list);
5199 if (!count) {
5200 return (FC_FAILURE);
5203 /* Scan load list for a boot image */
5204 for (i = 0; i < count; i++) {
5205 if (load_list[i].Type == BOOT_BIOS) {
5206 /* Update the parms with the boot image id */
5207 /* Don't load the EROM this time */
5208 (void) emlxs_update_boot_wakeup_parms(hba,
5209 &hba->wakeup_parms, &load_list[i], 0);
5211 break;
5215 if (i == count) {
5216 return (EMLXS_NO_BOOT_CODE);
5220 /* Now read the parms again to verify */
5221 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5222 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5223 vpd->boot_version);
5224 /* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5226 /* return the result */
5227 return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5228 FC_SUCCESS : FC_FAILURE);
5230 } /* emlxs_boot_code_enable() */
5234 extern int32_t
5235 emlxs_boot_code_state(emlxs_hba_t *hba)
5237 emlxs_port_t *port = &PPORT;
5239 if ((hba->model_info.chip == EMLXS_BE2_CHIP) ||
5240 (hba->model_info.chip == EMLXS_BE3_CHIP)) {
5241 return (FC_SUCCESS);
5244 /* Read the wakeup parms */
5245 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
5246 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5247 "emlxs_boot_code_state: Unable to read wake up parms.");
5249 return (FC_FAILURE);
5252 /* return the result */
5253 return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5254 FC_SUCCESS : FC_FAILURE);
5256 } /* emlxs_boot_code_state() */