emlxs_sli.c revision bb63f56ebeb244bd34f5e8d50900e3420f01b394
/*
* 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 */
#ifdef SFCT_SUPPORT
#endif /* SFCT_SUPPORT */
int
{
int status;
if (hba->slim_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"(SBUS) ddi_regs_map_setup SLIM failed. "
"status=%x", status);
goto failed;
}
}
if (hba->csr_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"(SBUS) ddi_regs_map_setup DFLY CSR "
"failed. status=%x", status);
goto failed;
}
}
if (hba->sbus_flash_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"(SBUS) ddi_regs_map_setup Fcode Flash "
"failed. status=%x", status);
goto failed;
}
}
if (hba->sbus_core_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"(SBUS) ddi_regs_map_setup TITAN CORE "
"failed. status=%x", status);
goto failed;
}
}
if (hba->sbus_csr_handle == 0) {
if (status != DDI_SUCCESS) {
"(SBUS) ddi_regs_map_setup TITAN CSR "
"failed. status=%x", status);
goto failed;
}
}
} else { /* ****** PCI ****** */
if (hba->slim_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"(PCI) ddi_regs_map_setup SLIM failed. "
"stat=%d mem=%p attr=%p hdl=%p",
&hba->slim_acc_handle);
goto failed;
}
}
/*
* Map in control registers, using memory-mapped version of
* the registers rather than the I/O space-mapped registers.
*/
if (hba->csr_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"ddi_regs_map_setup CSR failed. status=%x",
status);
goto failed;
}
}
}
goto failed;
}
}
/* offset from beginning of register space */
/* offset from beginning of register space */
/* for TITAN registers */
hba->shc_reg_addr =
(sizeof (uint32_t) * SBUS_CTRL_REG_OFFSET);
hba->shs_reg_addr =
(sizeof (uint32_t) * SBUS_STAT_REG_OFFSET);
hba->shu_reg_addr =
(sizeof (uint32_t) * SBUS_UPDATE_REG_OFFSET);
}
return (0);
return (ENOMEM);
} /* emlxs_sli3_map_hdw() */
/*ARGSUSED*/
int
{
/*
* Map in Hardware BAR pages that will be used for
* communication with HBA.
*/
return (0);
} /* emlxs_sli4_map_hdw() */
void
{
if (hba->csr_acc_handle) {
hba->csr_acc_handle = 0;
}
if (hba->slim_acc_handle) {
hba->slim_acc_handle = 0;
}
if (hba->sbus_flash_acc_handle) {
hba->sbus_flash_acc_handle = 0;
}
if (hba->sbus_core_acc_handle) {
hba->sbus_core_acc_handle = 0;
}
if (hba->sbus_csr_handle) {
hba->sbus_csr_handle = 0;
}
}
}
return;
} /* emlxs_sli3_unmap_hdw() */
/*ARGSUSED*/
void
{
/*
* Free map for Hardware BAR pages that were used for
* communication with HBA.
*/
} /* emlxs_sli4_unmap_hdw() */
extern int
{
int32_t i;
i = 0;
/* Restart the adapter */
return (1);
}
/*
* WARNING: There is a max of 6 ring masks allowed
*/
/* RING 0 - FCP */
hba->ring_rmask[i] = 0;
} else {
}
/* RING 1 - IP */
} else {
}
/* RING 2 - ELS */
/* RING 3 - CT */
if (i > 6) {
"emlxs_hba_init: Too many ring masks defined. cnt=%d", i);
return (1);
}
/* Initialize all the port objects */
for (i = 0; i < MAX_VPORTS; i++) {
}
/*
* Initialize the max_node count to a default value if needed
* This determines how many node objects we preallocate in the pool
* The actual max_nodes will be set later based on adapter info
*/
} else {
}
}
return (0);
} /* emlxs_sli3_online() */
/*ARGSUSED*/
extern int
{
/*
* Initalize Hardware that will be used to bring
* SLI4 online.
*/
return (0);
} /* emlxs_sli4_online() */
extern void
{
/* Interlock the adapter to take it down */
(void) emlxs_interlock(hba);
} /* emlxs_sli3_offline() */
/*ARGSUSED*/
extern void
{
return;
} /* emlxs_sli4_offline() */
extern uint32_t
{
uint32_t i;
i = 0;
"Adapter reset disabled.");
return (1);
}
/* Make sure we have called interlock */
(void) emlxs_interlock(hba);
if (restart) {
"Restarting.");
} else {
"Resetting.");
}
/* Save reset time */
if (restart) {
/* First put restart command in mailbox */
word0 = 0;
/* Only skip post after emlxs_ffinit is completed */
if (skip_post) {
1);
} else {
0);
}
}
/*
* Turn off SERR, PERR in PCI cmd register
*/
/* Wait 1 msec before restoring PCI config */
DELAYMS(1);
/* Restore PCI cmd register */
/* Wait 3 seconds before checking */
DELAYMS(3000);
i += 3;
/* Wait for reset completion */
while (i < 30) {
/* Check status register to see what current state is */
/* Check to see if any errors occurred during init */
status1 =
status2 =
"HS_FFERM: status=0x%x status1=0x%x status2=0x%x",
return (1);
}
/* Reset Done !! */
goto done;
}
/*
* Check every 1 second for 15 seconds, then reset board
*/
DELAYMS(1000);
i++;
if (i == 15) {
"Reset failed. Retrying...");
goto reset;
}
}
/* Timeout occurred */
"Timeout: status=0x%x", status);
/* Log a dump event */
return (1);
done:
/* Reset the hba structure */
hba->iodone_count = 0;
hba->heartbeat_active = 0;
hba->discovery_timer = 0;
hba->linkup_timer = 0;
hba->loopback_tics = 0;
/* Initialize hc_copy */
/* Reset the ring objects */
for (i = 0; i < MAX_RINGS; i++) {
}
/* Reset the port objects */
for (i = 0; i < MAX_VPORTS; i++) {
vport->node_count = 0;
}
}
return (0);
} /* emlxs_sli3_hba_reset */
/*ARGSUSED*/
extern uint32_t
{
return (0);
} /* emlxs_sli4_hba_reset */
#define BPL_CMD 0
#define BPL_RESP 1
#define BPL_DATA 2
{
uint_t i;
#if (EMLXS_MODREV >= EMLXS_MODREV3)
switch (bpl_type) {
case BPL_CMD:
break;
case BPL_RESP:
break;
case BPL_DATA:
break;
}
#else
switch (bpl_type) {
case BPL_CMD:
cookie_cnt = 1;
break;
case BPL_RESP:
cookie_cnt = 1;
break;
case BPL_DATA:
cookie_cnt = 1;
break;
}
#endif /* >= EMLXS_MODREV3 */
bpl++;
}
return (bpl);
} /* emlxs_pkt_to_bpl */
{
#ifdef EMLXS_SPARC
/* Use FCP MEM_BPL table to get BPL buffer */
} else {
/* Use MEM_BPL pool to get BPL buffer */
}
#else
/* Use MEM_BPL pool to get BPL buffer */
#endif
if (!bmp) {
return (1);
}
cookie_cnt = 0;
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#else
cmd_cookie_cnt = 1;
resp_cookie_cnt = 1;
data_cookie_cnt = 1;
#endif /* >= EMLXS_MODREV3 */
case FC_FCP_RING:
/* CMD payload */
/* RSP payload */
bpl =
/* DATA payload */
if (pkt->pkt_datalen != 0) {
bdeFlag =
(pkt->pkt_tran_type ==
FC_PKT_FCP_READ) ? BUFF_USE_RCV : 0;
bpl =
bdeFlag);
}
}
/*
* else
* {
* Target mode FCP status. Do nothing more.
* }
*/
break;
case FC_IP_RING:
/* CMD payload */
break;
case FC_ELS_RING:
/* CMD payload */
/* RSP payload */
bpl =
}
break;
case FC_CT_RING:
/* CMD payload */
/* RSP payload */
bpl =
}
break;
}
return (0);
} /* emlxs_sli2_bde_setup */
#ifdef SLI3_SUPPORT
{
int data_cookie_cnt;
uint32_t i;
#if (EMLXS_MODREV >= EMLXS_MODREV3)
return (i);
}
#endif /* >= EMLXS_MODREV3 */
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#else
data_cookie_cnt = 1;
#endif /* >= EMLXS_MODREV3 */
case FC_FCP_RING:
/* CMD payload */
/* RSP payload */
/* DATA payload */
if (pkt->pkt_datalen != 0) {
bde =
for (i = 0; i < data_cookie_cnt; i++) {
cp_data++;
bde++;
}
}
}
/*
* else
* {
* Target mode FCP status. Do nothing more.
* }
*/
break;
case FC_IP_RING:
/* CMD payload */
break;
case FC_ELS_RING:
/* CMD payload */
/* RSP payload */
}
break;
case FC_CT_RING:
/* CMD payload */
/* RSP payload */
}
break;
}
iocb->ulpBdeCount = 0;
return (0);
} /* emlxs_sli3_bde_setup */
#endif /* SLI3_SUPPORT */
/*ARGSUSED*/
{
return (0);
} /* emlxs_sli4_bde_setup */
/* Only used for FCP Data xfers */
{
#ifdef SFCT_SUPPORT
struct stmf_sglist_ent *sgl;
iocb->ulpBdeCount = 0;
return (0);
}
#ifdef EMLXS_SPARC
/* Use FCP MEM_BPL table to get BPL buffer */
#else
/* Use MEM_BPL pool to get BPL buffer */
#endif /* EMLXS_SPARC */
if (!bmp) {
"emlxs_fct_sli2_bde_setup: Unable to BPL buffer. iotag=%x",
iocb->ulpBdeCount = 0;
return (1);
}
/* Init the buffer list */
bpl++;
sgl++;
}
/* Init the IOCB */
#endif /* SFCT_SUPPORT */
return (0);
} /* emlxs_sli2_fct_bde_setup */
#ifdef SLI3_SUPPORT
/*ARGSUSED*/
{
#ifdef SFCT_SUPPORT
struct stmf_sglist_ent *sgl;
iocb->ulpBdeCount = 0;
return (0);
}
/* Init first BDE */
sgl++;
/* Init remaining BDE's */
bde++;
sgl++;
}
iocb->ulpBdeCount = 0;
#endif /* SFCT_SUPPORT */
return (0);
} /* emlxs_sli3_fct_bde_setup */
#endif /* SLI3_SUPPORT */
/*ARGSUSED*/
{
return (0);
} /* emlxs_sli4_fct_bde_setup */
extern void
{
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
void *ioa2;
throttle = 0;
/* Check if FCP ring and adapter is not ready */
return;
}
}
/* Attempt to acquire CMD_RING lock */
/* Queue it for later */
if (iocbq) {
return;
} else {
/*
* EMLXS_MSGF(EMLXS_CONTEXT,
* &emlxs_ring_watchdog_msg,
* "%s host=%d port=%d cnt=%d,%d RACE
* CONDITION3 DETECTED.",
* emlxs_ring_xlate(ringno),
* rp->fc_cmdidx, rp->fc_port_cmdidx,
* hba->ring_tx_count[ringno],
* hba->io_count[ringno]);
*/
}
} else {
return;
}
}
/* CMD_RING_LOCK acquired */
/* Check if HBA is full */
if (throttle <= 0) {
/* Hitting adapter throttle limit */
/* Queue it for later */
if (iocbq) {
}
goto busy;
}
/* Read adapter's get index */
offset =
/* Calculate the next put index */
nextIdx =
/* Check if ring is full */
/* Try one more time */
/* Queue it for later */
if (iocbq) {
}
goto busy;
}
}
/*
* We have a command ring slot available
* Make sure we have an iocb to send
*/
if (iocbq) {
/* Check if the ring already has iocb's waiting */
/* Put the current iocbq on the tx queue */
emlxs_tx_put(iocbq, 0);
/*
* Attempt to replace it with the next iocbq
* in the tx queue
*/
}
} else {
/* Try to get the next iocb on the tx queue */
}
count = 0;
/* Process each iocbq */
while (iocbq) {
#ifdef NPIV_SUPPORT
/*
*/
/*
* Update adapter if needed, since we are about to
* delay here
*/
if (count) {
count = 0;
/* Update the adapter's cmd put index */
/* DMA sync the index for the adapter */
((uint64_t)
((unsigned long)&(slim2p->
} else {
ioa2 =
}
}
/* Perform delay */
if (ringno == FC_ELS_RING) {
drv_usecwait(100000);
} else {
drv_usecwait(20000);
}
}
#endif /* NPIV_SUPPORT */
/*
* At this point, we have a command ring slot available
* and an iocb to send
*/
/* Send the iocb */
count++;
/* Check if HBA is full */
if (throttle <= 0) {
goto busy;
}
/* Calculate the next put index */
nextIdx =
/* Check if ring is full */
/* Try one more time */
goto busy;
}
}
/* Get the next iocb from the tx queue if there is one */
}
if (count) {
/* Update the adapter's cmd put index */
/* DMA sync the index for the adapter */
} else {
ioa2 =
}
/* Check tx queue one more time before releasing */
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_watchdog_msg,
* "%s host=%d port=%d RACE CONDITION1
* DETECTED.", emlxs_ring_xlate(ringno),
* rp->fc_cmdidx, rp->fc_port_cmdidx);
*/
goto sendit;
}
}
return;
busy:
/*
* Set ring to SET R0CE_REQ in Chip Att register.
* Chip will tell us when an entry is freed.
*/
if (count) {
/* Update the adapter's cmd put index */
/* DMA sync the index for the adapter */
} else {
ioa2 =
}
}
if (throttle <= 0) {
} else {
}
return;
} /* emlxs_sli3_issue_iocb_cmd() */
/*ARGSUSED*/
extern void
{
return;
} /* emlxs_sli4_issue_iocb_cmd() */
/* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */
/* MBX_WAIT - returns MBX_TIMEOUT or mailbox_status */
/* MBX_SLEEP - returns MBX_TIMEOUT or mailbox_status */
/* MBX_POLL - returns MBX_TIMEOUT or mailbox_status */
extern uint32_t
{
/* Check for minimum timeouts */
switch (mb->mbxCommand) {
case MBX_DOWN_LOAD:
case MBX_UPDATE_CFG:
case MBX_LOAD_AREA:
case MBX_LOAD_EXP_ROM:
case MBX_WRITE_NV:
case MBX_FLASH_WR_ULA:
case MBX_DEL_LD_ENTRY:
case MBX_LOAD_SM:
if (tmo < 300) {
tmo = 300;
}
break;
default:
if (tmo < 30) {
tmo = 30;
}
break;
}
/* Adjust wait flag */
if (flag != MBX_NOWAIT) {
/* If interrupt is enabled, use sleep, otherwise poll */
} else {
}
}
/* Check for hardware error */
"Hardware error reported. %s failed. status=%x mb=%p",
return (MBX_HARDWARE_ERROR);
}
if (hba->mbox_queue_flag) {
/* If we are not polling, then queue it for later */
if (flag == MBX_NOWAIT) {
"Busy. %s: mb=%p NoWait.",
return (MBX_BUSY);
}
/* Convert tmo seconds to 50 millisecond tics */
while (hba->mbox_queue_flag) {
if (tmo_local-- == 0) {
"Timeout. %s: mb=%p tmo=%d Waiting.",
tmo);
/* Non-lethalStatus mailbox timeout */
/* Does not indicate a hardware error */
return (MBX_TIMEOUT);
}
DELAYMS(50);
}
}
/* Initialize mailbox area */
switch (flag) {
case MBX_NOWAIT:
"Sending. %s: mb=%p NoWait.",
}
}
break;
case MBX_SLEEP:
"Sending. %s: mb=%p Sleep.",
}
break;
case MBX_POLL:
"Sending. %s: mb=%p Polled.",
}
break;
}
/* Clear the attention bit */
/* First copy command data */
offset =
#ifdef MBOX_EXT_SUPPORT
}
#endif /* MBOX_EXT_SUPPORT */
}
/* Check for config port command */
/* copy command data into host mbox for cmpl */
/* First copy command data */
(MAILBOX_CMD_WSIZE - 1));
/* copy over last word, with mbxOwner set */
/* switch over to host mailbox */
} else { /* SLIM 1 */
#ifdef MBOX_EXT_SUPPORT
}
#endif /* MBOX_EXT_SUPPORT */
/* First copy command data */
(MAILBOX_CMD_WSIZE - 1));
/* copy over last word, with mbxOwner set */
}
/* Interrupt board to do it right away */
switch (flag) {
case MBX_NOWAIT:
return (MBX_SUCCESS);
case MBX_SLEEP:
/* Wait for completion */
/* The driver clock is timing the mailbox. */
/* emlxs_mb_fini() will be called externally. */
}
"Timeout. %s: mb=%p tmo=%d. Sleep.",
} else {
"Completed. %s: mb=%p status=%x Sleep.",
}
}
break;
case MBX_POLL:
/* Convert tmo seconds to 500 usec tics */
ha_copy =
/* Wait for command to complete */
/* self time */
"%s: mb=%p Polled.",
mbxCommand), mb);
break;
}
DELAYUS(500);
}
"Timeout. %s: mb=%p tmo=%d. Polled.",
tmo);
break;
}
}
/* Get first word of mailbox */
sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
} else {
word0 =
}
/* Wait for command to complete */
/* self time */
"%s: mb=%p Polled.",
break;
}
DELAYUS(500);
/* Get first word of mailbox */
} else {
word0 =
}
} /* while */
"Timeout. %s: mb=%p tmo=%d. Polled.",
break;
}
/* copy results back to user */
} else {
}
#ifdef MBOX_EXT_SUPPORT
hba->mbox_ext_size);
} else {
}
}
#endif /* MBOX_EXT_SUPPORT */
/* Sync the memory buffer */
}
"Completed. %s: mb=%p status=%x Polled.",
}
/* Process the result */
}
/* Clear the attention bit */
/* Clean up the mailbox area */
break;
} /* switch (flag) */
} /* emlxs_sli3_issue_mbox_cmd() */
/*ARGSUSED*/
extern uint32_t
{
return (0);
} /* emlxs_sli4_issue_mbox_cmd() */
#ifdef SFCT_SUPPORT
extern uint32_t
{
timeout =
} else {
timeout = 0x80000000;
}
#ifdef FCT_API_TRACE
"emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d",
#endif /* FCT_API_TRACE */
/* Get the iotag by registering the packet */
if (!iotag) {
/* No more command slots available, retry later */
"Adapter Busy. Unable to allocate iotag. did=0x%x", did);
return (IOERR_NO_RESOURCES);
}
/* Initalize iocbq */
/* Unregister the packet */
"Adapter Busy. Unable to setup buffer list. did=%x", did);
return (IOERR_INTERNAL_ERROR);
}
/* Point of no return */
/* Initalize iocb */
} else { /* TF_READ_DATA */
}
return (IOERR_SUCCESS);
} /* emlxs_sli3_prep_fct_iocb() */
/*ARGSUSED*/
extern uint32_t
{
return (FCT_SUCCESS);
} /* emlxs_sli4_prep_fct_iocb() */
#endif /* SFCT_SUPPORT */
extern uint32_t
{
/* Find target node object */
/* Get the iotag by registering the packet */
if (!iotag) {
/*
* No more command slots available, retry later
*/
"Adapter Busy. Unable to allocate iotag: did=0x%x", did);
return (FC_TRAN_BUSY);
}
/* Initalize iocbq */
/* Unregister the packet */
"Adapter Busy. Unable to setup buffer list. did=%x", did);
return (FC_TRAN_BUSY);
}
/* Point of no return */
/* Initalize iocb */
iocb->ulpRsvdByte =
case FC_TRAN_CLASS1:
break;
case FC_TRAN_CLASS2:
/* iocb->ulpClass = CLASS3; */
break;
case FC_TRAN_CLASS3:
default:
break;
}
/* if device is FCP-2 device, set the following bit */
/* that says to run the FC-TAPE protocol. */
}
if (pkt->pkt_datalen == 0) {
} else {
}
return (FC_SUCCESS);
} /* emlxs_sli3_prep_fcp_iocb() */
/*ARGSUSED*/
extern uint32_t
{
return (FC_SUCCESS);
} /* emlxs_sli4_prep_fcp_iocb() */
extern uint32_t
{
/* Get the iotag by registering the packet */
if (!iotag) {
/*
* No more command slots available, retry later
*/
"Adapter Busy. Unable to allocate iotag: did=0x%x", did);
return (FC_TRAN_BUSY);
}
/* Initalize iocbq */
/* Unregister the packet */
"Adapter Busy. Unable to setup buffer list. did=%x", did);
return (FC_TRAN_BUSY);
}
/* Point of no return */
/* Initalize iocb */
}
}
/* network headers */
iocb->ulpRsvdByte =
iocb->ulpContext = 0;
#ifdef SLI3_SUPPORT
}
}
#endif /* SLI3_SUPPORT */
} else {
}
case FC_TRAN_CLASS1:
break;
case FC_TRAN_CLASS2:
break;
case FC_TRAN_CLASS3:
default:
break;
}
return (FC_SUCCESS);
} /* emlxs_sli3_prep_ip_iocb() */
/*ARGSUSED*/
extern uint32_t
{
return (FC_SUCCESS);
} /* emlxs_sli4_prep_ip_iocb() */
extern uint32_t
{
/* Get the iotag by registering the packet */
if (!iotag) {
/*
* No more command slots available, retry later
*/
"Adapter Busy. Unable to allocate iotag. did=0x%x", did);
return (FC_TRAN_BUSY);
}
/* Initalize iocbq */
/* Unregister the packet */
"Adapter Busy. Unable to setup buffer list. did=%x", did);
return (FC_TRAN_BUSY);
}
/* Point of no return */
/* Initalize iocb */
/* ELS Response */
} else {
/* ELS Request */
iocb->ulpContext =
cmd &= ELS_CMD_MASK;
} else {
}
}
}
iocb->ulpRsvdByte =
case FC_TRAN_CLASS1:
break;
case FC_TRAN_CLASS2:
break;
case FC_TRAN_CLASS3:
default:
break;
}
return (FC_SUCCESS);
} /* emlxs_sli3_prep_els_iocb() */
/*ARGSUSED*/
extern uint32_t
{
return (FC_SUCCESS);
} /* emlxs_sli4_prep_els_iocb() */
extern uint32_t
{
/* Get the iotag by registering the packet */
if (!iotag) {
/*
* No more command slots available, retry later
*/
"Adapter Busy. Unable to allocate iotag. did=0x%x", did);
return (FC_TRAN_BUSY);
}
/* Unregister the packet */
"Adapter Busy. Unable to setup buffer list. did=%x", did);
return (FC_TRAN_BUSY);
}
/* Point of no return */
/* Initalize iocbq */
/* Fill in rest of iocb */
}
}
/* Initalize iocb */
/* CT Response */
} else {
/* CT Request */
}
iocb->ulpRsvdByte =
case FC_TRAN_CLASS1:
break;
case FC_TRAN_CLASS2:
break;
case FC_TRAN_CLASS3:
default:
break;
}
return (FC_SUCCESS);
} /* emlxs_sli3_prep_ct_iocb() */
/*ARGSUSED*/
extern uint32_t
{
return (FC_SUCCESS);
} /* emlxs_sli4_prep_ct_iocb() */
#ifdef SFCT_SUPPORT
static uint32_t
{
struct stmf_sglist_ent *sgl;
sgl++;
}
if (resid > 0) {
"emlxs_fct_bde_setup: Not enough scatter gather buffers "
" size=%d resid=%d count=%d",
return (1);
}
#ifdef SLI3_SUPPORT
} else {
}
#else /* !SLI3_SUPPORT */
#endif /* SLI3_SUPPORT */
return (rval);
} /* emlxs_fct_bde_setup() */
#endif /* SFCT_SUPPORT */
static uint32_t
{
#ifdef SLI3_SUPPORT
} else {
}
#else /* !SLI3_SUPPORT */
#endif /* SLI3_SUPPORT */
return (rval);
} /* emlxs_bde_setup() */
extern void
{
/*
* Polling a specific attention bit.
*/
for (;;) {
break;
}
}
/* Process the attentions */
return;
} /* emlxs_sli3_poll_intr() */
/*ARGSUSED*/
extern void
{
return;
} /* emlxs_sli4_poll_intr() */
#ifdef MSI_SUPPORT
extern uint32_t
{
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
* "emlxs_sli3_msi_intr: arg1=%p arg2=%p", arg1, arg2);
*/
/* Check for legacy interrupt handling */
return (DDI_INTR_CLAIMED);
} else {
return (DDI_INTR_UNCLAIMED);
}
}
/* Get host attention bits */
if (ha_copy == 0) {
if (hba->intr_unclaimed) {
return (DDI_INTR_UNCLAIMED);
}
} else {
hba->intr_unclaimed = 0;
}
/* Process the interrupt */
return (DDI_INTR_CLAIMED);
}
/* DDI_INTR_TYPE_MSI */
/* DDI_INTR_TYPE_MSIX */
/* Get MSI message id */
/* Validate the message id */
msgid = 0;
}
/* Check if adapter is offline */
/* Always claim an MSI interrupt */
return (DDI_INTR_CLAIMED);
}
/* Disable interrupts associated with this msgid */
restore = 1;
}
/* Get host attention bits */
/* Process the interrupt */
/* Restore interrupts */
if (restore) {
}
return (DDI_INTR_CLAIMED);
} /* emlxs_sli3_msi_intr() */
/*ARGSUSED*/
extern uint32_t
{
return (DDI_INTR_CLAIMED);
} /* emlxs_sli4_msi_intr() */
#endif /* MSI_SUPPORT */
extern int
emlxs_sli3_intx_intr(char *arg)
{
return (DDI_INTR_CLAIMED);
} else {
return (DDI_INTR_UNCLAIMED);
}
}
/* Get host attention bits */
if (ha_copy == 0) {
if (hba->intr_unclaimed) {
return (DDI_INTR_UNCLAIMED);
}
} else {
hba->intr_unclaimed = 0;
}
/* Process the interrupt */
return (DDI_INTR_CLAIMED);
} /* emlxs_sli3_intx_intr() */
/*ARGSUSED*/
extern int
emlxs_sli4_intx_intr(char *arg)
{
return (DDI_INTR_CLAIMED);
} /* emlxs_sli4_intx_intr() */
/* EMLXS_PORT_LOCK must be held when call this routine */
{
#ifdef MSI_SUPPORT
/* Check for default MSI interrupt */
if (msgid == 0) {
/* Read host attention register to determine interrupt source */
/* Filter out MSI non-default attention bits */
}
/* Check for polled or fixed type interrupt */
else if (msgid == -1) {
/* Read host attention register to determine interrupt source */
}
/* Otherwise, assume a mapped MSI interrupt */
else {
/* Convert MSI msgid to mapped attention bits */
}
#else /* !MSI_SUPPORT */
/* Read host attention register to determine interrupt source */
#endif /* MSI_SUPPORT */
/* Check if Hardware error interrupt is enabled */
}
/* Check if link interrupt is enabled */
}
/* Check if Mailbox interrupt is enabled */
}
/* Check if ring0 interrupt is enabled */
}
/* Check if ring1 interrupt is enabled */
}
/* Check if ring2 interrupt is enabled */
}
/* Check if ring3 interrupt is enabled */
}
/* Accumulate attention bits */
/* Clear attentions except for error, link, and autoclear(MSIX) */
if (ha_copy2) {
}
return (ha_copy);
} /* emlxs_get_attention() */
void
{
/* ha_copy should be pre-filtered */
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
* "emlxs_proc_attention: ha_copy=%x", ha_copy);
*/
return;
}
if (!ha_copy) {
return;
}
(void) READ_SBUS_CSR_REG(hba,
}
/* Adapter error */
return;
}
/* Mailbox interrupt */
(void) emlxs_handle_mb_event(hba);
}
/* Link Attention interrupt */
}
/* event on ring 0 - FCP Ring */
}
/* event on ring 1 - IP Ring */
}
/* event on ring 2 - ELS Ring */
}
/* event on ring 3 - CT Ring */
}
}
/* Set heartbeat flag to show activity */
return;
} /* emlxs_proc_attention() */
/*
* emlxs_handle_ff_error()
*
* Description: Processes a FireFly error
* Runs at Interrupt level
*/
extern void
{
int i = 0;
/* do what needs to be done, get error from STATUS REGISTER */
/* Clear Chip error bit */
/* If HS_FFER1 is set, then wait until the HS_FFER1 bit clears */
"HS_FFER1 received");
(void) emlxs_offline(hba);
status =
DELAYMS(1000);
i++;
}
}
if (i == 300) {
/* 5 minutes is up, shutdown HBA */
"HS_FFER1 clear timeout");
goto go_shutdown;
}
"HS_FFER1 cleared");
if (status & HS_OVERTEMP) {
status1 =
"Maximum adapter temperature exceeded (%d �C).", status1);
} else {
status1 =
status2 =
"Host Error Attention: "
"status=0x%x status1=0x%x status2=0x%x",
}
} else {
}
} /* emlxs_handle_ff_error() */
/*
* emlxs_handle_link_event()
*
* Description: Process a Link Attention.
*/
static void
{
/* Get a buffer which will be used for mailbox commands */
/* Get link attention message */
0) != MBX_BUSY) {
}
/*
* Clear Link Attention in HA REG
*/
HA_LATT);
} else {
}
}
} /* emlxs_handle_link_event() */
/*
* emlxs_handle_ring_event()
*
* Description: Process a Ring Attention.
*/
static void
{
void *ioa2;
count = 0;
/*
* Isolate this ring's host attention bits
* This makes all ring attention bits equal
* to Ring0 attention bits
*/
/*
* Gather iocb entries off response ring.
* Ensure entry is owned by the host.
*/
offset =
/* While ring is not empty */
/* Get the next response ring iocb */
entry =
/* DMA sync the response ring iocb for the adapter */
count++;
/* Copy word6 and word7 to local iocb for now */
iocbq = &local_iocbq;
/* when LE is not set, entire Command has not been received */
/* This should never happen */
"ulpLE is not set. "
"ring=%d iotag=%x cmd=%x status=%x",
goto next;
}
#ifdef SFCT_SUPPORT
case CMD_CLOSE_XRI_CX:
case CMD_ABORT_XRI_CX:
break;
}
sbp =
break;
#endif /* SFCT_SUPPORT */
/* Ring 0 registered commands */
case CMD_FCP_ICMND_CR:
case CMD_FCP_ICMND_CX:
case CMD_FCP_IREAD_CR:
case CMD_FCP_IREAD_CX:
case CMD_FCP_IWRITE_CR:
case CMD_FCP_IWRITE_CX:
case CMD_FCP_ICMND64_CR:
case CMD_FCP_ICMND64_CX:
case CMD_FCP_IREAD64_CR:
case CMD_FCP_IREAD64_CX:
case CMD_FCP_IWRITE64_CR:
case CMD_FCP_IWRITE64_CX:
#ifdef SFCT_SUPPORT
case CMD_FCP_TSEND_CX:
case CMD_FCP_TSEND64_CX:
case CMD_FCP_TRECEIVE_CX:
case CMD_FCP_TRECEIVE64_CX:
case CMD_FCP_TRSP_CX:
case CMD_FCP_TRSP64_CX:
#endif /* SFCT_SUPPORT */
/* Ring 1 registered commands */
case CMD_XMIT_BCAST_CN:
case CMD_XMIT_BCAST_CX:
case CMD_XMIT_SEQUENCE_CX:
case CMD_XMIT_SEQUENCE_CR:
case CMD_XMIT_BCAST64_CN:
case CMD_XMIT_BCAST64_CX:
case CMD_XMIT_SEQUENCE64_CX:
case CMD_XMIT_SEQUENCE64_CR:
case CMD_CREATE_XRI_CR:
case CMD_CREATE_XRI_CX:
/* Ring 2 registered commands */
case CMD_ELS_REQUEST_CR:
case CMD_ELS_REQUEST_CX:
case CMD_XMIT_ELS_RSP_CX:
case CMD_ELS_REQUEST64_CR:
case CMD_ELS_REQUEST64_CX:
case CMD_XMIT_ELS_RSP64_CX:
/* Ring 3 registered commands */
case CMD_GEN_REQUEST64_CR:
case CMD_GEN_REQUEST64_CX:
sbp =
break;
default:
}
/* If packet is stale, then drop it. */
if (sbp == STALE_PACKET) {
/* Copy entry to the local iocbq */
"ringno=%d iocb=%p cmd=%x status=%x "
"error=%x iotag=%x context=%x info=%x",
goto next;
}
/*
* If a packet was found, then queue the packet's
* iocb for deferred processing
*/
else if (sbp) {
#ifdef SFCT_SUPPORT
if (fct_cmd) {
cmd_sbp =
}
#endif /* SFCT_SUPPORT */
/* Copy entry to sbp's iocbq */
/*
* If this is NOT a polled command completion
* or a driver allocated pkt, then defer pkt
* completion.
*/
(PACKET_POLLED | PACKET_ALLOCATED))) {
/* Add the IOCB to the local list */
if (!rsp_head) {
} else {
}
goto next;
}
} else {
/* Copy entry to the local iocbq */
}
/* process the ring event now */
next:
/* Increment the driver's local response get index */
}
} /* while(TRUE) */
if (rsp_head) {
} else {
}
}
/* Check if at least one response entry was processed */
if (count) {
/* Update response get index for the adapter */
/* DMA sync the index for the adapter */
} else {
ioa2 =
1) * sizeof (uint32_t)));
}
if (reg & HA_R0RE_REQ) {
/* HBASTATS.chipRingFree++; */
/* Tell the adapter we serviced the ring */
chipatt);
}
}
/* HBASTATS.hostRingFree++; */
/* Cmd ring may be available. Try sending more iocbs */
}
/* HBASTATS.ringEvent++; */
return;
} /* emlxs_handle_ring_event() */
int
{
char error_str[64];
#ifdef SLI3_SUPPORT
#endif /* SLI3_SUPPORT */
switch (ringno) {
#ifdef SFCT_SUPPORT
case FC_FCT_RING:
break;
#endif /* SFCT_SUPPORT */
case FC_IP_RING:
break;
case FC_ELS_RING:
break;
case FC_CT_RING:
break;
default:
"ring=%d cmd=%x %s %x %x %x %x",
return (1);
}
goto done;
} else {
}
goto failed;
}
#ifdef SLI3_SUPPORT
(*UbPosted)--;
hbqe_tag);
goto dropped;
}
} else
#endif /* SLI3_SUPPORT */
{
bdeAddr =
/* Check for invalid buffer */
goto dropped;
}
}
if (!mp) {
goto dropped;
}
if (!size) {
goto dropped;
}
#ifdef SLI3_SUPPORT
/* To avoid we drop the broadcast packets */
if (ringno != FC_IP_RING) {
/* Get virtual port */
"Invalid VPI=%d:", vpi);
goto dropped;
}
}
}
#endif /* SLI3_SUPPORT */
/* Process request */
switch (ringno) {
#ifdef SFCT_SUPPORT
case FC_FCT_RING:
break;
#endif /* SFCT_SUPPORT */
case FC_IP_RING:
break;
case FC_ELS_RING:
/* If this is a target port, then let fct handle this */
#ifdef SFCT_SUPPORT
size);
#endif /* SFCT_SUPPORT */
} else {
size);
}
break;
case FC_CT_RING:
break;
}
goto done;
(*RcvDropped)++;
"%s: cmd=%x %s %x %x %x %x",
if (ringno == FC_FCT_RING) {
#ifdef SLI3_SUPPORT
} else
#endif /* SLI3_SUPPORT */
{
}
}
goto done;
(*RcvError)++;
"%s: cmd=%x %s %x %x %x %x hba:%x %x",
done:
#ifdef SLI3_SUPPORT
} else
#endif /* SLI3_SUPPORT */
{
if (mp) {
}
}
return (0);
} /* emlxs_handle_rcv_seq() */
/* EMLXS_CMD_RING_LOCK must be held when calling this function */
static void
{
/* Check for ULP pkt request */
if (sbp) {
/* Set node to base node by default */
}
}
/* get the next available command ring iocb */
iocb =
/* Copy the local iocb to the command ring iocb */
hba->iocb_cmd_size);
/* DMA sync the command ring iocb for the adapter */
/* Free the local iocb if there is no sbp tracking it */
if (!sbp) {
}
#ifdef SFCT_SUPPORT
else {
if (fct_cmd) {
#ifdef FCT_IO_TRACE
icmd->ulpCommand);
#endif /* FCT_IO_TRACE */
}
}
#endif /* SFCT_SUPPORT */
/* update local ring index to next available ring index */
return;
} /* emlxs_issue_iocb() */
extern uint32_t
{
uint32_t j;
interlock_failed = 0;
return (FC_SUCCESS);
}
j = 0;
while (j++ < 10000) {
if (hba->mbox_queue_flag == 0) {
break;
}
DELAYUS(100);
}
if (hba->mbox_queue_flag != 0) {
"Interlock failed. Mailbox busy.");
return (FC_SUCCESS);
}
/* Disable all host interrupts */
goto mode_B;
}
"Attempting SLIM2 Interlock...");
value = 0xFFFFFFFF;
word0 = 0;
/* Write value to SLIM */
/* Send Kill board request */
/* Sync the memory */
/* interrupt board to do it right away */
/* First wait for command acceptence */
j = 0;
while (j++ < 1000) {
if (value == 0) {
break;
}
DELAYUS(50);
}
if (value == 0) {
/* Now wait for mailbox ownership to clear */
while (j++ < 10000) {
word0 =
break;
}
DELAYUS(50);
}
"Interlock succeeded.");
goto done;
}
/* Interlock failed !!! */
interlock_failed = 1;
"Attempting SLIM1 Interlock...");
value = 0xFFFFFFFF;
word0 = 0;
/* Write KILL BOARD to mailbox */
/* interrupt board to do it right away */
/* First wait for command acceptence */
j = 0;
while (j++ < 1000) {
if (value == 0) {
break;
}
DELAYUS(50);
}
if (value == 0) {
/* Now wait for mailbox ownership to clear */
while (j++ < 10000) {
word0 =
break;
}
DELAYUS(50);
}
"Interlock succeeded.");
goto done;
}
/* Interlock failed !!! */
/* If this is the first time then try again */
if (interlock_failed == 0) {
"Interlock failed. Retrying...");
/* Try again */
interlock_failed = 1;
goto interlock_B;
}
/*
* Now check for error attention to indicate the board has
* been kiilled
*/
j = 0;
while (j++ < 10000) {
break;
}
DELAYUS(50);
}
"Interlock failed. Board killed.");
} else {
"Interlock failed. Board not killed.");
}
done:
hba->mbox_queue_flag = 0;
return (FC_SUCCESS);
} /* emlxs_interlock() */
extern uint32_t
{
uint32_t i;
"%s: Unable to allocate mailbox buffer.",
return ((uint32_t)FC_FAILURE);
}
"%s: Unable to reset ring. Mailbox cmd=%x status=%x",
return ((uint32_t)FC_FAILURE);
}
/* Free the mailbox */
/* Update the response ring indicies */
/* Update the command ring indicies */
for (i = 0; i < MAX_VPORTS; i++) {
continue;
}
/* Clear all node XRI contexts */
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
}
}
}
return (FC_SUCCESS);
} /* emlxs_reset_ring() */
/*
* emlxs_handle_mb_event
*
* Description: Process a Mailbox Attention.
* Called from host_interrupt to process MBATT
*
* Returns:
*
*/
extern uint32_t
{
uint32_t i;
switch (hba->mbox_queue_flag) {
case 0:
"No mailbox active.");
return (0);
case MBX_POLL:
/* Mark mailbox complete, this should wake up any polling */
/* threads. This can happen if interrupts are enabled while */
/* a polled mailbox command is outstanding. If we don't set */
/* MBQ_COMPLETED here, the polling thread may wait until */
/* timeout error occurs */
if (mbq) {
"Mailbox event. Completing Polled command.");
}
return (0);
case MBX_SLEEP:
case MBX_NOWAIT:
break;
default:
"Invalid Mailbox flag (%x).");
return (0);
}
/* Get first word of mailbox */
sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
} else {
}
i = 0;
if (i++ > 10000) {
"OWN_CHIP: %s: status=%x",
return (1);
}
/* Get first word of mailbox */
sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
} else {
word0 =
}
}
/* Now that we are the owner, DMA Sync entire mailbox if needed */
} else {
}
#ifdef MBOX_EXT_SUPPORT
} else {
}
}
#endif /* MBOX_EXT_SUPPORT */
/* Now sync the memory buffer if one was used */
}
/* Mailbox has been completely received at this point */
hba->heartbeat_active = 0;
goto done;
}
"Received. %s: status=%x Sleep.",
}
} else {
"Completed. %s: status=%x",
}
}
/* Filter out passthru mailbox */
goto done;
}
/* If succesful, process the result */
goto done;
}
/* ERROR RETURNED */
/* Check for no resources */
/* Retry only MBX_NOWAIT requests */
"Retrying. %s: status=%x",
switch (mbox->mbxCommand) {
case MBX_READ_SPARM:
if (control == 0) {
}
break;
case MBX_READ_SPARM64:
control =
if (control == 0) {
}
break;
case MBX_REG_LOGIN:
if (control == 0) {
#ifdef NPIV_SUPPORT
/* Special handle for vport PLOGI */
}
#endif /* NPIV_SUPPORT */
goto done;
}
break;
case MBX_REG_LOGIN64:
control =
if (control == 0) {
#ifdef NPIV_SUPPORT
/* Special handle for vport PLOGI */
}
#endif /* NPIV_SUPPORT */
goto done;
}
break;
case MBX_READ_LA:
control =
if (control == 0) {
}
break;
case MBX_READ_LA64:
control =
if (control == 0) {
}
break;
}
/* Refresh the mailbox area */
0) != MBX_BUSY) {
}
return (0);
}
}
/*
* ERROR: process mailbox command error
*/
switch (mb->mbxCommand) {
case MBX_REG_LOGIN:
case MBX_REG_LOGIN64:
#ifdef SLI3_SUPPORT
#endif /* SLI3_SUPPORT */
}
#ifdef NPIV_SUPPORT
/* Special handle for vport PLOGI */
}
#endif /* NPIV_SUPPORT */
break;
case MBX_READ_LA:
case MBX_READ_LA64:
/* Enable Link Attention interrupts */
}
break;
case MBX_CLEAR_LA:
la_enable = 1;
/* Get a buffer which will be used for */
/* mailbox commands */
/* Get link attention message */
MBX_NOWAIT, 0) != MBX_BUSY) {
(void) emlxs_mem_put(hba,
}
la_enable = 0;
} else {
}
}
}
if (la_enable) {
/* Enable Link Attention interrupts */
}
} else {
/* Disable Link Attention interrupts */
}
}
break;
case MBX_INIT_LINK:
/* Retry only MBX_NOWAIT requests */
"Retrying. %s: status=%x. Auto-speed set.",
MEM_MBOX))) {
/* Refresh the mailbox area */
MBX_NOWAIT, 0) != MBX_BUSY) {
(void) emlxs_mem_put(hba,
}
return (0);
}
}
}
break;
}
done:
/* Clean up the mailbox area */
/* Attempt to send pending mailboxes */
MBX_BUSY) {
}
}
return (0);
} /* emlxs_handle_mb_event() */
/*
* emlxs_mb_handle_cmd
*
* Description: Process a Mailbox Command.
* Called from host_interrupt to process MBATT
*
* Returns:
*
*/
static int
{
int32_t i;
return (1);
}
/*
* Mailbox command completed successfully, process completion
*/
switch (mb->mbxCommand) {
case MBX_SHUTDOWN:
case MBX_LOAD_SM:
case MBX_READ_NV:
case MBX_WRITE_NV:
case MBX_RUN_BIU_DIAG:
case MBX_RUN_BIU_DIAG64:
case MBX_INIT_LINK:
case MBX_DOWN_LINK:
case MBX_CONFIG_LINK:
case MBX_PART_SLIM:
case MBX_CONFIG_RING:
case MBX_RESET_RING:
case MBX_READ_CONFIG:
case MBX_READ_RCONFIG:
case MBX_READ_STATUS:
case MBX_READ_XRI:
case MBX_READ_REV:
case MBX_READ_LNK_STAT:
case MBX_UNREG_LOGIN:
case MBX_DUMP_MEMORY:
case MBX_DUMP_CONTEXT:
case MBX_RUN_DIAGS:
case MBX_RESTART:
case MBX_UPDATE_CFG:
case MBX_DOWN_LOAD:
case MBX_DEL_LD_ENTRY:
case MBX_RUN_PROGRAM:
case MBX_SET_MASK:
case MBX_SET_VARIABLE:
case MBX_UNREG_D_ID:
case MBX_KILL_BOARD:
case MBX_CONFIG_FARP:
case MBX_LOAD_AREA:
case MBX_CONFIG_PORT:
case MBX_CONFIG_MSI:
case MBX_FLASH_WR_ULA:
case MBX_SET_DEBUG:
case MBX_GET_DEBUG:
case MBX_LOAD_EXP_ROM:
case MBX_BEACON:
case MBX_READ_RPI:
case MBX_READ_RPI64:
case MBX_REG_VPI:
case MBX_UNREG_VPI:
case MBX_CONFIG_HBQ:
case MBX_ASYNC_EVENT:
case MBX_HEARTBEAT:
case MBX_READ_EVENT_LOG:
case MBX_WRITE_EVENT_LOG:
case MBX_NV_LOG:
case MBX_PORT_CAPABILITIES:
case MBX_IOV_CONTROL:
case MBX_IOV_MBX:
break;
case MBX_CONFIG_MSIX:
break;
case MBX_READ_SPARM: /* a READ SPARAM command completed */
case MBX_READ_SPARM64: /* a READ SPARAM command completed */
{
if (mp) {
sizeof (SERV_PARM));
/* Initialize thenode name and port name only once */
/* Initialize the physical port */
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
/* Initialize the virtual ports */
for (i = 1; i < MAX_VPORTS; i++) {
continue;
}
sizeof (SERV_PARM));
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
}
}
}
break;
}
case MBX_REG_LOGIN:
case MBX_REG_LOGIN64:
if (!mp) {
break;
}
#ifdef SLI3_SUPPORT
#endif /* SLI3_SUPPORT */
/* First copy command data */
if (!ndlp) {
/* Attempt to create a node */
sizeof (SERV_PARM));
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
/* Add the node */
/* Open the node */
} else {
"Unable to allocate node. did=%06x rpi=%x "
"wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
break;
}
} else {
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
"node=%p did=%06x rpi=%x "
"wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
wwn[7]);
/* Open the node */
}
if (sp->valid_vendor_version) {
}
}
/* If this was a fabric login */
/* If CLEAR_LA has been sent, then attempt to */
/* register the vpi now */
(void) emlxs_mb_reg_vpi(port);
}
#ifdef SLI3_SUPPORT
/*
* If NPIV Fabric support has just been established on
* the physical port, then notify the vports of the
* link up
*/
if ((lvpi == 0) &&
/* Skip the physical port */
for (i = 1; i < MAX_VPORTS; i++) {
continue;
}
}
}
#endif /* SLI3_SUPPORT */
}
#ifdef NPIV_SUPPORT
}
#endif /* NPIV_SUPPORT */
#ifdef DHCHAP_SUPPORT
/* Auth started - auth completion will */
/* handle sbp and ubp now */
}
}
#endif /* DHCHAP_SUPPORT */
#ifdef SFCT_SUPPORT
}
}
#endif /* SFCT_SUPPORT */
break;
case MBX_READ_LA:
case MBX_READ_LA64:
{
if (mp) {
128);
} else {
}
"tag=%d -> %d ALPA=%x",
} else {
"tag=%d -> %d ALPA=%x",
}
} else {
}
/* Declare link down here */
}
}
/* If link not already up then declare it up now */
#ifdef MENLO_SUPPORT
la.granted_AL_PA = 0;
}
#endif /* MENLO_SUPPORT */
/* Save the linkspeed */
/* Check for old model adapters that only */
/* supported 1Gb */
}
} else {
}
if (i == 0) {
} else {
uint32_t j;
/* Check number of devices in map */
}
"alpa_map: %d device(s): "
"%02x %02x %02x %02x %02x %02x "
"alpa_map: "
"%02x %02x %02x %02x %02x "
"%02x %02x %02x",
alpa_map[j],
alpa_map[j + 1],
alpa_map[j + 2],
alpa_map[j + 3],
alpa_map[j + 4],
alpa_map[j + 5],
alpa_map[j + 6],
alpa_map[j + 7]);
}
}
}
#ifdef MENLO_SUPPORT
/* Check if Menlo maintenance mode is enabled */
"Maintenance Mode enabled.");
} else {
"Maintenance Mode disabled.");
}
/* Check FCoE attention bit */
}
}
#endif /* MENLO_SUPPORT */
/* This should turn on DELAYED ABTS for */
/* ELS timeouts */
0x00052198, 0x1);
}
/* If link not already down then */
/* declare it down now */
if (emlxs_mb_read_sparam(hba,
} else {
}
}
}
/* Declare the linkup here */
}
/* If link not already down then declare it down now */
/* Declare link down here */
}
/* Enable Link attention interrupt */
}
/* Log the link event */
break;
}
case MBX_CLEAR_LA:
/* Enable on Link Attention interrupts */
}
}
/* Adapter is now ready for FCP traffic */
/* Register vpi's for all ports that have did's */
for (i = 0; i < MAX_VPORTS; i++) {
continue;
}
(void) emlxs_mb_reg_vpi(vport);
}
/* Attempt to send any pending IO */
0);
}
break;
default:
break;
}
return (0);
} /* emlxs_mb_handle_cmd() */
void
{
return;
}
/* Return if timer hasn't expired */
return;
}
hba->mbox_timer = 0;
/* Mailbox timed out, first check for error attention */
return;
}
if (hba->mbox_queue_flag) {
/* Get first word of mailbox */
sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
} else {
word0 =
}
/* Check if mailbox has actually completed */
/* Read host attention register to determine */
/* interrupt source */
"Mailbox attention missed: %s. Forcing event. "
(void) emlxs_handle_mb_event(hba);
return;
}
}
}
switch (hba->mbox_queue_flag) {
case MBX_NOWAIT:
break;
case MBX_SLEEP:
mb);
break;
case MBX_POLL:
mb);
break;
default:
break;
}
/* Perform mailbox cleanup */
/* This will wake any sleeping or polling threads */
/* Trigger adapter shutdown */
return;
} /* emlxs_timer_check_mbox() */
/*
* emlxs_mb_config_port Issue a CONFIG_PORT mailbox command
*/
{
uint32_t i;
#ifdef SLI3_SUPPORT
#else /* SLI3_SUPPORT */
#endif /* SLI3_SUPPORT */
/* Set Host pointers in SLIM flag */
/* Initialize hba structure for assumed default SLI2 mode */
/* If config port succeeds, then we will update it then */
#ifdef SLI3_SUPPORT
if (sli_mode >= EMLXS_HBA_SLI3_MODE) {
#ifdef NPIV_SUPPORT
MAX_VPORTS - 1;
} else {
MAX_VPORTS_LIMITED - 1;
}
} else {
"CFGPORT: Firmware does not support NPIV. "
}
}
#endif /* NPIV_SUPPORT */
}
#endif /* SLI3_SUPPORT */
/*
* Now setup pcb
*/
sizeof (MAILBOX) + MBOX_EXTENSION_SIZE;
/*
* Set up HGP - Port Memory
*
* CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
* RR0Get 0xc4 0x84
* CR1Put 0xc8 0x88
* RR1Get 0xcc 0x8c
* CR2Put 0xd0 0x90
* RR2Get 0xd4 0x94
* CR3Put 0xd8 0x98
* RR3Get 0xdc 0x9c
*
* Reserved 0xa0-0xbf
*
* If HBQs configured:
* HBQ 0 Put ptr 0xc0
* HBQ 1 Put ptr 0xc4
* HBQ 2 Put ptr 0xc8
* ...
* HBQ(M-1)Put Pointer 0xc0+(M-1)*4
*/
#ifdef SLI3_SUPPORT
if (sli_mode >= EMLXS_HBA_SLI3_MODE) {
/* ERBM is enabled */
} else /* SLI2 */
#endif /* SLI3_SUPPORT */
{
/* ERBM is disabled */
hba->hgp_hbq_offset = 0;
}
/* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */
} else {
Laddr =
Laddr &= ~0x4;
}
offset = 0;
for (i = 0; i < 4; i++) {
/* Setup command ring */
rp->fc_cmdringaddr =
/* Setup response ring */
rp->fc_rspringaddr =
}
offset =
return (0);
} /* emlxs_mb_config_port() */
{
void *ioa2;
uint32_t j;
switch (hbq_id) {
case EMLXS_ELS_HBQ_ID:
seg = MEM_ELSBUF;
break;
case EMLXS_IP_HBQ_ID:
ringno = FC_IP_RING;
break;
case EMLXS_CT_HBQ_ID:
ringno = FC_CT_RING;
break;
#ifdef SFCT_SUPPORT
case EMLXS_FCT_HBQ_ID:
seg = MEM_FCTBUF;
break;
#endif /* SFCT_SUPPORT */
default:
"emlxs_hbq_setup: Invalid HBQ id. (%x)", hbq_id);
return (1);
}
/* Configure HBQ */
/* Get a Mailbox buffer to setup mailbox commands for CONFIG_HBQ */
"emlxs_hbq_setup: Unable to get mailbox.");
return (1);
}
/* Allocate HBQ Host buffer and Initialize the HBQEs */
"emlxs_hbq_setup: Unable to allocate HBQ.");
return (1);
}
/* 0=all, 7=logentry */
/* HBQ to a ring */
/* Ring0=b0001, Ring1=b0010, */
/* Ring2=b0100 */
/* be used for */
hbq->HBQ_PutIdx_next = 0;
hbq->HBQ_GetIdx = 0;
/* Fill in POST BUFFERs in HBQE */
/* Allocate buffer to post */
"emlxs_hbq_setup: Unable to allocate HBQ buffer. "
"cnt=%d", j);
return (1);
}
}
/* Issue CONFIG_HBQ */
"emlxs_hbq_setup: Unable to config HBQ. cmd=%x status=%x",
return (1);
}
return (0);
} /* emlxs_hbq_setup */
void
{
uint32_t j;
switch (hbq_id) {
case EMLXS_ELS_HBQ_ID:
seg = MEM_ELSBUF;
HBASTATS.ElsUbPosted = 0;
break;
case EMLXS_IP_HBQ_ID:
HBASTATS.IpUbPosted = 0;
break;
case EMLXS_CT_HBQ_ID:
HBASTATS.CtUbPosted = 0;
break;
#ifdef SFCT_SUPPORT
case EMLXS_FCT_HBQ_ID:
seg = MEM_FCTBUF;
HBASTATS.FctUbPosted = 0;
break;
#endif /* SFCT_SUPPORT */
default:
return;
}
for (j = 0; j < hbq->HBQ_PostBufCnt; j++) {
}
hbq->HBQ_PostBufCnt = 0;
}
return;
} /* emlxs_hbq_free_all() */
void
{
void *ioa2;
switch (hbq_id) {
case EMLXS_ELS_HBQ_ID:
break;
case EMLXS_IP_HBQ_ID:
break;
case EMLXS_CT_HBQ_ID:
break;
#ifdef SFCT_SUPPORT
case EMLXS_FCT_HBQ_ID:
break;
#endif /* SFCT_SUPPORT */
default:
return;
}
hbq->HBQ_PutIdx =
return;
}
}
return;
} /* emlxs_update_HBQ_index() */
void
{
/* Enable mailbox, error attention interrupts */
/* Enable ring interrupts */
status |=
status |= (HC_R0INT_ENA);
}
}
void
{
}
void
{
/* Disable all adapter interrupts */
}
{
return (ha_copy);
}