/*
* 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
*/
/*
*/
/*
* Hemron IOCTL Routines
*
* Implements all ioctl access into the driver. This includes all routines
* necessary for updating firmware, accessing the hermon flash device, and
* providing interfaces for VTS.
*/
/* Hemron HCA state pointer (extern) */
extern void *hermon_statep;
extern int hermon_verbose;
/*
* (DEBUG-only), and VTS interfaces)
*/
#ifdef DEBUG
int mode);
int mode);
#endif /* DEBUG */
int mode);
int mode);
/* Hemron Flash Functions */
int *err);
int *intel_xcmd);
#ifdef DO_WRCONF
#endif
/* Hemron loopback test functions */
/* Patchable timeout values for flash operations */
/*
* hermon_ioctl()
*/
/* ARGSUSED */
int
int *rvalp)
{
int status;
return (EPERM);
}
return (EBADF);
}
return (EBADF);
}
status = 0;
switch (cmd) {
case HERMON_IOCTL_FLASH_READ:
break;
case HERMON_IOCTL_FLASH_WRITE:
break;
case HERMON_IOCTL_FLASH_ERASE:
break;
case HERMON_IOCTL_FLASH_INIT:
break;
case HERMON_IOCTL_FLASH_FINI:
break;
case HERMON_IOCTL_INFO:
break;
case HERMON_IOCTL_PORTS:
break;
case HERMON_IOCTL_LOOPBACK:
break;
#ifdef DEBUG
case HERMON_IOCTL_REG_WRITE:
break;
case HERMON_IOCTL_REG_READ:
break;
#endif /* DEBUG */
case HERMON_IOCTL_DDR_READ:
/* XXX guard until the ioctl header is cleaned up */
break;
break;
default:
break;
}
return (status);
}
/*
* hermon_ioctl_flash_read()
*/
static int
int mode)
{
int status = 0;
/*
* Check that flash init ioctl has been called first. And check
* that the same dev_t that called init is the one calling read now.
*/
(state->hs_fw_flashstarted == 0)) {
return (EIO);
}
/* copy user struct to kernel */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_flash_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
mode) != 0) {
return (EFAULT);
}
/*
* Determine type of READ ioctl
*/
switch (ioctl_info.af_type) {
case HERMON_FLASH_READ_SECTOR:
/* Check if sector num is too large for flash device */
if (ioctl_info.af_sector_num >=
return (EFAULT);
}
/* Perform the Sector Read */
ioctl_info.af_sector_num)) != 0) {
return (status);
}
/* copyout the firmware sector image data */
mode) != 0) {
return (EFAULT);
}
break;
/* Check if addr is too large for flash device */
return (EFAULT);
}
/* Perform the Quadlet Read */
return (status);
}
break;
default:
return (EINVAL);
}
/* copy results back to userland */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_flash_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
sizeof (hermon_flash_ioctl_t), mode) != 0) {
return (EFAULT);
}
return (status);
}
/*
* hermon_ioctl_flash_write()
*/
static int
int mode)
{
int status = 0;
/*
* Check that flash init ioctl has been called first. And check
* that the same dev_t that called init is the one calling write now.
*/
(state->hs_fw_flashstarted == 0)) {
return (EIO);
}
/* copy user struct to kernel */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_flash_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
sizeof (hermon_flash_ioctl_t), mode) != 0) {
return (EFAULT);
}
/*
* Determine type of WRITE ioctl
*/
switch (ioctl_info.af_type) {
/* Check if sector num is too large for flash device */
if (ioctl_info.af_sector_num >=
return (EFAULT);
}
/* copy in fw sector image data */
mode) != 0) {
return (EFAULT);
}
/* Perform Write Sector */
break;
case HERMON_FLASH_WRITE_BYTE:
/* Check if addr is too large for flash device */
return (EFAULT);
}
/* Perform Write Byte */
/*
* CMJ -- is a reset really needed before and after writing
* each byte? This code came from arbel, but we should look
* into this. Also, for SPI, no reset is actually performed.
*/
ioctl_info.af_addr)) != 0 ||
return (status);
}
break;
default:
break;
}
return (status);
}
/*
* hermon_ioctl_flash_erase()
*/
static int
int mode)
{
int status = 0;
/*
* Check that flash init ioctl has been called first. And check
* that the same dev_t that called init is the one calling erase now.
*/
(state->hs_fw_flashstarted == 0)) {
return (EIO);
}
/* copy user struct to kernel */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_flash_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
mode) != 0) {
return (EFAULT);
}
/*
* Determine type of ERASE ioctl
*/
switch (ioctl_info.af_type) {
/* Check if sector num is too large for flash device */
if (ioctl_info.af_sector_num >=
return (EFAULT);
}
/* Perform Sector Erase */
break;
case HERMON_FLASH_ERASE_CHIP:
/* Perform Chip Erase */
break;
default:
break;
}
return (status);
}
/*
* hermon_ioctl_flash_init()
*/
static int
int mode)
{
int ret;
int intel_xcmd = 0;
/* initialize the FMA retry loop */
/*
* init cannot be called more than once. If we have already init'd the
* flash, return directly.
*/
return (EINVAL);
}
/* copyin the user struct to kernel */
sizeof (hermon_flash_init_ioctl_t), mode) != 0) {
return (EFAULT);
}
/* Init Flash */
goto pio_error;
}
return (ret);
}
/* Read CFI info */
&intel_xcmd)) != 0) {
goto pio_error;
}
return (ret);
}
/*
* Return error if the command set is unknown.
*/
goto pio_error;
}
return (ret);
}
return (EFAULT);
}
/* the FMA retry loop starts. */
/* Read HWREV - least significant 8 bits is revision ID */
HERMON_HW_FLASH_CFG_HWREV) & 0xFF;
/* the FMA retry loop ends. */
/* Fill in the firmwate revision numbers */
/* Alloc flash mem for one sector size */
/* Set HW part number and length */
if (state->hs_hca_pn_len != 0) {
}
/* Copy ioctl results back to userland */
sizeof (hermon_flash_init_ioctl_t), mode) != 0) {
goto pio_error;
}
return (ret);
}
return (EFAULT);
}
/* Set flash state to started */
/*
* If "flash init" is successful, add an "on close" callback to the
* current dev node to ensure that "flash fini" gets called later
* even if the userland process prematurely exits.
*/
(int (*)(void *))hermon_ioctl_flash_cleanup, state);
if (ret != DDI_SUCCESS) {
if (status != 0) {
return (EIO);
}
return (status);
}
}
return (0);
return (EIO);
}
/*
* hermon_ioctl_flash_fini()
*/
static int
{
int ret;
/*
* Check that flash init ioctl has been called first. And check
* that the same dev_t that called init is the one calling fini now.
*/
(state->hs_fw_flashstarted == 0)) {
return (EINVAL);
}
}
return (ret);
}
/*
* If "flash fini" is successful, remove the "on close" callback
* that was setup during "flash init".
*/
if (ret != DDI_SUCCESS) {
return (EFAULT);
}
return (0);
}
/*
* hermon_ioctl_flash_cleanup()
*/
static int
{
int status;
return (status);
}
/*
* hermon_ioctl_flash_cleanup_nolock()
*/
static int
{
int status;
/* free flash mem */
if (state->hs_fw_sector) {
}
/* Fini the Flash */
return (status);
/* Set flash state to fini */
state->hs_fw_flashstarted = 0;
state->hs_fw_flashdev = 0;
return (0);
}
/*
* hermon_ioctl_info()
*/
static int
{
/*
* Access to Hemron VTS ioctls is not allowed in "maintenance mode".
*/
return (EFAULT);
}
/* copyin the user struct to kernel */
mode) != 0) {
return (EFAULT);
}
/*
* Check ioctl revision
*/
return (EINVAL);
}
/*
* If the 'fw_device_sz' has not been initialized yet, we initialize it
* here. This is done by leveraging the
* hermon_ioctl_flash_init()/fini() calls. We also hold our own mutex
* around this operation in case we have multiple VTS threads in
* process at the same time.
*/
if (state->hs_fw_device_sz == 0) {
return (EFAULT);
}
}
/* Copy ioctl results back to user struct */
mode) != 0) {
return (EFAULT);
}
return (0);
}
/*
* hermon_ioctl_ports()
*/
static int
{
int i;
/*
* Access to Hemron VTS ioctls is not allowed in "maintenance mode".
*/
return (EFAULT);
}
/* copyin the user struct to kernel */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_ports_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
mode) != 0) {
return (EFAULT);
}
/*
* Check ioctl revision
*/
return (EINVAL);
}
KM_SLEEP);
KM_SLEEP);
/*
* Setup the number of ports, then loop through all ports and
* query properties of each.
*/
for (i = 0; i < info.ap_num_ports; i++) {
/*
* Get portstate information from the device. If
* hermon_port_query() fails, leave zeroes in user
* struct port entry and continue.
*/
/*
* Copy queried port results back to user struct. If
* this fails, then break out of loop, attempt to copy
* out remaining info to user struct, and return (without
* error).
*/
if (ddi_copyout(&portstat,
sizeof (hermon_stat_port_ioctl_t), mode) != 0) {
break;
}
}
/* Copy ioctl results back to user struct */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_ports_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
mode) != 0) {
return (EFAULT);
}
return (0);
}
/*
* hermon_ioctl_loopback()
*/
static int
{
/*
* Access to Hemron VTS ioctls is not allowed in "maintenance mode".
*/
return (EFAULT);
}
/* copyin the user struct to kernel */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_loopback_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
mode) != 0) {
return (EFAULT);
}
/* Initialize the internal loopback test state structure */
/*
* Check ioctl revision
*/
return (EINVAL);
}
/* Validate that specified port number is legal */
return (EINVAL);
}
KM_SLEEP);
KM_SLEEP);
/*
* Get portstate information from specific port on device
*/
return (EINVAL);
}
1 : 0; /* XXX bogus assumption of a SUN subnet manager */
/*
* Compute the timeout duration in usec per the formula:
* to_usec_per_retry = 4.096us * (2 ^ supplied_timeout)
* (plus we add a little fudge-factor here too)
*/
/*
* Determine how many times we should loop before declaring a
* timeout failure.
*/
if ((max_usec % HERMON_VTS_LOOPBACK_MIN_WAIT_DUR) != 0) {
loopmax++;
}
return (EINVAL);
}
/* Allocate protection domain (PD) */
return (EFAULT);
}
/* Allocate and register a TX buffer */
lb.alb_buf_sz) != 0) {
return (EFAULT);
}
/* Allocate and register an RX buffer */
lb.alb_buf_sz) != 0) {
return (EFAULT);
}
/* Copy in the transmit buffer data */
return (EFAULT);
}
/* Allocate the transmit QP and CQs */
return (EFAULT);
}
/* Allocate the receive QP and CQs */
return (EFAULT);
}
/* Activate the TX QP (connect to RX QP) */
return (EFAULT);
}
/* Activate the RX QP (connect to TX QP) */
return (EFAULT);
}
/* Run the loopback test (for specified number of iterations) */
lb.alb_pass_done = 0;
/* Post RDMA Write work request */
return (EFAULT);
}
/* Poll the TX CQ for a completion every few ticks */
for (j = 0; j < loopmax; j++) {
mode) != 0) {
return (EFAULT);
}
return (EFAULT);
} else if (ret == IBT_CQ_EMPTY) {
continue;
}
/* Compare the data buffers */
lb.alb_buf_sz) == 0) {
break;
} else {
mode) != 0) {
return (EFAULT);
}
return (EFAULT);
}
}
}
/* Copy ioctl results back to user struct */
/* Free up everything and release all consumed resources */
return (ret);
}
#ifdef DEBUG
/*
* hermon_ioctl_reg_read()
*/
static int
{
int status;
/* initialize the FMA retry loop */
/*
* Access to Hemron registers is not allowed in "maintenance mode".
* This is primarily because the device may not have BARs to access
*/
return (EFAULT);
}
/* Copy in the hermon_reg_ioctl_t structure */
mode);
if (status != 0) {
return (EFAULT);
}
/* Determine base address for requested register set */
switch (rdreg.arg_reg_set) {
case HERMON_CMD_BAR:
break;
case HERMON_UAR_BAR:
break;
default:
return (EINVAL);
}
/* Ensure that address is properly-aligned */
/* the FMA retry loop starts. */
/* Read the register pointed to by addr */
/* the FMA retry loop ends. */
fm_test);
/* Copy in the result into the hermon_reg_ioctl_t structure */
mode);
if (status != 0) {
return (EFAULT);
}
return (0);
return (EIO);
}
/*
* hermon_ioctl_reg_write()
*/
static int
{
int status;
/* initialize the FMA retry loop */
/*
* Access to Hermon registers is not allowed in "maintenance mode".
* This is primarily because the device may not have BARs to access
*/
return (EFAULT);
}
/* Copy in the hermon_reg_ioctl_t structure */
mode);
if (status != 0) {
return (EFAULT);
}
/* Determine base address for requested register set */
switch (wrreg.arg_reg_set) {
case HERMON_CMD_BAR:
break;
case HERMON_UAR_BAR:
break;
default:
return (EINVAL);
}
/* Ensure that address is properly-aligned */
/* the FMA retry loop starts. */
/* Write the data to the register pointed to by addr */
/* the FMA retry loop ends. */
fm_test);
return (0);
return (EIO);
}
#endif /* DEBUG */
static int
int mode)
{
/* initialize the FMA retry loop */
/*
* Check that flash init ioctl has been called first. And check
* that the same dev_t that called init is the one calling write now.
*/
(state->hs_fw_flashstarted == 0)) {
return (EIO);
}
/* copy user struct to kernel */
#ifdef _MULTI_DATAMODEL
sizeof (hermon_flash_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
sizeof (hermon_flash_ioctl_t), mode) != 0) {
return (EFAULT);
}
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_AMD_CMDSET:
break;
case HERMON_FLASH_SPI_CMDSET:
{
/* the FMA retry loop starts. */
/* the FMA retry loop ends. */
break;
}
default:
return (EINVAL);
}
return (0);
return (EIO);
}
/*
* hermon_flash_reset()
*/
static int
{
int status;
/*
* Performs a reset to the flash device. After a reset the flash will
*/
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_AMD_CMDSET:
&status);
if (status != 0) {
return (status);
}
break;
&status);
if (status != 0) {
return (status);
}
break;
/* It appears no reset is needed for SPI */
case HERMON_FLASH_SPI_CMDSET:
status = 0;
break;
default:
break;
}
return (status);
}
/*
* hermon_flash_read_sector()
*/
static int
{
int i, status;
/*
* Calculate the start and end address of the sector, based on the
* sector number passed in.
*/
/* Set the flash bank correctly for the given address */
return (status);
/* Read the entire sector, one quadlet at a time */
if (status != 0) {
return (status);
}
}
return (0);
}
/*
* hermon_flash_read_quadlet()
*/
static int
{
int status;
/* Set the flash bank correctly for the given address */
return (status);
}
/* Read one quadlet of data */
if (status != 0) {
return (EIO);
}
return (0);
}
/*
* hermon_flash_write_sector()
*/
static int
{
int status = 0;
int i;
/*
* Calculate the start and end address of the sector, based on the
* sector number passed in.
*/
/* Set the flash bank correctly for the given address */
return (status);
}
/* Erase the sector before writing */
if (status != 0) {
return (status);
}
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_SPI_CMDSET:
/* Write the sector, one dword at a time */
return (status);
}
}
break;
case HERMON_FLASH_AMD_CMDSET:
/* Write the sector, one byte at a time */
sector[i]);
if (status != 0) {
break;
}
}
break;
default:
break;
}
return (status);
}
/*
* hermon_flash_spi_write_dword()
*
* NOTE: This function assumes that "data" is in network byte order.
*
*/
static int
{
int status;
/* initialize the FMA retry loop */
/* the FMA retry loop starts. */
fm_test);
/* Issue Write Enable */
/* Set the Address */
/* Set the Data */
/* Set the Page Program and execute */
/* Wait for write to complete */
return (status);
}
/* the FMA retry loop ends. */
return (0);
return (EIO);
}
/*
* hermon_flash_write_byte()
*/
static int
{
int status = 0;
int dword_addr;
int byte_offset;
int i;
union {
} dword;
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_AMD_CMDSET:
/* Issue Flash Byte program command */
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
/* Wait for Write Byte to Complete */
i = 0;
do {
drv_usecwait(1);
if (status != 0) {
return (status);
}
if (i == hermon_hw_flash_timeout_write) {
"hermon_flash_write_byte: ACS write "
"timeout: addr: 0x%x, data: 0x%x\n",
return (EIO);
}
i++;
break;
/* Issue Flash Byte program command */
&status);
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
/* Wait for Write Byte to Complete */
i = 0;
do {
drv_usecwait(1);
if (status != 0) {
return (status);
}
if (i == hermon_hw_flash_timeout_write) {
"hermon_flash_write_byte: ICS write "
"timeout: addr: %x, data: %x\n",
return (EIO);
}
i++;
} while ((stat & HERMON_HW_FLASH_ICS_READY) == 0);
if (stat & HERMON_HW_FLASH_ICS_ERROR) {
"hermon_flash_write_byte: ICS write cmd error: "
"addr: %x, data: %x\n",
return (EIO);
}
break;
case HERMON_FLASH_SPI_CMDSET:
/*
* Our lowest write granularity on SPI is a dword.
* To support this ioctl option, we can read in the
* dword that contains this byte, modify this byte,
* and write the dword back out.
*/
/* Determine dword offset and byte offset within the dword */
#ifdef _LITTLE_ENDIAN
#endif
/* Read in dword */
dword_addr)) != 0)
break;
/* Set "data" to the appopriate byte */
/* Write modified dword back out */
break;
default:
"hermon_flash_write_byte: unknown cmd set: 0x%x\n",
break;
}
return (status);
}
/*
* hermon_flash_erase_sector()
*/
static int
{
int status = 0;
int i;
/* initialize the FMA retry loop */
/* Get address from sector num */
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_AMD_CMDSET:
/* Issue Flash Sector Erase Command */
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
/* Wait for Sector Erase to complete */
i = 0;
do {
drv_usecwait(1);
if (status != 0) {
return (status);
}
if (i == hermon_hw_flash_timeout_erase) {
"hermon_flash_erase_sector: "
"ACS erase timeout\n");
return (EIO);
}
i++;
} while (stat != 0xFFFFFFFF);
break;
/* Issue Flash Sector Erase Command */
&status);
if (status != 0) {
return (status);
}
&status);
if (status != 0) {
return (status);
}
/* Wait for Sector Erase to complete */
i = 0;
do {
drv_usecwait(1);
if (status != 0) {
return (status);
}
if (i == hermon_hw_flash_timeout_erase) {
"hermon_flash_erase_sector: "
"ICS erase timeout\n");
return (EIO);
}
i++;
} while ((stat & HERMON_HW_FLASH_ICS_READY) == 0);
if (stat & HERMON_HW_FLASH_ICS_ERROR) {
"hermon_flash_erase_sector: "
"ICS erase cmd error\n");
return (EIO);
}
break;
case HERMON_FLASH_SPI_CMDSET:
/* the FMA retry loop starts. */
fm_test);
/* Issue Write Enable */
/* Set the Address */
/* Issue Flash Sector Erase */
/* the FMA retry loop ends. */
fm_test);
/* Wait for Sector Erase to complete */
break;
default:
"hermon_flash_erase_sector: unknown cmd set: 0x%x\n",
break;
}
/* Reset the flash device */
if (status == 0) {
}
return (status);
return (EIO);
}
/*
* hermon_flash_erase_chip()
*/
static int
{
int status = 0;
int i;
int num_sect;
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_AMD_CMDSET:
/* Issue Flash Chip Erase Command */
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
if (status != 0) {
return (status);
}
/* Wait for Chip Erase to Complete */
i = 0;
do {
drv_usecwait(1);
if (status != 0) {
return (status);
}
if (i == hermon_hw_flash_timeout_erase) {
"hermon_flash_erase_chip: erase timeout\n");
return (EIO);
}
i++;
} while (stat != 0xFFFFFFFF);
break;
case HERMON_FLASH_SPI_CMDSET:
/*
* These chips don't have a chip erase command, so erase
* all blocks one at a time.
*/
for (i = 0; i < num_sect; i++) {
if (status != 0) {
"hermon_flash_erase_chip: "
"sector %d erase error\n", i);
return (status);
}
}
break;
default:
break;
}
return (status);
}
/*
* hermon_flash_spi_write_enable()
*/
static void
{
}
/*
* hermon_flash_spi_wait_wip()
*/
static int
{
/* initialize the FMA retry loop */
/* the FMA retry loop starts. */
fm_test);
/* wait on the gateway to clear busy */
do {
} while (status & HERMON_HW_FLASH_SPI_BUSY);
/* now, get the status and check for WIP to clear */
do {
} while (status & HERMON_HW_FLASH_SPI_WIP);
/* the FMA retry loop ends. */
return (0);
return (EIO);
}
/*
* hermon_flash_bank()
*/
static int
{
/* initialize the FMA retry loop */
/* Set handle */
/* Determine the bank setting from the address */
/*
* If the bank is different from the currently set bank, we need to
* change it. Also, if an 'addr' of 0 is given, this allows the
* capability to force the flash bank to 0. This is useful at init
* time to initially set the bank value
*/
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_SPI_CMDSET:
/* CMJ: not needed for hermon */
break;
case HERMON_FLASH_AMD_CMDSET:
/* the FMA retry loop starts. */
HERMON_HW_FLASH_GPIO_DATACLEAR, 0x70);
/* the FMA retry loop ends. */
break;
default:
return (EINVAL);
}
}
return (0);
return (EIO);
}
/*
* hermon_flash_spi_exec_command()
*/
static void
{
int timeout = 0;
do {
timeout++;
} while ((data & HERMON_HW_FLASH_SPI_BUSY) &&
}
/*
* hermon_flash_read()
*/
static uint32_t
{
/* initialize the FMA retry loop */
/* the FMA retry loop starts. */
fm_test);
switch (state->hs_fw_cmdset) {
case HERMON_FLASH_SPI_CMDSET:
/* Set the transaction address */
break;
case HERMON_FLASH_AMD_CMDSET:
/*
* The Read operation does the following:
* 1) Write the masked address to the HERMON_FLASH_ADDR
* register. Only the least significant 19 bits are valid.
* 2) Read back the register until the command has completed.
* 3) Read the data retrieved from the address at the
* HERMON_FLASH_DATA register.
*/
timeout = 0;
do {
timeout++;
} while ((data & HERMON_HW_FLASH_CMD_MASK) &&
if (timeout == hermon_hw_flash_timeout_config) {
"out.\n");
return (data);
}
break;
default:
break;
}
/* the FMA retry loop ends. */
return (data);
return (data);
}
/*
* hermon_flash_write()
*/
static void
{
int cmd;
int timeout;
/* initialize the FMA retry loop */
/* the FMA retry loop starts. */
fm_test);
/*
* The Write operation does the following:
* 1) Write the data to be written to the HERMON_FLASH_DATA offset.
* 2) Write the address to write the data to to the HERMON_FLASH_ADDR
* offset.
* 3) Wait until the write completes.
*/
timeout = 0;
do {
timeout++;
} while ((cmd & HERMON_HW_FLASH_CMD_MASK) &&
if (timeout == hermon_hw_flash_timeout_config) {
return;
}
/* the FMA retry loop ends. */
*err = 0;
return;
}
/*
* hermon_flash_init()
*/
static int
{
int sema_cnt;
int gpio;
/* initialize the FMA retry loop */
/* Set handle */
/* the FMA retry loop starts. */
fm_test);
/* Init the flash */
#ifdef DO_WRCONF
/*
* Grab the WRCONF semaphore.
*/
#endif
/*
* Grab the GPIO semaphore. This allows us exclusive access to the
* GPIO settings on the Hermon for the duration of the flash burning
* procedure.
*/
sema_cnt = 0;
do {
if (word == 0) {
break;
}
sema_cnt++;
drv_usecwait(1);
} while (sema_cnt < hermon_hw_flash_timeout_gpio_sema);
/*
* Determine if we timed out trying to grab the GPIO semaphore
*/
if (sema_cnt == hermon_hw_flash_timeout_gpio_sema) {
return (EIO);
}
/* Save away original GPIO Values */
/* Set new GPIO value */
/* Save away original GPIO Values */
/* unlock GPIO */
/*
* Set new GPIO values
*/
/* re-lock GPIO */
/* Set CPUMODE to enable hermon to access the flash device */
/* CMJ This code came from arbel. Hermon doesn't seem to need it. */
/*
* hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_CPUMODE,
* 1 << HERMON_HW_FLASH_CPU_SHIFT);
*/
/* the FMA retry loop ends. */
return (0);
return (EIO);
}
/*
* hermon_flash_cfi_init
* Implements access to the CFI (Common Flash Interface) data
*/
static int
int *intel_xcmd)
{
int i;
int status;
/* Right now, all hermon cards use SPI. */
if (hermon_device_mode(state)) {
/*
* Don't use CFI for SPI part. Just fill in what we need
* and return.
*/
/*
* set this to inform caller of cmdset type.
*/
return (0);
}
/*
* Determine if the user command supports the Intel Extended
* Command Set. The query string is contained in the fourth
* quad word.
*/
if (hermon_verbose) {
IBTF_DPRINTF_L2("hermon",
"Support for Intel X is present\n");
}
}
/* CFI QUERY */
if (status != 0) {
return (status);
}
/* temporarily set the cmdset in order to do the initial read */
/* Read in CFI data */
for (i = 0; i < HERMON_CFI_INFO_SIZE; i += 4) {
if (status != 0) {
return (status);
}
}
/* Determine chip set */
/*
* Mode: x16 working in x8 mode (Intel).
* Pack data - skip spacing bytes.
*/
if (hermon_verbose) {
IBTF_DPRINTF_L2("hermon",
"x16 working in x8 mode (Intel)\n");
}
for (i = 0; i < HERMON_CFI_INFO_SIZE; i += 2) {
}
}
"hermon_flash_cfi_init: UNKNOWN chip cmd set 0x%04x\n",
return (0);
}
/* Determine total bytes in one sector size */
/* Calculate equivalent of log2 (n) */
sector_sz_bytes >>= 1;
}
/* Set sector size */
/* Set flash size */
/* Reset to turn off CFI mode */
goto out;
/* Pass CFI data back to user command. */
for (i = 0; i < HERMON_FLASH_CFI_SIZE_QUADLET; i++) {
}
if (*intel_xcmd == 1) {
/*
* Inform the user cmd that this driver does support the
* Intel Extended Command Set.
*/
} else {
}
out:
return (status);
}
/*
* hermon_flash_fini()
*/
static int
{
int status;
/* initialize the FMA retry loop */
/* Set handle */
return (status);
/* the FMA retry loop starts. */
fm_test);
/*
* Restore original GPIO Values
*/
state->hs_fw_gpio[0]);
/* unlock GPIOs */
/* re-lock GPIOs */
/* Give up gpio semaphore */
/* the FMA retry loop ends. */
return (0);
return (EIO);
}
/*
* hermon_flash_read_cfg
*/
static uint32_t
{
if (do_bar0) {
} else {
/*
* Perform flash read operation:
* 1) Place addr to read from on the HERMON_HW_FLASH_CFG_ADDR
* register
* 2) Read data at that addr from the HERMON_HW_FLASH_CFG_DATA
* register
*/
addr);
}
return (read);
}
#ifdef DO_WRCONF
static void
{
}
static void
{
while (sem_value) {
}
}
#endif
/*
* hermon_flash_write_cfg
*/
static void
#ifdef DO_WRCONF
#else
#endif
{
if (do_bar0) {
} else {
/*
* Perform flash write operation:
* 1) Place addr to write to on the HERMON_HW_FLASH_CFG_ADDR
* register
* 2) Place data to write on to the HERMON_HW_FLASH_CFG_DATA
* register
*/
addr);
data);
}
}
/*
* Support routines to convert Common Flash Interface (CFI) data
* from a 32 bit word to a char array, and from a char array to
* a 32 bit word.
*/
static void
{
}
static void
{
}
/*
* hermon_loopback_free_qps
*/
static void
{
int i;
}
}
for (i = 0; i < 2; i++) {
}
}
}
}
/*
* hermon_loopback_free_state
*/
static void
{
}
}
}
}
}
}
/*
* hermon_loopback_init
*/
static int
{
return (EFAULT);
}
return (0);
}
/*
* hermon_loopback_init_qp_info
*/
static void
{
}
/*
* hermon_loopback_alloc_mem
*/
static int
{
/* Allocate buffer of specified size */
return (EFAULT);
}
/* Register the buffer as a memory region */
return (EFAULT);
}
return (0);
}
/*
* hermon_loopback_alloc_qps
*/
static int
{
/* Allocate send and recv CQs */
for (i = 0; i < 2; i++) {
return (EFAULT);
}
}
/* Allocate the QP */
}
return (EFAULT);
}
return (0);
}
/*
* hermon_loopback_modify_qp
*/
static int
{
/* Modify QP to INIT */
return (EFAULT);
}
/*
* Modify QP to RTR (set destination LID and QP number to local
* LID and QP number)
*/
return (EFAULT);
}
/* Modify QP to RTS */
return (EFAULT);
}
return (0);
}
/*
* hermon_loopback_copyout
*/
static int
{
#ifdef _MULTI_DATAMODEL
sizeof (hermon_loopback_ioctl32_t), mode) != 0) {
return (EFAULT);
}
} else
#endif /* _MULTI_DATAMODEL */
mode) != 0) {
return (EFAULT);
}
return (0);
}
/*
* hermon_loopback_post_send
*/
static int
{
int ret;
/* Initialize local address for TX buffer */
/* Initialize the remaining details of the work request */
/* Initialize the remote address for RX buffer */
tx->hlc_complete = 0;
1, NULL);
if (ret != IBT_SUCCESS) {
return (EFAULT);
}
return (0);
}
/*
* hermon_loopback_poll_cq
*/
static int
{
comm->hlc_num_polled = 0;
}
return (comm->hlc_status);
}