emlxs_download.c revision b3660a963b4e1d5319365d4d7c34beb66fb5abc7
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Emulex. All rights reserved.
* Use is subject to license terms.
*/
#include <emlxs.h>
/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
#define MAX_BOOTID 10
char *file_type);
/* ************************************************************************* */
extern int32_t
{
int32_t AbsChangeParams = 0;
uint32_t i;
#ifdef EMLXS_LITTLE_ENDIAN
#endif /* EMLXS_LITTLE_ENDIAN */
return (rval);
}
return (EMLXS_IMAGE_BAD);
}
#ifdef EMLXS_LITTLE_ENDIAN
/* We need to swap the image buffer before we start */
/*
* Use KM_SLEEP to allocate a temporary buffer
*/
/* Perform a 32 bit swap of the image */
for (i = 0; i < (len / 4); i++) {
bptr1++;
bptr2++;
}
/* Replace the original buffer */
#endif /* EMLXS_LITTLE_ENDIAN */
for (i = 0; i < MAX_PROG_TYPES; i++) {
}
/* Validate image */
goto done;
}
/* Get image type */
/*
* Pegasus and beyond FW download is done differently
* for absolute download.
*/
/* Check for absolute image */
if ((ImageType == NOP_IMAGE_TYPE) &&
/*
* Because 2Mb flash download file format is different from
* 512k, it needs to be handled differently
*/
goto done;
}
/* Offline already handled */
offline = 0;
goto SLI_DOWNLOAD_EXIT;
}
/* Pre-pegasus adapters only */
/* Check for absolute image */
else if (ImageType == NOP_IMAGE_TYPE) {
}
} else { /* (ImageType != NOP_IMAGE_TYPE) Relative image */
}
/*
* Everything checks out, now to just do it
*/
if (offline) {
offline = 0;
"Unable to take adapter offline.");
goto SLI_DOWNLOAD_EXIT;
}
offline = 0;
"Unable to restart adapter.");
goto SLI_DOWNLOAD_EXIT;
}
}
/* Erase Flash */
if (emlxs_erase_fcode_flash(hba)) {
"Unable to erase flash.");
goto SLI_DOWNLOAD_EXIT;
}
/* Write FCODE */
"Unable to write flash.");
goto SLI_DOWNLOAD_EXIT;
}
} else { /* !SBUS_FCODE */
"Unable to get parameters.");
goto SLI_DOWNLOAD_EXIT;
}
&MaxIbusSramSize)) {
"Unable to get RAM size.");
goto SLI_DOWNLOAD_EXIT;
}
if (ImageType == NOP_IMAGE_TYPE) {
DwcFile)) {
"Failed to program flash.");
goto SLI_DOWNLOAD_EXIT;
}
} else {
"Failed to program flash.");
goto SLI_DOWNLOAD_EXIT;
}
}
} /* !SBUS_FCODE */
if (offline) {
(void) emlxs_online(hba);
}
if (rval == 0) {
"Status good.");
}
done:
#ifdef EMLXS_LITTLE_ENDIAN
/* Free the local buffer */
#endif /* EMLXS_LITTLE_ENDIAN */
return (rval);
} /* emlxs_fw_download */
static void
{
while (size--) {
}
} /* emlxs_memset () */
static int32_t
{
if (file->image_size == 0) {
return (0);
}
block_offset = 0;
while (block_size) {
/* Build data buffer payload */
/* Copy remaining image into payload */
if (image_size) {
image_size -= count;
}
/* Set last two words of last payload with */
/* image size and block crc */
}
/* Send write request */
MBX_SUCCESS) {
"%s: Unable to download image. status=%x",
goto done;
}
block_size -= xfer_size;
}
done:
return (rval);
} /* emlxs_sli4_flash_image() */
static int32_t
{
uint32_t i;
char signature[BE_SIGNATURE_SIZE];
/* Check for special deflated format */
sizeof (signature)-1) == 0) {
ufi_plus = 1;
}
block_offset = 0;
while (block_size) {
/* Send read request */
MBX_SUCCESS) {
"%s: Unable to read image. status=%x",
goto done;
}
"%s: Image mismatch. [%08x] %x, %x",
"%08x: %08x %08x %08x %08x %08x " \
"%08x %08x %08x",
wptr[7]);
"%08x: %08x %08x %08x %08x %08x " \
"%08x %08x %08x",
wptr1[7]);
goto done;
}
}
block_size -= xfer_size;
}
/* Verify CRC */
done:
if (rval == 0) {
}
return (rval);
} /* emlxs_sli4_verify_image() */
static int32_t
{
xfer_size = 8;
/* Send read request */
MBX_SUCCESS) {
"%s: Unable to read CRC. status=%x",
goto done;
}
/* Verify image size */
"%s: Image size mismatch. %08x != %08x",
goto done;
}
/* Verify block crc */
"%s: CRC mismatch. %08x != %08x",
}
done:
if (rval == 0) {
}
return (rval);
} /* emlxs_sli4_verify_crc() */
extern int32_t
{
"read_fw_version: Unable to allocate mailbox buffer.");
rval = 1;
goto done;
}
"read_fw_version: Unable to allocate payload buffer.");
goto done;
}
/* Read CRC and size */
xfer_size = 8;
/* Send read request */
MBX_SUCCESS) {
"read_fw_version: Unable to read CRC. status=%x",
rval = 1;
goto done;
}
/* Read version label */
xfer_size = 32;
block_offset = 0x30;
/* Send read request */
MBX_SUCCESS) {
"read_fw_version: Unable to read version string. status=%x",
rval = 1;
goto done;
}
"FCOE FIRMWARE: size=%x version=%s (0x%08x)",
done:
if (mbq) {
}
if (mp) {
}
return (rval);
} /* emlxs_sli4_read_fw_version() */
static uint32_t
{
uint32_t i;
uint32_t k;
char signature[BE_SIGNATURE_SIZE];
"Invalid adapter model.");
return (EMLXS_IMAGE_INCOMPATIBLE);
}
if (len < (sizeof (emlxs_sli4_ufi_header_t) +
sizeof (emlxs_sli4_flash_dir_t))) {
"Image too small. (%d < %d)",
len, (sizeof (emlxs_sli4_ufi_header_t) +
sizeof (emlxs_sli4_flash_dir_t)));
return (EMLXS_IMAGE_BAD);
}
/* Check if this is a standard UFI image */
sizeof (BE_SIGNATURE)-1) != 0) {
"Invalid image provided.");
return (EMLXS_IMAGE_INCOMPATIBLE);
}
/* Check for special deflated format */
sizeof (signature)-1) == 0) {
ufi_plus = 1;
}
#ifdef EMLXS_BIG_ENDIAN
/* Big Endian Swapping */
/* Swap ufi header */
#endif /* EMLXS_BIG_ENDIAN */
"Invalid image size (%d != %d)",
return (EMLXS_IMAGE_BAD);
}
/* Scan for flash dir signature */
sizeof (BE_DIR_SIGNATURE)) == 0) {
break;
}
}
if (!flash_dir) {
"Unable to find flash directory.");
return (EMLXS_IMAGE_BAD);
}
#ifdef EMLXS_BIG_ENDIAN
/* Big Endian Swapping */
/* Swap flash dir */
for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
}
continue;
}
if (entry->image_size == 0) {
continue;
}
}
#endif /* EMLXS_BIG_ENDIAN */
/* Build fw_image table */
continue;
}
if (entry->image_size == 0) {
continue;
}
case BE_FLASHTYPE_REDBOOT:
break;
case BE_FLASHTYPE_ISCSI_BIOS:
break;
case BE_FLASHTYPE_PXE_BIOS:
break;
case BE_FLASHTYPE_FCOE_BIOS:
break;
break;
break;
case BE_FLASHTYPE_FCOE_BACKUP:
continue;
default:
"Unknown image type found. type=%x",
continue;
}
if (ufi_plus) {
} else {
sizeof (emlxs_sli4_ufi_header_t);
/* Get entry block size and crc */
k &= 0xFFFFFFFC;
for (; k < len; k += 4) {
if (*wptr++ == image_size) {
/* Calculate block_size */
/* Read block_crc */
break;
}
}
if (k >= len) {
"%s: End of block not found. offset=%x",
return (EMLXS_IMAGE_BAD);
}
}
/* Make sure image will fit in block specified */
"%s: Image too large for block. image=%x block=%x",
return (EMLXS_IMAGE_BAD);
}
/* Automatically create a backup file entry for firmware */
/* Save FCOE version info */
}
}
"Unable to find FCOE firmware component.");
return (EMLXS_IMAGE_BAD);
}
/* Display contents */
for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
if (file->image_size == 0) {
continue;
}
"%s: type=%x block=%x image=%x offset=%x crc=%x",
}
return (0);
} /* emlxs_sli4_validate_image() */
static int32_t
{
uint32_t i;
/* For now we will not take the driver offline during a download */
offline = 0;
return (EMLXS_IMAGE_INCOMPATIBLE);
}
return (EMLXS_IMAGE_BAD);
}
/* Validate image */
return (rval);
}
/* Allocate resources */
"Unable to allocate mailbox buffer.");
offline = 0;
goto done;
}
"Unable to allocate flash buffer.");
offline = 0;
goto done;
}
/* Check if update is required */
for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
if (file->image_size == 0) {
continue;
}
if (rval == 0) {
file->image_size = 0;
continue;
}
update++;
}
if (!update) {
offline = 0;
goto done;
}
/*
* Everything checks out, now to just do it
*/
if (offline) {
"Unable to take adapter offline.");
offline = 0;
goto done;
}
}
/* Download entries which require update */
for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
if (file->image_size == 0) {
continue;
}
if (rval != 0) {
goto done;
}
}
done:
if (mbq) {
}
if (mp) {
}
if (offline) {
(void) emlxs_online(hba);
}
if (rval == 0) {
if (update) {
"Status good.");
"Please reboot system or power cycle adapter "
} else {
"No firmware update required.");
}
}
return (rval);
} /* emlxs_sli4_fw_download() */
extern int32_t
{
#ifdef EMLXS_BIG_ENDIAN
uint32_t i;
#endif /* EMLXS_BIG_ENDIAN */
return (EMLXS_IMAGE_BAD);
}
#ifdef EMLXS_BIG_ENDIAN
/* We need to swap the image buffer before we start */
/*
* Use KM_SLEEP to allocate a temporary buffer
*/
/* Perform a 32 bit swap of the image */
for (i = 0; i < (len / 4); i++) {
bptr1++;
bptr2++;
}
/* Replace the original buffer */
#endif /* EMLXS_BIG_ENDIAN */
if (len > 128) {
"Invalid image length: 0x%x > 128", len);
return (EMLXS_IMAGE_BAD);
}
/* Check the region number */
"Invalid region id: 0x%x", region);
return (EMLXS_IMAGE_BAD);
}
/* Check the image vendor id */
"Invalid image id: 0x%x", id);
return (EMLXS_IMAGE_BAD);
}
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
rval = 1;
goto done;
}
/*
* Everything checks out, now to just do it
*/
"Unable to take HBA offline.");
goto done;
}
"Unable to restart adapter.");
goto done;
}
/* Check if default region is requested */
if (region == 0xff) {
/*
* Sun-branded Helios and Zypher have different
* default PCI region
*/
(EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
region = 2;
} else {
region = 0;
}
}
/* Set region id based on PCI region requested */
"PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
/* Copy the data buffer to SLIM */
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
rval = 1;
}
#endif /* FMA_SUPPORT */
"Unable to update PCI configuration: Mailbox cmd=%x "
rval = 1;
}
(void) emlxs_online(hba);
if (rval == 0) {
"Status good.");
}
done:
if (mbox) {
}
#ifdef EMLXS_BIG_ENDIAN
/* Free the local buffer */
#endif /* EMLXS_BIG_ENDIAN */
return (rval);
} /* emlxs_cfl_download */
static uint32_t
{
EndAddr++;
StartAddr++;
}
} /* emlxs_valid_cksum() */
static void
{
} /* emlxs_disp_aif_header() */
static void
{
} /* emlxs_dump_image_header() */
static void
{
/* Clear the local dump_region */
} else {
}
return;
} /* emlxs_format_dump() */
/* ARGSUSED */
static uint32_t
{
uint32_t i;
"Performing absolute download...");
KM_NOSLEEP)) == NULL) {
"Unable to allocate data buffer.");
return (rval);
}
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (rval);
}
if (DwcFile) {
0, 0, NULL);
} else {
ERASE_FLASH, 0, 0, 0, NULL);
}
"Unable to erase Flash: Mailbox cmd=%x status=%x",
rval = 1;
goto EXIT_ABS_DOWNLOAD;
}
"Programming flash...");
while (DlByteCount) {
if (DlByteCount > SegSize) {
} else {
}
DlByteCount -= DlCount;
for (i = 0; i < (DlCount / 4); i++) {
Dst++;
Src++;
}
(volatile uint32_t *)
MBX_SUCCESS) {
"Unable to program Flash: Mailbox cmd=%x status=%x",
rval = 1;
goto EXIT_ABS_DOWNLOAD;
}
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
rval = 1;
goto EXIT_ABS_DOWNLOAD;
}
#endif /* FMA_SUPPORT */
switch (MaxRbusSramSize) {
case REDUCED_RBUS_SRAM_CFG:
break;
case FULL_RBUS_SRAM_CFG:
break;
default:
break;
}
if (AbsWakeUpParms) {
rval =
} else {
rval =
}
if (DataBuffer) {
}
if (mbox) {
}
return (rval);
} /* emlxs_start_abs_download() */
/* ARGSUSED */
static void
{
if (ProgId)
else
if (BdeSize) {
} else if (ProgId) {
} else {
}
} /* emlxs_format_prog_flash() */
static void
{
sizeof (WAKE_UP_PARMS));
} /* emlxs_format_update_parms () */
/* ARGSUSED */
static void
{
} /* emlxs_format_update_pci_cfg() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
}
"Unable to update boot wakeup parms: Mailbox cmd=%x "
rval = 1;
}
if (mbox) {
}
return (rval);
} /* emlxs_update_boot_wakeup_parms() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to update wakeup parameters: Mailbox cmd=%x "
rval = 1;
}
if (mbox) {
}
return (rval);
} /* emlxs_update_ff_wakeup_parms() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to update wakeup parameters. Mailbox cmd=%x "
rval = 1;
}
if (mbox) {
}
return (rval);
} /* emlxs_update_sli1_wakeup_parms() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to update wakeup parameters. Mailbox cmd=%x "
rval = 1;
}
if (mbox) {
}
return (rval);
} /* emlxs_update_sli2_wakeup_parms() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to update wakeup parameters. Mailbox cmd=%x "
rval = 1;
}
if (mbox) {
}
return (rval);
} /* emlxs_update_sli3_wakeup_parms() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to update wakeup parameters. Mailbox cmd=%x "
rval = 1;
}
if (mbox) {
}
return (rval);
} /* emlxs_update_sli4_wakeup_parms() */
/* ARGSUSED */
static uint32_t
{
uint32_t i;
"Performing relative download...");
KM_NOSLEEP)) == NULL) {
"Unable to allocate data buffer.");
return (rval);
}
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (rval);
}
switch (MaxRbusSramSize) {
case REDUCED_RBUS_SRAM_CFG:
"Invalid header id.");
return (1);
}
break;
case FULL_RBUS_SRAM_CFG:
"Invalid header id.");
return (1);
}
break;
default:
"Invalid header id.");
return (1);
}
break;
}
}
"Unable to erase flash. Mailbox cmd=%x status=%x",
rval = 1;
goto EXIT_REL_DOWNLOAD;
}
"Programming flash...");
while (DlByteCount) {
if (DlByteCount > SegSize) {
} else {
}
DlByteCount -= DlCount;
for (i = 0; i < (DlCount / 4); i++) {
Dst++;
Src++;
}
(volatile uint32_t *)
0,
MBX_SUCCESS) {
"Unable to program flash. Mailbox cmd=%x status=%x",
rval = 1;
goto EXIT_REL_DOWNLOAD;
}
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
rval = 1;
goto EXIT_REL_DOWNLOAD;
}
#endif /* FMA_SUPPORT */
case TEST_PROGRAM:
rval = 0;
break;
case FUNC_FIRMWARE:
"FF: Updating parms...");
rval =
break;
case BOOT_BIOS:
"BOOT: Updating parms...");
rval =
break;
case SLI1_OVERLAY:
"SLI1: Updating parms...");
rval =
break;
case SLI2_OVERLAY:
"SLI2: Updating parms...");
rval =
break;
case SLI3_OVERLAY:
"SLI3: Updating parms...");
rval =
break;
case SLI4_OVERLAY:
"SLI4: Updating parms...");
rval =
break;
default:
break;
}
if (DataBuffer) {
}
if (mbox) {
}
return (rval);
} /* emlxs_start_rel_download() */
#define FLASH_POLLING_BIT 0x80
#define FLASH_ERROR_BIT 0x20
typedef struct _flash_t
{
} flash_t;
static uint32_t
{
uint32_t i;
uint32_t j;
uint32_t k;
{0x555, 0xaa},
{0x2aa, 0x55},
{0x555, 0xa0}
};
/* Load Fcode */
for (i = 0; i < DlByteCount; i++) {
for (k = 0; k < 3; k++) {
}
/* Reverse Endian word alignment */
j = (i & 3) ^ 3;
if (j == 0) {
src += 4;
}
/* check for complete */
for (;;) {
DELAYUS(20);
/* If data matches then continue */
break;
}
/* Polling bit will be inverse final value */
/* while active */
/* Still busy */
/* Check for error bit */
if (cc & FLASH_ERROR_BIT) {
/* Read data one more time */
/* Check if data matches */
break;
}
"FCode write error: offset:%x "
return (1);
}
}
}
}
/* Load Header */
for (k = 0; k < 3; k++) {
}
/* Reverse Endian word alignment */
j = (i & 3) ^ 3;
if (j == 0) {
src += 4;
}
/* check for complete */
for (;;) {
DELAYUS(20);
/* If data matches then continue */
break;
}
/* Polling bit will be inverse final value */
/* while active */
/* Still busy */
/* Check for error bit */
if (cc & FLASH_ERROR_BIT) {
/* Read data one more time */
/* Check if data matches */
break;
}
"FCode write error: offset:%x "
return (1);
}
}
}
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
return (1);
}
#endif /* FMA_SUPPORT */
return (0);
} /* emlxs_write_fcode_flash() */
static uint32_t
{
int32_t i, j;
{0x555, 0xaa},
{0x2aa, 0x55},
{0x555, 0x80},
{0x555, 0xaa},
{0x2aa, 0x55},
{0x555, 0x10}
};
/* Auto select */
{0x555, 0xaa},
{0x2aa, 0x55},
{0x555, 0x90}
};
/* Check Manufacturers Code */
for (i = 0; i < 3; i++) {
}
/* Check Device Code */
for (i = 0; i < 3; i++) {
}
/* Check block protections (up to 4 16K blocks = 64K) */
for (j = 0; j < 4; j++) {
for (i = 0; i < 3; i++) {
}
if (cc == 0x01) {
"Block %d is protected and can't be erased.", j);
}
}
/* Write erase flash sequence */
for (i = 0; i < 6; i++) {
}
/* check for complete */
for (;;) {
/* Delay 3 seconds */
DELAYMS(3000);
/* If data matches then continue; */
if (cc == 0xff) {
break;
}
/* Polling bit will be inverse final value while active */
/* Still busy */
/* Check for error bit */
if (cc & FLASH_ERROR_BIT) {
/* Read data one more time */
/* Check if data matches */
if (cc == 0xff) {
break;
}
"FCode write error: offset:%x wrote:%x "
return (1);
}
}
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
return (1);
}
#endif /* FMA_SUPPORT */
return (0);
} /* emlxs_erase_fcode_flash() */
extern uint32_t
{
uint32_t i;
KM_NOSLEEP)) == NULL) {
"Unable to allocate LOADLIST buffer.");
rval = 1;
goto done;
}
rval = 1;
goto done;
}
"Load List[%d]: %08x %08x", i,
}
}
done:
if (LoadList) {
}
return (rval);
} /* emlxs_get_load_list() */
extern uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
"Unable to get parameters: Mailbox cmd=%x status=%x",
} else {
rval = 1;
}
} else {
} else {
}
if (verbose) {
"Wakeup: sli3_prog_id=%08x %08x", wd[0],
wd[1]);
}
"Wakeup: sli4_prog_id=%08x %08x", wd[0],
wd[1]);
}
"Wakeup: pci_cfg_rsvd=%x",
"Wakeup: use_hdw_def=%x",
"Wakeup: pci_cfg_sel=%x",
"Wakeup: cfg_lookup=%x",
}
}
done:
if (mbox) {
}
#ifdef FMA_SUPPORT
"emlxs_read_wakeup_parms: hdl=%p",
rval = 1;
}
}
#endif /* FMA_SUPPORT */
return (rval);
} /* emlxs_read_wakeup_parms() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to get load list: Mailbox cmd=%x status=%x",
goto done;
}
} else {
}
while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
MBX_SUCCESS) {
"Unable to get load list (%d): Mailbox cmd=%x "
goto done;
}
} else {
}
/* update next current load entry address */
} /* end of while (not end of list) */
done:
if (mbox) {
}
#ifdef FMA_SUPPORT
"emlxs_read_load_list: hdl=%p",
return (1);
}
}
#endif /* FMA_SUPPORT */
return (0);
} /* emlxs_read_load_list() */
static uint32_t
{
return (0xffffffff);
return (Version);
} /* emlxs_get_abs_image_type() */
static uint32_t
{
uint32_t i;
while (BufferSize > NextImage) {
for (i = 0; i < sizeof (IMAGE_HDR); i++) {
}
break;
case 6:
case 7:
if (HwId == 0xffffffff) {
}
"Invalid hardware id. %x %x", HwId,
}
break;
}
}
return (HwId);
} /* emlxs_get_dwc_image_type() */
static int
{
uint32_t i;
return (FALSE);
}
while (BufferSize > NextImage) {
for (i = 0; i < sizeof (IMAGE_HDR); i++) {
}
break;
case TEST_PROGRAM:
break;
case FUNC_FIRMWARE:
ChangeParams = TRUE;
break;
case BOOT_BIOS:
ChangeParams = TRUE;
break;
case SLI1_OVERLAY:
ChangeParams = TRUE;
break;
case SLI2_OVERLAY:
ChangeParams = TRUE;
break;
case SLI3_OVERLAY:
ChangeParams = TRUE;
break;
case SLI4_OVERLAY:
ChangeParams = TRUE;
break;
default:
break;
}
}
return (ChangeParams);
} /* emlxs_build_parms() */
static uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to update wakeup parameters: Mailbox cmd=%x "
rval = 1;
}
if (mbox) {
}
return (rval);
} /* emlxs_update_wakeup_parms() */
static uint32_t
{
/* Create the version label */
/* Process the DWC type */
switch (type) {
case TEST_PROGRAM:
"%s: TEST: offset=%08x version=%08x, %s", file_type,
break;
case BOOT_BIOS:
"%s: BOOT: offset=%08x version=%08x, %s", file_type,
"BOOT Check: Image not compatible with %s. id=%02x",
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
case FUNC_FIRMWARE: /* Stub */
"%s: STUB: offset=%08x version=%08x, %s", file_type,
"STUB Check: Image not compatible with %s. id=%02x",
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
case SLI1_OVERLAY:
"%s: SLI1: offset=%08x version=%08x, %s", file_type,
"SLI1 Check: Image not compatible with %s. id=%02x",
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
case SLI2_OVERLAY:
"%s: SLI2: offset=%08x version=%08x, %s", file_type,
"SLI2 Check: Image not compatible with %s. id=%02x",
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
case SLI3_OVERLAY:
"%s: SLI3: offset=%08x version=%08x, %s", file_type,
"SLI3 Check: Image not compatible with %s. id=%02x",
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
case SLI4_OVERLAY:
"%s: SLI4: offset=%08x version=%08x, %s", file_type,
"SLI4 Check: Image not compatible with %s. id=%02x",
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
case SBUS_FCODE:
"%s: SBUS FCODE: offset=%08x version=%08x, %s",
"SBUS FCODE Check: Image not compatible with %s. "
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
case KERNEL_CODE:
"%s: KERN: offset=%08x version=%08x, %s", file_type,
"KERN Check: Image not compatible with %s. id=%02x",
return (EMLXS_IMAGE_INCOMPATIBLE);
}
break;
default:
return (EMLXS_IMAGE_BAD);
}
return (0);
} /* emlxs_validate_version() */
static uint32_t
{
/* Get image type */
/* Pegasus and beyond adapters */
if ((ImageType == NOP_IMAGE_TYPE) &&
"Invalid image header length: 0x%x < 0x%x",
return (EMLXS_IMAGE_BAD);
}
/* Validate checksum */
CkSumEnd =
sizeof (AIF_HDR));
"Invalid checksum found.");
return (EMLXS_IMAGE_BAD);
}
switch (FileType) {
case FILE_TYPE_AWC:
/* Validate the file version */
return (rval);
}
break;
case FILE_TYPE_BWC:
/* Validate the file version */
return (rval);
}
break;
case FILE_TYPE_DWC:
/* Validate the file version */
return (rval);
}
/* Scan for program types */
while (BufferSize > NextImage) {
sizeof (IMAGE_HDR));
&ImageHdr);
/* Validate block size */
break;
}
/* Calculate the program offset */
/* Acquire the versions */
/* Validate the file version */
type, "DWC prog"))) {
return (rval);
}
} /* while () */
break;
}
FileLen =
sizeof (AIF_HDR) + ImageLength +
sizeof (uint32_t);
}
}
/* Pre-pegasus adapters */
else if (ImageType == NOP_IMAGE_TYPE) {
"Invalid image header length: 0x%x < 0x%x", Size,
sizeof (AIF_HDR));
return (EMLXS_IMAGE_BAD);
}
"Image length incorrect: 0x%x != 0x%x", Size,
sizeof (AIF_HDR) + ImageLength +
sizeof (uint32_t));
return (EMLXS_IMAGE_BAD);
}
"Invalid imageBase value %x != 0x20000",
return (EMLXS_IMAGE_BAD);
}
CkSumEnd =
"Invalid checksum found.");
return (EMLXS_IMAGE_BAD);
}
/* Validate the file version */
"DWC file"))) {
return (rval);
}
sizeof (IMAGE_HDR));
/* Validate block size */
break;
}
/* Calculate the program offset */
/* Acquire the versions */
/* Validate the file version */
"DWC prog"))) {
return (rval);
}
}
} else {
/* Precheck image size */
"Invalid image header length: 0x%x < 0x%x", Size,
sizeof (IMAGE_HDR));
return (EMLXS_IMAGE_BAD);
}
/* Validate block size */
"Invalid block size.");
return (EMLXS_IMAGE_BAD);
}
/* Validate image length */
if (Size != ImageLength) {
"Invalid image length: 0x%x != 0x%x", Size,
return (EMLXS_IMAGE_BAD);
}
/* Validate Checksum */
CkSumEnd =
1;
"Invalid checksum found.");
return (EMLXS_IMAGE_BAD);
}
/* Calculate the program offset */
/* Acquire the versions */
/* Validate the file version */
return (rval);
}
}
/*
* This checks if a DragonFly (pre-V2 ASIC) SLI2
* image file is greater than version 3.8
*/
0x0000ff00) >> 8;
"ASIC Check: Image requires DragonFly "
"V2 ASIC");
return (EMLXS_IMAGE_INCOMPATIBLE);
}
}
}
return (0);
} /* emlxs_validate_image() */
static uint32_t
{
return (1);
}
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
"Unable to load exp ROM. Mailbox cmd=%x status=%x",
rval = 1;
goto SLI_DOWNLOAD_EXIT;
}
rval = 1;
goto SLI_DOWNLOAD_EXIT;
}
"Invalid exp ROM progress. progress=%x",
rval = 1;
goto SLI_DOWNLOAD_EXIT;
}
/*
* continue Erase
*/
MBX_SUCCESS) {
"Unable to load exp ROM. Mailbox cmd=%x status=%x",
rval = 1;
goto SLI_DOWNLOAD_EXIT;
}
}
MBX_SUCCESS) {
"Unable to load exp ROM. Mailbox cmd=%x status=%x",
rval = 1;
goto SLI_DOWNLOAD_EXIT;
}
}
if (mbox) {
}
return (rval);
} /* emlxs_update_exp_rom() */
/*
*
* FUNCTION NAME: emlxs_start_abs_download_2mb
*
* DESCRIPTION: Perform absolute download for 2 MB flash. A incoming
* buffer may consist of more than 1 file. This function
* will parse the buffer to find all the files.
*
*
* PARAMETERS:
*
*
* RETURNS:
*
*/
/* ARGSUSED */
static uint32_t
{
uint32_t i;
/* Check for AWC file */
}
/* Check for BWC file */
}
/* Check for DWC file */
}
/* Check for program files */
count = 0;
for (i = 0; i < MAX_PROG_TYPES; i++) {
count++;
}
}
if (count > 1) {
} else {
}
} else {
}
/* If nothing to download then quit now */
return (0);
}
/*
* Everything checks out, now to just do it
*/
if (offline) {
return (EMLXS_OFFLINE_FAILED);
}
return (EMLXS_OFFLINE_FAILED);
}
}
if (AwcBuffer) {
if (rval) {
goto SLI_DOWNLOAD_2MB_EXIT;
}
}
if (DwcBuffer) {
"DWC file: TEST: new=%s ",
"DWC file: SLI3: old=%s new=%s ",
}
"DWC file: SLI4: old=%s new=%s ",
}
if (rval) {
goto SLI_DOWNLOAD_2MB_EXIT;
}
}
if (BwcBuffer) {
}
if (offline) {
(void) emlxs_online(hba);
}
return (rval);
} /* emlxs_start_abs_download_2mb() */
/*
*
* FUNCTION NAME: emlxs_proc_abs_2mb
*
* the port and download the file with sliIssueMbCommand()
*
*
* PARAMETERS:
*
*
* RETURNS:
*
*/
static uint32_t
{
uint32_t i;
uint32_t RspProgress = 0;
uint32_t numBootImage = 0;
KM_NOSLEEP)) == NULL) {
"%x: Unable to allocate data buffer.", FileType);
return (EMLXS_IMAGE_FAILED);
}
KM_NOSLEEP)) == NULL) {
"%x: Unable to allocate mailbox buffer.", FileType);
return (EMLXS_IMAGE_FAILED);
}
switch (FileType) {
case FILE_TYPE_AWC:
break;
case FILE_TYPE_BWC:
"BWC build parms failed.");
goto EXIT_ABS_DOWNLOAD;
}
break;
case FILE_TYPE_DWC:
"DWC build parms failed.");
goto EXIT_ABS_DOWNLOAD;
}
break;
default:
"Invalid file type: %x", FileType);
goto EXIT_ABS_DOWNLOAD;
}
"%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
goto EXIT_ABS_DOWNLOAD;
}
0,
MBX_SUCCESS) {
"%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
goto EXIT_ABS_DOWNLOAD;
}
}
while (DlByteCount) {
if (DlByteCount >= SegSize)
else
DlByteCount -= DlCount;
for (i = 0; i < (DlCount / 4); i++) {
Dst++;
Src++;
}
(volatile uint32_t *)((volatile char *)
(DlByteCount) ? 0 : 1,
MBX_SUCCESS) {
"%x: Could not program 2MB Flash: Mailbox "
"cmd=%x status=%x", FileType,
goto EXIT_ABS_DOWNLOAD;
}
}
}
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
goto EXIT_ABS_DOWNLOAD;
}
#endif /* FMA_SUPPORT */
if (RspProgress != RSP_DOWNLOAD_DONE) {
"%x: Failed download response received. %x", FileType,
goto EXIT_ABS_DOWNLOAD;
}
if (ParamsChg) {
&AbsWakeUpParms)) {
"%x: Unable to update parms.", FileType);
}
}
if (DataBuffer) {
}
if (mbox) {
}
return (rval);
} /* emlxs_proc_abs_2mb() */
static void
{
} /* emlxs_format_load_area_cmd() */
/* ARGSUSED */
static uint32_t
{
/* Read wakeup paramters */
"Unable to get BWC parameters.");
return (FALSE);
}
pId[1] = 0;
}
/* case of EROM inactive */
} else {
/* case of EROM active */
/* same ID */
} else {
/* different ID */
if (returnStat) {
pId[0];
pId[1];
}
}
}
}
return (TRUE);
} /* emlxs_build_parms_2mb_bwc() */
/* ARGSUSED */
static uint32_t
{
uint32_t i;
/* Read wakeup paramters */
"Unable to get DWC parameters.");
return (FALSE);
}
sizeof (WAKE_UP_PARMS));
*numBootImage = 0;
}
/* incoming buffer is without aif header */
while (BufferSize > NextImage) {
for (i = 0; i < sizeof (IMAGE_HDR); i++) {
}
break;
}
case TEST_PROGRAM:
break;
case FUNC_FIRMWARE:
ChangeParams = TRUE;
break;
case BOOT_BIOS:
break;
} else if (BWCflag == ALL_WITHOUT_BWC) {
/* for possible future changes */
break;
}
}
ChangeParams = TRUE;
if (*numBootImage < MAX_BOOTID) {
(*numBootImage)++;
}
break;
case SLI1_OVERLAY:
ChangeParams = TRUE;
break;
case SLI2_OVERLAY:
ChangeParams = TRUE;
break;
case SLI3_OVERLAY:
ChangeParams = TRUE;
break;
case SLI4_OVERLAY:
ChangeParams = TRUE;
break;
}
}
if (*numBootImage > 1) {
for (i = 0; i < *numBootImage; i++) {
ptr1 =
BootId[i];
(void) emlxs_update_exp_rom(hba,
break;
}
}
} else {
if (*numBootImage == 1) {
BootId[0];
(void) emlxs_update_exp_rom(hba,
}
}
}
}
return (ChangeParams);
} /* emlxs_build_parms_2mb_dwc() */
extern uint32_t
{
KM_NOSLEEP)) == NULL) {
"Unable to allocate mailbox buffer.");
return (1);
}
MBX_SUCCESS) {
"Unable to get SRAM size: Mailbox cmd=%x status=%x",
rval = 1;
goto Exit_Function;
}
} else {
}
*MaxRbusSize = Uptr[0];
if (mbox) {
}
#ifdef FMA_SUPPORT
"emlxs_get_max_sram: hdl=%p",
rval = 1;
}
}
#endif /* FMA_SUPPORT */
return (rval);
} /* emlxs_get_max_sram() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_kern_check() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_stub_check() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_bios_check() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_sli1_check() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_sli2_check() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_sli3_check() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_sli4_check() */
static uint32_t
{
while (*ptr) {
return (1);
}
}
return (0);
} /* emlxs_sbus_fcode_check() */
static uint32_t
{
if (type == 0xff) {
return (KERNEL_CODE);
}
if (type >= MAX_PROG_TYPES) {
return (RESERVED_D);
}
return (type);
} /* emlxs_type_check() */
extern int32_t
{
return (EMLXS_OP_NOT_SUP);
}
"emlxs_boot_code_disable: Unable to read wake up parms.");
return (FC_FAILURE);
}
/* Check if boot code is already disabled */
return (FC_SUCCESS);
}
/* Make sure EROM entry has copy of boot bios entry */
}
/* Update the bios id with a zero id */
/* Don't load the EROM this time */
/* Now read the parms again to verify */
vpd->boot_version);
/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
/* Return the result */
FC_SUCCESS : FC_FAILURE);
} /* emlxs_boot_code_disable() */
extern int32_t
{
uint32_t i;
return (FC_SUCCESS);
}
/* Read the wakeup parms */
"emlxs_boot_code_enable: Unable to read wake up parms.");
return (FC_FAILURE);
}
/* Check if boot code is already enabled */
return (FC_SUCCESS);
}
return (EMLXS_NO_BOOT_CODE);
}
/* Update the parms with the boot image id */
/* Don't load the EROM this time */
} else { /* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
return (FC_FAILURE);
}
/* Scan load list for a boot image */
for (i = 0; i < MAX_LOAD_ENTRY; i++) {
/* Update the parms with the boot image id */
/* Don't load the EROM this time */
(void) emlxs_update_boot_wakeup_parms(hba,
break;
}
}
if (i == MAX_LOAD_ENTRY) {
return (EMLXS_NO_BOOT_CODE);
}
}
/* Now read the parms again to verify */
vpd->boot_version);
/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
/* return the result */
FC_SUCCESS : FC_FAILURE);
} /* emlxs_boot_code_enable() */
extern int32_t
{
return (FC_SUCCESS);
}
/* Read the wakeup parms */
"emlxs_boot_code_state: Unable to read wake up parms.");
return (FC_FAILURE);
}
/* return the result */
FC_SUCCESS : FC_FAILURE);
} /* emlxs_boot_code_state() */