emlxs_solaris.c revision 62379b581655b9c347d192fce07f06c575a54ea3
/*
* 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.
*/
#define DEF_ICFG 1
#include <emlxs.h>
#include <emlxs_version.h>
char emlxs_revision[] = EMLXS_REVISION;
char emlxs_version[] = EMLXS_VERSION;
char emlxs_name[] = EMLXS_NAME;
char emlxs_label[] = EMLXS_LABEL;
/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
#ifdef MENLO_SUPPORT
#endif /* MENLO_SUPPORT */
/*
* Driver Entry Routines.
*/
/*
* FC_AL Transport Functions.
*/
static void emlxs_unbind_port(opaque_t);
/*
* Driver Internal Functions.
*/
#ifdef EMLXS_I386
#ifdef S11
#endif
#endif
static void emlxs_lock_destroy(emlxs_hba_t *);
static void emlxs_lock_init(emlxs_hba_t *);
char *emlxs_pm_components[] = {
"NAME=emlxx000",
"0=Device D3 State",
"1=Device D0 State"
};
/*
* Default emlx dma limits
*/
(uint32_t)0, /* dlim_addr_lo */
1, /* dlim_minxfer */
0x00ffffff /* dlim_dmaspeed */
};
/*
* Be careful when using these attributes; the defaults listed below are
* (almost) the most general case, permitting allocation in almost any
* way supported by the LightPulse family. The sole exception is the
* alignment specified as requiring memory allocation on a 4-byte boundary;
* the Lightpulse can DMA memory on any byte boundary.
*
* The LightPulse family currently is limited to 16M transfers;
* this restriction affects the dma_attr_count_max and dma_attr_maxxfer fields.
*/
DMA_ATTR_V0, /* dma_attr_version */
(uint64_t)0, /* dma_attr_addr_lo */
1, /* dma_attr_align */
1, /* dma_attr_minxfer */
EMLXS_SGLLEN, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
DMA_ATTR_V0, /* dma_attr_version */
(uint64_t)0, /* dma_attr_addr_lo */
1, /* dma_attr_align */
1, /* dma_attr_minxfer */
EMLXS_SGLLEN, /* dma_attr_sgllen */
1, /* dma_attr_granular */
DDI_DMA_RELAXED_ORDERING /* dma_attr_flags */
};
DMA_ATTR_V0, /* dma_attr_version */
(uint64_t)0, /* dma_attr_addr_lo */
1, /* dma_attr_align */
1, /* dma_attr_minxfer */
1, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
#if (EMLXS_MODREV >= EMLXS_MODREV3)
DMA_ATTR_V0, /* dma_attr_version */
(uint64_t)0, /* dma_attr_addr_lo */
1, /* dma_attr_align */
1, /* dma_attr_minxfer */
EMLXS_SGLLEN, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
#endif /* >= EMLXS_MODREV3 */
/*
* DDI access attributes for device
*/
DDI_DEVICE_ATTR_V1, /* devacc_attr_version */
DDI_STRUCTURE_LE_ACC, /* PCI is Little Endian */
DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */
DDI_DEFAULT_ACC /* devacc_attr_access */
};
/*
* DDI access attributes for data
*/
DDI_DEVICE_ATTR_V1, /* devacc_attr_version */
DDI_NEVERSWAP_ACC, /* don't swap for Data */
DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */
DDI_DEFAULT_ACC /* devacc_attr_access */
};
/*
* Fill in the FC Transport structure,
* as defined in the Fibre Channel Transport Programmming Guide.
*/
#if (EMLXS_MODREV == EMLXS_MODREV5)
static fc_fca_tran_t emlxs_fca_tran = {
FCTL_FCA_MODREV_5, /* fca_version, with SUN NPIV support */
MAX_VPORTS, /* fca numerb of ports */
sizeof (emlxs_buf_t), /* fca pkt size */
2048, /* fca cmd max */
&emlxs_dma_lim, /* fca dma limits */
0, /* fca iblock, to be filled in later */
&emlxs_dma_attr, /* fca dma attributes */
&emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */
&emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */
&emlxs_dma_attr_ro, /* fca dma fcp data attributes */
&emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */
&emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */
&emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */
&emlxs_dma_attr, /* fca dma fcsm rsp attributes */
&emlxs_data_acc_attr, /* fca access atributes */
0, /* fca_num_npivports */
{0, 0, 0, 0, 0, 0, 0, 0}, /* Physical port WWPN */
};
#endif /* EMLXS_MODREV5 */
#if (EMLXS_MODREV == EMLXS_MODREV4)
static fc_fca_tran_t emlxs_fca_tran = {
FCTL_FCA_MODREV_4, /* fca_version */
MAX_VPORTS, /* fca numerb of ports */
sizeof (emlxs_buf_t), /* fca pkt size */
2048, /* fca cmd max */
&emlxs_dma_lim, /* fca dma limits */
0, /* fca iblock, to be filled in later */
&emlxs_dma_attr, /* fca dma attributes */
&emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */
&emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */
&emlxs_dma_attr_ro, /* fca dma fcp data attributes */
&emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */
&emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */
&emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */
&emlxs_dma_attr, /* fca dma fcsm rsp attributes */
&emlxs_data_acc_attr, /* fca access atributes */
};
#endif /* EMLXS_MODEREV4 */
#if (EMLXS_MODREV == EMLXS_MODREV3)
static fc_fca_tran_t emlxs_fca_tran = {
FCTL_FCA_MODREV_3, /* fca_version */
MAX_VPORTS, /* fca numerb of ports */
sizeof (emlxs_buf_t), /* fca pkt size */
2048, /* fca cmd max */
&emlxs_dma_lim, /* fca dma limits */
0, /* fca iblock, to be filled in later */
&emlxs_dma_attr, /* fca dma attributes */
&emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */
&emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */
&emlxs_dma_attr_ro, /* fca dma fcp data attributes */
&emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */
&emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */
&emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */
&emlxs_dma_attr, /* fca dma fcsm rsp attributes */
&emlxs_data_acc_attr, /* fca access atributes */
};
#endif /* EMLXS_MODREV3 */
#if (EMLXS_MODREV == EMLXS_MODREV2)
static fc_fca_tran_t emlxs_fca_tran = {
FCTL_FCA_MODREV_2, /* fca_version */
MAX_VPORTS, /* number of ports */
sizeof (emlxs_buf_t), /* pkt size */
2048, /* max cmds */
&emlxs_dma_lim, /* DMA limits */
0, /* iblock, to be filled in later */
&emlxs_dma_attr, /* dma attributes */
&emlxs_data_acc_attr, /* access atributes */
};
#endif /* EMLXS_MODREV2 */
/*
* This is needed when the module gets loaded by the kernel
* so ddi library calls get resolved.
*/
#ifndef MODSYM_SUPPORT
char _depends_on[] = "misc/fctl";
#endif /* MODSYM_SUPPORT */
/*
* state pointer which the implementation uses as a place to
* hang a set of per-driver structures;
*
*/
void *emlxs_soft_state = NULL;
/*
* Driver Global variables.
*/
/*
* Single private "global" lock used to gain access to
* single-threaded.
*/
/*
* CB ops vector. Used for administration only.
*/
static struct cb_ops emlxs_cb_ops = {
emlxs_open, /* cb_open */
emlxs_close, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nodev, /* cb_read */
nodev, /* cb_write */
emlxs_ioctl, /* cb_ioctl */
nodev, /* cb_devmap */
nodev, /* cb_mmap */
nodev, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
0, /* cb_stream */
#ifdef _LP64
#else
#endif
CB_REV, /* rev */
nodev, /* cb_aread */
nodev /* cb_awrite */
};
DEVO_REV, /* rev */
0, /* refcnt */
emlxs_info, /* getinfo */
nulldev, /* identify */
nulldev, /* probe */
emlxs_attach, /* attach */
emlxs_detach, /* detach */
nodev, /* reset */
&emlxs_cb_ops, /* devo_cb_ops */
NULL, /* devo_bus_ops */
emlxs_power, /* power ops */
#ifdef EMLXS_I386
#ifdef S11
emlxs_quiesce, /* quiesce */
#endif
#endif
};
extern struct mod_ops mod_driverops;
#ifdef SAN_DIAG_SUPPORT
extern kmutex_t sd_bucket_mutex;
extern sd_bucket_info_t sd_bucket;
#endif /* SAN_DIAG_SUPPORT */
/*
* Module linkage information for the kernel.
*/
static struct modldrv emlxs_modldrv = {
&mod_driverops, /* module type - driver */
emlxs_name, /* module name */
&emlxs_ops, /* driver ops */
};
/*
* Driver module linkage structure
*/
static struct modlinkage emlxs_modlinkage = {
MODREV_1, /* ml_rev - must be MODREV_1 */
&emlxs_modldrv, /* ml_linkage */
NULL /* end of driver linkage */
};
/* We only need to add entries for non-default return codes. */
/* Entries do not need to be in order. */
/* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */
/* FC_EXPLN_NONE, FC_ACTION_RETRYABLE */
/* {f/w code, pkt_state, pkt_reason, */
/* pkt_expln, pkt_action} */
/* 0x00 - Do not remove */
/* 0x01 - Do not remove */
/* 0x02 */
/*
* This is a default entry.
* The real codes are written dynamically in emlxs_els.c
*/
/* 0x09 */
/* Special error code */
/* 0x10 */
/* Special error code */
/* 0x11 */
/* CLASS 2 only */
/* 0x04 */
/* CLASS 2 only */
/* 0x05 */
/* CLASS 2 only */
/* 0x06 */
/* CLASS 2 only */
/* 0x07 */
};
/* We only need to add entries for non-default return codes. */
/* Entries do not need to be in order. */
/* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */
/* FC_EXPLN_NONE, FC_ACTION_RETRYABLE} */
/* {f/w code, pkt_state, pkt_reason, */
/* pkt_expln, pkt_action} */
/* 0x01 */
/* 0x02 */
/* 0x04 */
/* 0x05 */
/* 0x06 */
/* 0x07 */
/* 0x08 */
/* 0x0B */
/* 0x0D */
/* 0x0E */
/* 0x0F */
/* 0x11 */
/* 0x13 */
/* 0x14 */
/* 0x15 */
/* 0x16 */
/* 0x17 */
/* 0x18 */
/* 0x1A */
/* 0x21 */
/* Occurs at link down */
/* 0x28 */
/* 0xF0 */
};
{IOERR_SUCCESS, "No error."},
{IOERR_MISSING_CONTINUE, "Missing continue."},
{IOERR_SEQUENCE_TIMEOUT, "Sequence timeout."},
{IOERR_INTERNAL_ERROR, "Internal error."},
{IOERR_INVALID_RPI, "Invalid RPI."},
{IOERR_NO_XRI, "No XRI."},
{IOERR_ILLEGAL_COMMAND, "Illegal command."},
{IOERR_XCHG_DROPPED, "Exchange dropped."},
{IOERR_ILLEGAL_FIELD, "Illegal field."},
{IOERR_RCV_BUFFER_WAITING, "RX buffer waiting."},
{IOERR_TX_DMA_FAILED, "TX DMA failed."},
{IOERR_RX_DMA_FAILED, "RX DMA failed."},
{IOERR_ILLEGAL_FRAME, "Illegal frame."},
{IOERR_NO_RESOURCES, "No resources."},
{IOERR_ILLEGAL_LENGTH, "Illegal length."},
{IOERR_UNSUPPORTED_FEATURE, "Unsupported feature."},
{IOERR_ABORT_IN_PROGRESS, "Abort in progess."},
{IOERR_ABORT_REQUESTED, "Abort requested."},
{IOERR_RCV_BUFFER_TIMEOUT, "RX buffer timeout."},
{IOERR_LOOP_OPEN_FAILURE, "Loop open failed."},
{IOERR_RING_RESET, "Ring reset."},
{IOERR_LINK_DOWN, "Link down."},
{IOERR_CORRUPTED_DATA, "Corrupted data."},
{IOERR_CORRUPTED_RPI, "Corrupted RPI."},
{IOERR_OUT_OF_ORDER_DATA, "Out-of-order data."},
{IOERR_OUT_OF_ORDER_ACK, "Out-of-order ack."},
{IOERR_DUP_FRAME, "Duplicate frame."},
{IOERR_LINK_CONTROL_FRAME, "Link control frame."},
{IOERR_BAD_HOST_ADDRESS, "Bad host address."},
{IOERR_RCV_HDRBUF_WAITING, "RX header buffer waiting."},
{IOERR_MISSING_HDR_BUFFER, "Missing header buffer."},
{IOERR_MSEQ_CHAIN_CORRUPTED, "MSEQ chain corrupted."},
{IOERR_ABORTMULT_REQUESTED, "Abort multiple requested."},
{IOERR_BUFFER_SHORTAGE, "Buffer shortage."},
{IOERR_XRIBUF_WAITING, "XRI buffer shortage"},
{IOERR_XRIBUF_MISSING, "XRI buffer missing"},
{IOERR_ROFFSET_INVAL, "Relative offset invalid."},
{IOERR_ROFFSET_MISSING, "Relative offset missing."},
{IOERR_INSUF_BUFFER, "Buffer too small."},
{IOERR_MISSING_SI, "ELS frame missing SI"},
{IOERR_MISSING_ES, "Exhausted burst without ES"},
{IOERR_INCOMP_XFER, "Transfer incomplete."},
{IOERR_ABORT_TIMEOUT, "Abort timeout."}
}; /* emlxs_error_table */
{IOSTAT_SUCCESS, "Success."},
{IOSTAT_FCP_RSP_ERROR, "FCP response error."},
{IOSTAT_REMOTE_STOP, "Remote stop."},
{IOSTAT_LOCAL_REJECT, "Local reject."},
{IOSTAT_NPORT_RJT, "NPort reject."},
{IOSTAT_FABRIC_RJT, "Fabric reject."},
{IOSTAT_NPORT_BSY, "Nport busy."},
{IOSTAT_FABRIC_BSY, "Fabric busy."},
{IOSTAT_INTERMED_RSP, "Intermediate response."},
{IOSTAT_LS_RJT, "LS reject."},
{IOSTAT_CMD_REJECT, "Cmd reject."},
{IOSTAT_FCP_TGT_LENCHK, "TGT length check."},
{IOSTAT_NEED_BUFF_ENTRY, "Need buffer entry."},
{IOSTAT_DATA_UNDERRUN, "Data underrun."},
{IOSTAT_DATA_OVERRUN, "Data overrun."},
}; /* emlxs_state_table */
#ifdef MENLO_SUPPORT
{MENLO_CMD_INITIALIZE, "MENLO_INIT"},
{MENLO_CMD_FW_DOWNLOAD, "MENLO_FW_DOWNLOAD"},
{MENLO_CMD_READ_MEMORY, "MENLO_READ_MEM"},
{MENLO_CMD_WRITE_MEMORY, "MENLO_WRITE_MEM"},
{MENLO_CMD_FTE_INSERT, "MENLO_FTE_INSERT"},
{MENLO_CMD_FTE_DELETE, "MENLO_FTE_DELETE"},
{MENLO_CMD_GET_INIT, "MENLO_GET_INIT"},
{MENLO_CMD_GET_CONFIG, "MENLO_GET_CONFIG"},
{MENLO_CMD_GET_PORT_STATS, "MENLO_GET_PORT_STATS"},
{MENLO_CMD_GET_LIF_STATS, "MENLO_GET_LIF_STATS"},
{MENLO_CMD_GET_ASIC_STATS, "MENLO_GET_ASIC_STATS"},
{MENLO_CMD_GET_LOG_CONFIG, "MENLO_GET_LOG_CFG"},
{MENLO_CMD_GET_LOG_DATA, "MENLO_GET_LOG_DATA"},
{MENLO_CMD_GET_PANIC_LOG, "MENLO_GET_PANIC_LOG"},
{MENLO_CMD_GET_LB_MODE, "MENLO_GET_LB_MODE"},
{MENLO_CMD_SET_PAUSE, "MENLO_SET_PAUSE"},
{MENLO_CMD_SET_FCOE_COS, "MENLO_SET_FCOE_COS"},
{MENLO_CMD_SET_UIF_PORT_TYPE, "MENLO_SET_UIF_TYPE"},
{MENLO_CMD_DIAGNOSTICS, "MENLO_DIAGNOSTICS"},
{MENLO_CMD_LOOPBACK, "MENLO_LOOPBACK"},
{MENLO_CMD_RESET, "MENLO_RESET"},
{MENLO_CMD_SET_MODE, "MENLO_SET_MODE"}
}; /* emlxs_menlo_cmd_table */
{MENLO_RSP_SUCCESS, "SUCCESS"},
{MENLO_ERR_FAILED, "FAILED"},
{MENLO_ERR_INVALID_CMD, "INVALID_CMD"},
{MENLO_ERR_INVALID_CREDIT, "INVALID_CREDIT"},
{MENLO_ERR_INVALID_SIZE, "INVALID_SIZE"},
{MENLO_ERR_INVALID_ADDRESS, "INVALID_ADDRESS"},
{MENLO_ERR_INVALID_CONTEXT, "INVALID_CONTEXT"},
{MENLO_ERR_INVALID_LENGTH, "INVALID_LENGTH"},
{MENLO_ERR_INVALID_TYPE, "INVALID_TYPE"},
{MENLO_ERR_INVALID_DATA, "INVALID_DATA"},
{MENLO_ERR_INVALID_VALUE1, "INVALID_VALUE1"},
{MENLO_ERR_INVALID_VALUE2, "INVALID_VALUE2"},
{MENLO_ERR_INVALID_MASK, "INVALID_MASK"},
{MENLO_ERR_CHECKSUM, "CHECKSUM_ERROR"},
{MENLO_ERR_UNKNOWN_FCID, "UNKNOWN_FCID"},
{MENLO_ERR_UNKNOWN_WWN, "UNKNOWN_WWN"},
{MENLO_ERR_BUSY, "BUSY"},
}; /* emlxs_menlo_rsp_table */
#endif /* MENLO_SUPPORT */
{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
{MS_GTIN, "MS_GTIN"},
{MS_GIEL, "MS_GIEL"},
{MS_GIET, "MS_GIET"},
{MS_GDID, "MS_GDID"},
{MS_GMID, "MS_GMID"},
{MS_GFN, "MS_GFN"},
{MS_GIELN, "MS_GIELN"},
{MS_GMAL, "MS_GMAL"},
{MS_GIEIL, "MS_GIEIL"},
{MS_GPL, "MS_GPL"},
{MS_GPT, "MS_GPT"},
{MS_GPPN, "MS_GPPN"},
{MS_GAPNL, "MS_GAPNL"},
{MS_GPS, "MS_GPS"},
{MS_GPSC, "MS_GPSC"},
{MS_GATIN, "MS_GATIN"},
{MS_GSES, "MS_GSES"},
{MS_GPLNL, "MS_GPLNL"},
{MS_GPLT, "MS_GPLT"},
{MS_GPLML, "MS_GPLML"},
{MS_GPAB, "MS_GPAB"},
{MS_GNPL, "MS_GNPL"},
{MS_GPNL, "MS_GPNL"},
{MS_GPFCP, "MS_GPFCP"},
{MS_GPLI, "MS_GPLI"},
{MS_GNID, "MS_GNID"},
{MS_RIELN, "MS_RIELN"},
{MS_RPL, "MS_RPL"},
{MS_RPLN, "MS_RPLN"},
{MS_RPLT, "MS_RPLT"},
{MS_RPLM, "MS_RPLM"},
{MS_RPAB, "MS_RPAB"},
{MS_RPFCP, "MS_RPFCP"},
{MS_RPLI, "MS_RPLI"},
{MS_DPL, "MS_DPL"},
{MS_DPLN, "MS_DPLN"},
{MS_DPLM, "MS_DPLM"},
{MS_DPLML, "MS_DPLML"},
{MS_DPLI, "MS_DPLI"},
{MS_DPAB, "MS_DPAB"},
{MS_DPALL, "MS_DPALL"}
}; /* emlxs_mscmd_table */
{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
{SLI_CTNS_GA_NXT, "GA_NXT"},
{SLI_CTNS_GPN_ID, "GPN_ID"},
{SLI_CTNS_GNN_ID, "GNN_ID"},
{SLI_CTNS_GCS_ID, "GCS_ID"},
{SLI_CTNS_GFT_ID, "GFT_ID"},
{SLI_CTNS_GSPN_ID, "GSPN_ID"},
{SLI_CTNS_GPT_ID, "GPT_ID"},
{SLI_CTNS_GID_PN, "GID_PN"},
{SLI_CTNS_GID_NN, "GID_NN"},
{SLI_CTNS_GIP_NN, "GIP_NN"},
{SLI_CTNS_GIPA_NN, "GIPA_NN"},
{SLI_CTNS_GSNN_NN, "GSNN_NN"},
{SLI_CTNS_GNN_IP, "GNN_IP"},
{SLI_CTNS_GIPA_IP, "GIPA_IP"},
{SLI_CTNS_GID_FT, "GID_FT"},
{SLI_CTNS_GID_PT, "GID_PT"},
{SLI_CTNS_RPN_ID, "RPN_ID"},
{SLI_CTNS_RNN_ID, "RNN_ID"},
{SLI_CTNS_RCS_ID, "RCS_ID"},
{SLI_CTNS_RFT_ID, "RFT_ID"},
{SLI_CTNS_RSPN_ID, "RSPN_ID"},
{SLI_CTNS_RPT_ID, "RPT_ID"},
{SLI_CTNS_RIP_NN, "RIP_NN"},
{SLI_CTNS_RIPA_NN, "RIPA_NN"},
{SLI_CTNS_RSNN_NN, "RSNN_NN"},
{SLI_CTNS_DA_ID, "DA_ID"},
}; /* emlxs_ctcmd_table */
{SLI_CT_RESPONSE_FS_ACC, "CT_ACC"},
{SLI_CT_RESPONSE_FS_RJT, "CT_RJT"},
{CT_OP_GSAT, "RM_GSAT"},
{CT_OP_GHAT, "RM_GHAT"},
{CT_OP_GPAT, "RM_GPAT"},
{CT_OP_GDAT, "RM_GDAT"},
{CT_OP_GPST, "RM_GPST"},
{CT_OP_GDP, "RM_GDP"},
{CT_OP_GDPG, "RM_GDPG"},
{CT_OP_GEPS, "RM_GEPS"},
{CT_OP_GLAT, "RM_GLAT"},
{CT_OP_SSAT, "RM_SSAT"},
{CT_OP_SHAT, "RM_SHAT"},
{CT_OP_SPAT, "RM_SPAT"},
{CT_OP_SDAT, "RM_SDAT"},
{CT_OP_SDP, "RM_SDP"},
{CT_OP_SBBS, "RM_SBBS"},
{CT_OP_RPST, "RM_RPST"},
{CT_OP_VFW, "RM_VFW"},
{CT_OP_DFW, "RM_DFW"},
{CT_OP_RES, "RM_RES"},
{CT_OP_RHD, "RM_RHD"},
{CT_OP_UFW, "RM_UFW"},
{CT_OP_RDP, "RM_RDP"},
{CT_OP_GHDR, "RM_GHDR"},
{CT_OP_CHD, "RM_CHD"},
{CT_OP_SSR, "RM_SSR"},
{CT_OP_RSAT, "RM_RSAT"},
{CT_OP_WSAT, "RM_WSAT"},
{CT_OP_RSAH, "RM_RSAH"},
{CT_OP_WSAH, "RM_WSAH"},
{CT_OP_RACT, "RM_RACT"},
{CT_OP_WACT, "RM_WACT"},
{CT_OP_RKT, "RM_RKT"},
{CT_OP_WKT, "RM_WKT"},
{CT_OP_SSC, "RM_SSC"},
{CT_OP_QHBA, "RM_QHBA"},
{CT_OP_GST, "RM_GST"},
{CT_OP_GFTM, "RM_GFTM"},
{CT_OP_SRL, "RM_SRL"},
{CT_OP_SI, "RM_SI"},
{CT_OP_SRC, "RM_SRC"},
{CT_OP_GPB, "RM_GPB"},
{CT_OP_SPB, "RM_SPB"},
{CT_OP_RPB, "RM_RPB"},
{CT_OP_RAPB, "RM_RAPB"},
{CT_OP_GBC, "RM_GBC"},
{CT_OP_GBS, "RM_GBS"},
{CT_OP_SBS, "RM_SBS"},
{CT_OP_GANI, "RM_GANI"},
{CT_OP_GRV, "RM_GRV"},
{CT_OP_GAPBS, "RM_GAPBS"},
{CT_OP_APBC, "RM_APBC"},
{CT_OP_GDT, "RM_GDT"},
{CT_OP_GDLMI, "RM_GDLMI"},
{CT_OP_GANA, "RM_GANA"},
{CT_OP_GDLV, "RM_GDLV"},
{CT_OP_GWUP, "RM_GWUP"},
{CT_OP_GLM, "RM_GLM"},
{CT_OP_GABS, "RM_GABS"},
{CT_OP_SABS, "RM_SABS"},
{CT_OP_RPR, "RM_RPR"},
}; /* emlxs_rmcmd_table */
{ELS_CMD_ACC, "ACC"},
{ELS_CMD_LS_RJT, "LS_RJT"},
{ELS_CMD_PLOGI, "PLOGI"},
{ELS_CMD_FLOGI, "FLOGI"},
{ELS_CMD_LOGO, "LOGO"},
{ELS_CMD_ABTX, "ABTX"},
{ELS_CMD_RCS, "RCS"},
{ELS_CMD_RES, "RES"},
{ELS_CMD_RSS, "RSS"},
{ELS_CMD_RSI, "RSI"},
{ELS_CMD_ESTS, "ESTS"},
{ELS_CMD_ESTC, "ESTC"},
{ELS_CMD_ADVC, "ADVC"},
{ELS_CMD_RTV, "RTV"},
{ELS_CMD_RLS, "RLS"},
{ELS_CMD_ECHO, "ECHO"},
{ELS_CMD_TEST, "TEST"},
{ELS_CMD_RRQ, "RRQ"},
{ELS_CMD_PRLI, "PRLI"},
{ELS_CMD_PRLO, "PRLO"},
{ELS_CMD_SCN, "SCN"},
{ELS_CMD_TPLS, "TPLS"},
{ELS_CMD_GPRLO, "GPRLO"},
{ELS_CMD_GAID, "GAID"},
{ELS_CMD_FACT, "FACT"},
{ELS_CMD_FDACT, "FDACT"},
{ELS_CMD_NACT, "NACT"},
{ELS_CMD_NDACT, "NDACT"},
{ELS_CMD_QoSR, "QoSR"},
{ELS_CMD_RVCS, "RVCS"},
{ELS_CMD_PDISC, "PDISC"},
{ELS_CMD_FDISC, "FDISC"},
{ELS_CMD_ADISC, "ADISC"},
{ELS_CMD_FARP, "FARP"},
{ELS_CMD_FARPR, "FARPR"},
{ELS_CMD_FAN, "FAN"},
{ELS_CMD_RSCN, "RSCN"},
{ELS_CMD_SCR, "SCR"},
{ELS_CMD_LINIT, "LINIT"},
{ELS_CMD_RNID, "RNID"},
{ELS_CMD_AUTH, "AUTH"}
}; /* emlxs_elscmd_table */
/*
*
* Device Driver Entry Routines
*
*/
#ifdef MODSYM_SUPPORT
static void emlxs_fca_modclose();
static int emlxs_fca_modopen();
static int
{
int err;
if (emlxs_modsym.mod_fctl) {
return (0);
}
/* Leadville (fctl) */
err = 0;
if (!emlxs_modsym.mod_fctl) {
DRIVER_NAME, err);
goto failed;
}
err = 0;
/* Check if the fctl fc_fca_attach is present */
&err);
"?%s: misc/fctl: fc_fca_attach not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fctl fc_fca_detach is present */
&err);
"?%s: misc/fctl: fc_fca_detach not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fctl fc_fca_init is present */
"?%s: misc/fctl: fc_fca_init not present", DRIVER_NAME);
goto failed;
}
return (0);
return (1);
} /* emlxs_fca_modopen() */
static void
{
if (emlxs_modsym.mod_fctl) {
emlxs_modsym.mod_fctl = 0;
}
return;
} /* emlxs_fca_modclose() */
#endif /* MODSYM_SUPPORT */
/*
* Global driver initialization, called once when driver is loaded
*/
int
_init(void)
{
int ret;
char buf[64];
/*
* First init call for this driver,
* so initialize the emlxs_dev_ctl structure.
*/
#ifdef MODSYM_SUPPORT
#endif /* MODSYM_SUPPORT */
}
/*
* Provide for one ddiinst of the emlxs_dev_ctl structure
* for each possible board in the system.
*/
sizeof (emlxs_hba_t), MAX_FC_BRDS)) != 0) {
"?%s: _init: ddi_soft_state_init failed. rval=%x",
DRIVER_NAME, ret);
return (ret);
}
#ifdef MODSYM_SUPPORT
/* Open SFS */
(void) emlxs_fca_modopen();
#endif /* MODSYM_SUPPORT */
/* Setup devops for SFS */
(void) ddi_soft_state_fini(&emlxs_soft_state);
#ifdef MODSYM_SUPPORT
/* Close SFS */
#endif /* MODSYM_SUPPORT */
return (ret);
}
#ifdef SAN_DIAG_SUPPORT
#endif /* SAN_DIAG_SUPPORT */
return (ret);
} /* _init() */
/*
* Called when driver is unloaded.
*/
int
_fini(void)
{
int ret;
return (ret);
}
#ifdef MODSYM_SUPPORT
/* Close SFS */
#endif /* MODSYM_SUPPORT */
/*
* Destroy the soft state structure
*/
(void) ddi_soft_state_fini(&emlxs_soft_state);
/* Destroy the global device lock */
#ifdef SAN_DIAG_SUPPORT
#endif /* SAN_DIAG_SUPPORT */
return (ret);
} /* _fini() */
int
{
} /* _info() */
/*
* Attach an ddiinst of an emlx host adapter.
* Allocate data structures, initialize the adapter and we're ready to fly.
*/
static int
{
int ddiinst;
int emlxinst;
int rval;
switch (cmd) {
case DDI_ATTACH:
/* If successful this will set EMLXS_PM_IN_ATTACH */
break;
case DDI_PM_RESUME:
/* This will resume the driver */
break;
case DDI_RESUME:
/* This will resume the driver */
break;
default:
rval = DDI_FAILURE;
}
if (rval == DDI_SUCCESS) {
/* Enable driver dump feature */
}
}
return (rval);
} /* emlxs_attach() */
/*
*/
static int
{
int ddiinst;
int emlxinst;
int rval;
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
rval = DDI_SUCCESS;
/* Check driver dump */
"emlxs_detach: Driver busy. Driver dump active.");
return (DDI_FAILURE);
}
#ifdef SFCT_SUPPORT
"emlxs_detach: Driver busy. Target mode active.");
return (DDI_FAILURE);
}
#endif /* SFCT_SUPPORT */
"emlxs_detach: Driver busy. Initiator mode active.");
return (DDI_FAILURE);
}
switch (cmd) {
case DDI_DETACH:
"DDI_DETACH");
if (rval != DDI_SUCCESS) {
"Unable to detach.");
}
break;
case DDI_PM_SUSPEND:
"DDI_PM_SUSPEND");
/* This will suspend the driver */
if (rval != DDI_SUCCESS) {
"Unable to lower power.");
}
break;
case DDI_SUSPEND:
"DDI_SUSPEND");
/* Suspend the driver */
if (rval != DDI_SUCCESS) {
"Unable to suspend driver.");
}
break;
default:
DRIVER_NAME, cmd);
rval = DDI_FAILURE;
}
if (rval == DDI_FAILURE) {
/* Re-Enable driver dump feature */
}
return (rval);
} /* emlxs_detach() */
/* EMLXS_PORT_LOCK must be held when calling this */
extern void
{
/* Initialize the base node */
port->node_count = 0;
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
}
}
sizeof (SERV_PARM));
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
return;
} /* emlxs_port_init() */
void
{
#define NXT_PTR_OFF PCI_BYTE
#define PCIE_DEVCTL_OFF 0x8
#define PCIE_CAP_ID 0x10
while (cap_ptr) {
if (cap_id == PCIE_CAP_ID) {
break;
}
}
/* PCI Express Capability Register Set */
/* Turn off the Correctable Error Reporting */
/* (the Device Control Register, bit 0). */
if (cap_id == PCIE_CAP_ID) {
tmp16 &= ~1;
tmp16);
}
}
/*
* emlxs_bind_port
*
* Arguments:
*
* dip: the dev_info pointer for the ddiinst
* port_info: pointer to info handed back to the transport
* bind_info: pointer to info from the transport
*
* Return values: a port handle for this port, NULL for failure
*
*/
static opaque_t
{
int ddiinst;
char *dptr;
char buffer[16];
char topology[32];
char linkspeed[32];
#if (EMLXS_MODREV >= EMLXS_MODREV5)
#endif
{
"emlxs_port_bind: Port %d not supported.",
return (NULL);
}
}
/* Get true port pointer */
"emlxs_port_bind: Port %d is in target mode.",
return (NULL);
}
"emlxs_port_bind: Port %d is not in initiator mode.",
return (NULL);
}
/* Make sure the port is not already bound to the transport */
"emlxs_port_bind: Port %d already bound. flag=%x",
return (NULL);
}
"fca_bind_port: Port %d: port_info=%p bind_info=%p",
#if (EMLXS_MODREV >= EMLXS_MODREV5)
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
256);
}
}
}
#endif /* >= EMLXS_MODREV5 */
/*
* Restricted login should apply both physical and
* virtual ports.
*/
}
/* Perform generic port initialization */
/* Perform SFS specific initialization */
/* Update the port info structure */
/* Set the topology and state */
}
#ifdef MENLO_SUPPORT
}
#endif /* MENLO_SUPPORT */
else {
/* Check for loop topology */
} else {
}
} else {
}
/* Set the link speed */
case 0:
break;
case LA_1GHZ_LINK:
break;
case LA_2GHZ_LINK:
break;
case LA_4GHZ_LINK:
break;
case LA_8GHZ_LINK:
break;
case LA_10GHZ_LINK:
break;
default:
break;
}
/* Adjusting port context for link up messages */
}
}
/* PCIE Correctable Error Reporting workaround */
}
/* Save initial state */
/*
* The transport needs a copy of the common service parameters
* for this port. The transport can get any updates through
* the getcap entry point.
*/
sizeof (SERV_PARM));
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
/* Swap the service parameters for ULP */
#endif /* EMLXS_MODREV2X */
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
/*
* We need to turn off CLASS2 support.
* Otherwise, FC transport will use CLASS2 as default class
* and never try with CLASS3.
*/
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#if (EMLXS_MODREVX >= EMLXS_MODREV3X)
}
}
#else /* EMLXS_SPARC or EMLXS_MODREV2X */
}
}
#endif /* >= EMLXS_MODREV3X */
#endif /* >= EMLXS_MODREV3 */
#if (EMLXS_MODREV <= EMLXS_MODREV2)
}
}
#endif /* <= EMLXS_MODREV2 */
/* Additional parameters */
/* Initialize the RNID parameters */
/* Initialize the port attributes */
#ifdef EMLXS_I386
#else /* EMLXS_SPARC */
#endif /* EMLXS_I386 */
#if (EMLXS_MODREV >= EMLXS_MODREV5)
/*
* Copy the serial number string (right most 16 chars) into the right
* justified local buffer
*/
#endif /* >= EMLXS_MODREV5 */
uint32_t i;
uint32_t j;
/* Copy the WWPN as a string into the local buffer */
for (i = 0; i < 16; i++) {
if (j <= 9) {
buffer[i] =
} else {
buffer[i] =
10));
}
i++;
j = (byte & 0xf);
if (j <= 9) {
buffer[i] =
} else {
buffer[i] =
10));
}
}
} else {
/* Copy the serial number string (right most 16 chars) */
/* into the right justified local buffer */
}
#endif /* == EMLXS_MODREV3 || EMLXS_MODREV4 */
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#endif /* >= EMLXS_MODREV3 */
#if (EMLXS_MODREV >= EMLXS_MODREV4)
#endif /* >= EMLXS_MODREV4 */
/* Set the hba speed limit */
}
}
}
}
}
/* Set the hba model info */
/* Log information */
#if (EMLXS_MODREV >= EMLXS_MODREV5)
#endif /* >= EMLXS_MODREV5 */
"Port info: priv_lilp_posit = %x",
"Port info: hard_addr = %x",
"Port info: rnid.status = %x",
"Port info: rnid.global_id = %16s",
"Port info: rnid.unit_type = %x",
"Port info: rnid.port_id = %x",
"Port info: rnid.num_attached = %x",
"Port info: rnid.ip_version = %x",
"Port info: rnid.udp_port = %x",
"Port info: rnid.ip_addr = %16s",
"Port info: rnid.spec_id_resv = %x",
"Port info: rnid.topo_flags = %x",
"Port info: manufacturer = %s",
"Port info: serial_num = %s",
"Port info: model_description = %s",
"Port info: hardware_version = %s",
"Port info: driver_version = %s",
"Port info: option_rom_version = %s",
"Port info: firmware_version = %s",
"Port info: driver_name = %s",
"Port info: vendor_specific_id = %x",
"Port info: supported_cos = %x",
"Port info: supported_speed = %x",
"Port info: max_frame_size = %x",
#if (EMLXS_MODREV >= EMLXS_MODREV3)
"Port info: fru_port_index = %x",
"Port info: fru_high = %llx",
"Port info: fru_low = %llx",
#endif /* >= EMLXS_MODREV3 */
#if (EMLXS_MODREV >= EMLXS_MODREV4)
"Port info: sym_node_name = %s",
"Port info: sym_port_name = %s",
#endif /* >= EMLXS_MODREV4 */
/* Set the bound flag */
hba->num_of_ports++;
} /* emlxs_bind_port() */
static void
{
"fca_unbind_port: port=%p", port);
/* Destroy & flush all port nodes, if they exist */
if (port->node_count) {
(void) emlxs_sli4_unreg_all_rpi_by_port(port);
} else {
}
}
#if (EMLXS_MODREV >= EMLXS_MODREV5)
(void) emlxs_mb_unreg_vpi(port);
}
#endif
return;
}
hba->num_of_ports--;
port->ulp_handle = 0;
return;
} /* emlxs_unbind_port() */
/*ARGSUSED*/
extern int
{
if (!sbp) {
return (FC_FAILURE);
}
return (FC_SUCCESS);
} /* emlxs_pkt_init() */
static void
{
/* Reinitialize */
sbp->abort_attempts = 0;
sbp->flush_count = 0;
}
ddi_in_panic()) {
}
/* Prepare the fc packet */
pkt->pkt_reason = 0;
pkt->pkt_action = 0;
pkt->pkt_data_resid = 0;
pkt->pkt_resp_resid = 0;
/* Make sure all pkt's have a proper timeout */
/* This disables all IOCB on chip timeouts */
}
/* Clear the response buffer */
if (pkt->pkt_rsplen) {
/* Check for FCP commands */
iptr[2] = 0;
iptr[3] = 0;
} else {
}
}
return;
} /* emlxs_initialize_pkt() */
/*
* We may not need this routine
*/
/*ARGSUSED*/
extern int
{
if (!sbp) {
return (FC_FAILURE);
}
return (FC_FAILURE);
}
return (FC_SUCCESS);
} /* emlxs_pkt_uninit() */
static int
{
return (FC_CAP_ERROR);
}
"fca_get_cap: FC_NODE_WWN");
rval = FC_CAP_FOUND;
"fca_get_cap: FC_LOGIN_PARAMS");
/*
* We need to turn off CLASS2 support.
* Otherwise, FC transport will use CLASS2 as default class
* and never try with CLASS3.
*/
rval = FC_CAP_FOUND;
"fca_get_cap: FC_CAP_UNSOL_BUF (%d)",
/* We multiply by MAX_VPORTS because ULP uses a */
/* formula to calculate ub bufs from this */
rval = FC_CAP_FOUND;
"fca_get_cap: FC_CAP_PAYLOAD_SIZE");
*size = -1;
rval = FC_CAP_FOUND;
"fca_get_cap: FC_CAP_POST_RESET_BEHAVIOR");
rval = FC_CAP_FOUND;
"fca_get_cap: FC_CAP_NOSTREAM_ON_UNALIGN_BUF");
rval = FC_CAP_FOUND;
"fca_get_cap: FC_CAP_FCP_DMA");
*fcp_dma = FC_DVMA_SPACE;
rval = FC_CAP_FOUND;
} else {
"fca_get_cap: Unknown capability. [%s]", cap);
rval = FC_CAP_ERROR;
}
return (rval);
} /* emlxs_get_cap() */
static int
{
return (FC_CAP_ERROR);
} /* emlxs_set_cap() */
static opaque_t
{
return (NULL);
} /* emlxs_get_device() */
static int32_t
{
cmd);
return (FC_SUCCESS);
} /* emlxs_notify */
static int
{
"fca_get_map: mapbuf=%p length=%d (%X,%X,%X,%X)", mapbuf,
return (FC_NOMAP);
}
return (FC_NOMAP);
}
/* Check if alpa map is available */
} else { /* No LILP map available */
/* Set lilp_magic to MAGIC_LISA and this will */
/* trigger an ALPA scan in ULP */
}
/* The first byte of the alpa_map is the lilp map length */
/* Add one to include the lilp length byte itself */
/* Make sure the max transfer is 128 bytes */
if (lilp_length > 128) {
lilp_length = 128;
}
/* We start copying from the lilp_length field */
/* in order to get a word aligned address */
return (FC_SUCCESS);
} /* emlxs_get_map() */
extern int
{
/* Make sure adapter is online */
"Adapter offline.");
return (FC_OFFLINE);
}
/* Validate packet */
/* Make sure ULP was told that the port was online */
"Port offline.");
return (FC_OFFLINE);
}
"Invalid port handle. sbp=%p port=%p flags=%x", sbp,
return (FC_BADPACKET);
}
"Invalid packet flags. sbp=%p port=%p flags=%x", sbp,
return (FC_BADPACKET);
}
#ifdef SFCT_SUPPORT
"Packet blocked. Target mode.");
return (FC_TRANSPORT_ERROR);
}
#endif /* SFCT_SUPPORT */
#ifdef IDLE_TIMER
#endif /* IDLE_TIMER */
/* Prepare the packet for transport */
/* Save a copy of the pkt flags. */
/* We will check the polling flag later */
/* Send the packet */
switch (pkt->pkt_tran_type) {
case FC_PKT_FCP_READ:
case FC_PKT_FCP_WRITE:
break;
case FC_PKT_IP_WRITE:
case FC_PKT_BROADCAST:
break;
case FC_PKT_EXCHANGE:
case FC_TYPE_SCSI_FCP:
break;
case FC_TYPE_FC_SERVICES:
break;
#ifdef MENLO_SUPPORT
case EMLXS_MENLO_TYPE:
break;
#endif /* MENLO_SUPPORT */
default:
}
break;
case FC_PKT_OUTBOUND:
#ifdef SFCT_SUPPORT
case FC_TYPE_SCSI_FCP:
break;
case FC_TYPE_BASIC_LS:
break;
#endif /* SFCT_SUPPORT */
case FC_TYPE_FC_SERVICES:
break;
#ifdef MENLO_SUPPORT
case EMLXS_MENLO_TYPE:
break;
#endif /* MENLO_SUPPORT */
default:
}
break;
default:
break;
}
/* Check if send was not successful */
if (rval != FC_SUCCESS) {
/* Return packet to ULP */
return (rval);
}
/* Check if this packet should be polled for completion before */
/* returning. This check must be done with a saved copy of the */
/* pkt_flags because the packet itself could already be freed from */
/* memory if it was not polled. */
if (pkt_flags & PACKET_POLLED) {
}
return (FC_SUCCESS);
} /* emlxs_transport() */
static void
{
hba->io_poll_count++;
/* Check for panic situation */
if (ddi_in_panic()) {
/*
* In panic situations there will be one thread with
* no interrrupts (hard or soft) and no timers
*/
/*
* We must manually poll everything in this thread
* to keep the driver going.
*/
case FC_FCP_RING:
break;
case FC_IP_RING:
break;
case FC_ELS_RING:
break;
case FC_CT_RING:
break;
}
}
/* Keep polling the chip until our IO is completed */
/* Driver's timer will not function during panics. */
/* Therefore, timer checks must be performed manually. */
} else {
EMLXS_SLI_POLL_INTR(hba, 0);
}
/* Trigger timer checks periodically */
}
}
} else {
/* Wait for IO completion */
/* The driver's timer will detect */
/* any timeout and abort the I/O. */
}
}
/* Check for fcp reset pkt */
/* Flush the IO's on the chipq */
(void) emlxs_chipq_node_flush(port,
} else {
/* Flush the IO's on the chipq for this lun */
(void) emlxs_chipq_lun_flush(port,
}
if (sbp->flush_count == 0) {
goto done;
}
/* Set the timeout so the flush has time to complete */
}
if (sbp->flush_count == 0) {
goto done;
}
"sbp=%p flush_count=%d. Waiting...", sbp,
sbp->flush_count);
/* Let's try this one more time */
/* Flush the IO's on the chipq */
(void) emlxs_chipq_node_flush(port,
} else {
/* Flush the IO's on the chipq for this lun */
(void) emlxs_chipq_lun_flush(port,
}
/* Reset the timeout so the flush has time to complete */
}
if (sbp->flush_count == 0) {
goto done;
}
"sbp=%p flush_count=%d. Resetting link.", sbp,
sbp->flush_count);
/* Let's first try to reset the link */
if (sbp->flush_count == 0) {
goto done;
}
"sbp=%p flush_count=%d. Resetting HBA.", sbp,
sbp->flush_count);
/* If that doesn't work, reset the adapter */
if (sbp->flush_count != 0) {
"sbp=%p flush_count=%d. Giving up.", sbp,
sbp->flush_count);
}
}
/* PACKET_FCP_RESET */
done:
/* Packet has been declared completed and is now ready to be returned */
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
hba->io_poll_count--;
/* Make ULP completion callback if required */
cp->ulpCmplCmd++;
}
return;
} /* emlxs_poll() */
static int
{
int32_t i;
int result;
int rc;
}
return (FC_SUCCESS);
}
"ub_alloc failed: Port not bound! size=%x count=%d "
return (FC_FAILURE);
}
"ub_alloc failed: Too many unsolicted buffers requested. "
"count=%x", *count);
return (FC_FAILURE);
}
"ub_alloc failed: Token array is NULL.");
return (FC_FAILURE);
}
/* Clear the token array */
free_resv = 0;
switch (type) {
case FC_TYPE_BASIC_LS:
err = "BASIC_LS";
break;
case FC_TYPE_EXTENDED_LS:
err = "EXTENDED_LS";
break;
case FC_TYPE_IS8802:
err = "IS8802";
break;
case FC_TYPE_IS8802_SNAP:
err = "IS8802_SNAP";
"ub_alloc failed: IP support is disabled.");
return (FC_FAILURE);
}
break;
case FC_TYPE_SCSI_FCP:
err = "SCSI_FCP";
break;
case FC_TYPE_SCSI_GPP:
err = "SCSI_GPP";
break;
case FC_TYPE_HIPP_FP:
err = "HIPP_FP";
break;
case FC_TYPE_IPI3_MASTER:
err = "IPI3_MASTER";
break;
case FC_TYPE_IPI3_SLAVE:
err = "IPI3_SLAVE";
break;
case FC_TYPE_IPI3_PEER:
err = "IPI3_PEER";
break;
case FC_TYPE_FC_SERVICES:
err = "FC_SERVICES";
break;
}
/*
* Walk through the list of the unsolicited buffers
* for this ddiinst of emlx.
*/
/*
* The emlxs_ub_alloc() can be called more than once with different
* size. We will reject the call if there are
* duplicate size with the same FC-4 type.
*/
while (pool) {
"ub_alloc failed: Unsolicited buffer pool for %s "
result = FC_FAILURE;
goto fail;
}
}
KM_SLEEP);
for (i = 0; i < new_pool->pool_nentries; i++) {
KM_SLEEP);
/*
* Initialize emlxs_ub_priv_t
*/
/* Allocate the actual buffer */
"ub_alloc: buffer=%p token=%x size=%x type=%x ", ubp,
}
/* Add the pool to the top of the pool list */
}
/* Set the post counts */
if (type == FC_TYPE_IS8802_SNAP) {
MEM_MBOX, 1))) {
mbox, MBX_NOWAIT, 0);
}
}
} else if (type == FC_TYPE_EXTENDED_LS) {
} else if (type == FC_TYPE_FC_SERVICES) {
}
"%d unsolicited buffers allocated for %s of size 0x%x bytes.",
return (FC_SUCCESS);
fail:
/* Clean the pool */
/* Get the buffer object */
"ub_alloc failed: Freed buffer=%p token=%x size=%x "
/* Free the actual buffer */
/* Free the private area of the buffer object */
tokens[i] = 0;
}
/* Free the array of buffer objects in the pool */
/* Free the pool object */
return (result);
} /* emlxs_ub_alloc() */
static void
{
return;
}
sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) {
return;
}
"%s dropped: sid=%x. Rejecting.",
}
/* Build the fc header */
/* Build the command */
/* Send the pkt later in another thread */
(void) emlxs_pkt_send(pkt, 0);
return;
} /* emlxs_ub_els_reject() */
extern int
{
uint32_t i;
if (count == 0) {
"ub_release: Nothing to do. count=%d", count);
return (FC_SUCCESS);
}
"ub_release failed: Port not bound. count=%d token[0]=%p",
return (FC_UNBOUND);
}
"ub_release failed: No pools! count=%d token[0]=%p",
return (FC_UB_BADTOKEN);
}
for (i = 0; i < count; i++) {
if (!ubp) {
"ub_release failed: count=%d tokens[%d]=0", count,
i);
return (FC_UB_BADTOKEN);
}
"ub_release failed: Dead buffer found. ubp=%p",
ubp);
return (FC_UB_BADTOKEN);
}
"ub_release: Buffer already free! ubp=%p token=%x",
continue;
}
/* Check for dropped els buffer */
/* ULP will do this sometimes without sending a reply */
}
/* Mark the buffer free */
pool->pool_free_resv++;
} else {
}
"ub_release: ubp=%p token=%x time=%d av=%d (%d,%d,%d,%d)",
/* Check if pool can be destroyed now */
if ((pool->pool_available == 0) &&
pool->pool_nentries)) {
}
}
return (FC_SUCCESS);
} /* emlxs_ub_release() */
static int
{
uint32_t i;
return (FC_SUCCESS);
}
if (count == 0) {
"ub_free: Nothing to do. count=%d token[0]=%p", count,
tokens[0]);
return (FC_SUCCESS);
}
"ub_free: Port not bound. count=%d token[0]=%p", count,
tokens[0]);
return (FC_SUCCESS);
}
"ub_free failed: No pools! count=%d token[0]=%p", count,
tokens[0]);
return (FC_UB_BADTOKEN);
}
/* Process buffer list */
for (i = 0; i < count; i++) {
if (!ubp) {
"ub_free failed: count=%d tokens[%d]=0", count,
i);
return (FC_UB_BADTOKEN);
}
/* Mark buffer unavailable */
"ub_free failed: Dead buffer found. ubp=%p", ubp);
return (FC_UB_BADTOKEN);
}
/* Mark one less buffer available in the parent pool */
"ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp,
if (pool->pool_available) {
pool->pool_available--;
/* Check if pool can be destroyed */
if ((pool->pool_available == 0) &&
pool->pool_nentries)) {
}
}
}
return (FC_SUCCESS);
} /* emlxs_ub_free() */
/* EMLXS_UB_LOCK must be held when calling this routine */
extern void
{
uint32_t i;
/* Remove the pool object from the pool list */
}
if (prev) {
}
if (next) {
}
/* Clear the post counts */
case FC_TYPE_IS8802_SNAP:
break;
case FC_TYPE_EXTENDED_LS:
break;
case FC_TYPE_FC_SERVICES:
break;
}
/* Now free the pool memory */
"ub_destroy: pool=%p type=%d size=%d count=%d", pool,
/* Process the array of buffer objects in the pool */
for (i = 0; i < pool->pool_nentries; i++) {
/* Get the buffer object */
/* Free the memory the buffer object represents */
/* Free the private area of the buffer object */
}
/* Free the array of buffer objects in the pool */
/* Free the pool object */
return;
} /* emlxs_ub_destroy() */
/*ARGSUSED*/
extern int
{
"Port not bound.");
return (FC_UNBOUND);
}
"Adapter offline.");
return (FC_OFFLINE);
}
/* ULP requires the aborted pkt to be completed */
/* back to ULP before returning from this call. */
/* SUN knows of problems with this call so they suggested that we */
/* always return a FC_FAILURE for this call, until it is worked out. */
/* Check if pkt is no good */
return (FC_FAILURE);
}
/* Tag this now */
/* This will prevent any thread except ours from completing it */
/* Check again if we still own this */
return (FC_FAILURE);
}
/* Check if pkt is a real polled command */
"Attempting to abort a polled I/O. sbp=%p flags=%x", sbp,
return (FC_FAILURE);
}
/* Do nothing, pkt already on its way out */
goto done;
}
pass++;
/* Find it on the queue */
found = 0;
/* Search the priority queue */
while (next) {
/* Remove it */
if (prev) {
}
(void *)iocbq) {
(void *)prev;
}
(void *)iocbq) {
q_first =
}
found = 1;
break;
}
}
} else {
/* Search the normal queue */
while (next) {
/* Remove it */
if (prev) {
}
(void *)iocbq) {
(void *)prev;
}
(void *)iocbq) {
}
found = 1;
break;
}
}
}
if (!found) {
"I/O not found in driver. sbp=%p flags=%x", sbp,
goto done;
}
/* Check if node still needs servicing */
/*
* If this is the base node,
* then don't shift the pointers
*/
/* We want to drain the base node before moving on */
/* Just shift channel queue */
/* pointers to next node */
}
} else {
/* Remove node from channel queue */
/* If this is the only node on list */
} else {
/*
* This is a little more difficult find the
* previous node in the circular channel queue
*/
}
}
}
/* Clear node */
}
/* Free the ULPIOTAG and the bmp */
} else {
}
goto done;
}
/* Check the chip queue */
/* Create the abort IOCB */
iocbq =
sbp->abort_attempts++;
} else {
iocbq =
sbp->abort_attempts++;
}
/* Send this iocbq */
if (iocbq) {
}
goto done;
}
/* Pkt was not on any queues */
/* Check again if we still own this */
PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
goto done;
}
if (!sleep) {
return (FC_FAILURE);
}
/* Apparently the pkt was not found. Let's delay and try again */
if (pass < 5) {
/* Check again if we still own this */
PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
goto done;
}
goto begin;
}
/* Force the completion now */
/* Now complete it */
1);
done:
/* Now wait for the pkt to complete */
/* Set thread timeout */
/* Check for panic situation */
if (ddi_in_panic()) {
/*
* In panic situations there will be one thread with no
* interrrupts (hard or soft) and no timers
*/
/*
* We must manually poll everything in this thread
* to keep the driver going.
*/
case FC_FCP_RING:
break;
case FC_IP_RING:
break;
case FC_ELS_RING:
break;
case FC_CT_RING:
break;
}
/* Keep polling the chip until our IO is completed */
}
} else {
/* Wait for IO completion or timeout */
pkt_ret = 0;
while ((pkt_ret != -1) &&
pkt_ret =
}
}
/* Check if timeout occured. This is not good. */
/* Something happened to our IO. */
/* Force the completion now */
goto force_it;
}
}
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
/* Check again if we still own this */
}
}
#ifdef ULP_PATCH5
return (FC_FAILURE);
}
#endif /* ULP_PATCH5 */
return (FC_SUCCESS);
} /* emlxs_pkt_abort() */
static void
{
uint32_t i;
txcnt = 0;
chipcnt = 0;
continue;
}
if (rc == FC_SUCCESS) {
if (flg) {
chipcnt++;
} else {
txcnt++;
}
}
}
} /* emlxs_abort_all() */
extern int32_t
{
int rval;
int ret;
"fca_reset failed. Port not bound.");
return (FC_UNBOUND);
}
switch (cmd) {
case FC_FCA_LINK_RESET:
return (FC_SUCCESS);
}
"fca_reset: Resetting Link.");
return (FC_FAILURE);
}
ret = 0;
ret =
timeout);
}
if (ret == -1) {
return (FC_FAILURE);
}
return (FC_SUCCESS);
case FC_FCA_CORE:
#ifdef DUMP_SUPPORT
"fca_reset: Core dump.");
/* Schedule a USER dump */
/* Wait for dump to complete */
return (FC_SUCCESS);
#endif /* DUMP_SUPPORT */
case FC_FCA_RESET:
case FC_FCA_RESET_CORE:
"fca_reset: Resetting Adapter.");
rval = FC_SUCCESS;
if (emlxs_offline(hba) == 0) {
(void) emlxs_online(hba);
} else {
"fca_reset: Adapter reset failed. Device busy.");
}
return (rval);
default:
"fca_reset: Unknown command. cmd=%x", cmd);
break;
}
return (FC_FAILURE);
} /* emlxs_reset() */
extern int
{
ret = FC_SUCCESS;
return (FC_UNBOUND);
}
#ifdef IDLE_TIMER
#endif /* IDLE_TIMER */
switch (pm->pm_cmd_code) {
case FC_PORT_GET_FW_REV:
{
char buffer[128];
"fca_port_manage: FC_PORT_GET_FW_REV");
vpd->fw_version);
break;
}
break;
}
case FC_PORT_GET_FCODE_REV:
{
char buffer[128];
"fca_port_manage: FC_PORT_GET_FCODE_REV");
/* Force update here just to be sure */
vpd->fcode_version);
break;
}
break;
}
case FC_PORT_GET_DUMP_SIZE:
{
#ifdef DUMP_SUPPORT
"fca_port_manage: FC_PORT_GET_DUMP_SIZE");
break;
}
#else
"fca_port_manage: FC_PORT_GET_DUMP_SIZE unsupported.");
#endif /* DUMP_SUPPORT */
break;
}
case FC_PORT_GET_DUMP:
{
#ifdef DUMP_SUPPORT
"fca_port_manage: FC_PORT_GET_DUMP");
break;
}
#else
"fca_port_manage: FC_PORT_GET_DUMP unsupported.");
#endif /* DUMP_SUPPORT */
break;
}
case FC_PORT_FORCE_DUMP:
{
#ifdef DUMP_SUPPORT
"fca_port_manage: FC_PORT_FORCE_DUMP");
/* Schedule a USER dump */
/* Wait for dump to complete */
#else
"fca_port_manage: FC_PORT_FORCE_DUMP unsupported.");
#endif /* DUMP_SUPPORT */
break;
}
case FC_PORT_LINK_STATE:
{
"fca_port_manage: FC_PORT_LINK_STATE");
break;
}
/*
* Can't look beyond the FCA port.
*/
break;
}
/* Set the state */
/* Check for loop topology */
} else {
}
/* Set the link speed */
case LA_2GHZ_LINK:
break;
case LA_4GHZ_LINK:
break;
case LA_8GHZ_LINK:
break;
case LA_10GHZ_LINK:
break;
case LA_1GHZ_LINK:
default:
break;
}
} else {
}
break;
}
case FC_PORT_ERR_STATS:
case FC_PORT_RLS:
{
return (FC_OFFLINE);
}
"fca_port_manage: FC_PORT_RLS / FC_PORT_ERR_STATS");
break;
}
MEM_MBOX, 1)) == 0) {
break;
}
!= MBX_SUCCESS) {
} else {
}
break;
}
case FC_PORT_DOWNLOAD_FW:
return (FC_OFFLINE);
}
"fca_port_manage: FC_PORT_DOWNLOAD_FW");
break;
case FC_PORT_DOWNLOAD_FCODE:
return (FC_OFFLINE);
}
"fca_port_manage: FC_PORT_DOWNLOAD_FCODE");
break;
case FC_PORT_DIAG:
{
switch (pm->pm_cmd_flags) {
case EMLXS_DIAG_BIU:
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_DIAG_BIU");
if (pm->pm_data_len) {
}
}
break;
case EMLXS_DIAG_POST:
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_DIAG_POST");
}
break;
case EMLXS_DIAG_ECHO:
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_DIAG_ECHO");
break;
}
if (pm->pm_data_len) {
}
}
break;
case EMLXS_PARM_GET_NUM:
{
uint32_t i;
"fca_port_manage: EMLXS_PARM_GET_NUM");
break;
}
count = 0;
for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
count++;
}
}
break;
}
case EMLXS_PARM_GET_LIST:
{
uint32_t i;
"fca_port_manage: EMLXS_PARM_GET_LIST");
break;
}
for (i = 0; i < NUM_CFG_PARAM && max_count; i++,
cfg++) {
parm++;
max_count--;
}
}
break;
}
case EMLXS_PARM_GET:
{
uint32_t i;
"fca_port_manage: EMLXS_PARM_GET. "
"inbuf too small.");
break;
}
"fca_port_manage: EMLXS_PARM_GET. "
"outbuf too small");
break;
}
ret = FC_BADOBJECT;
"fca_port_manage: EMLXS_PARM_GET: %s",
for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
ret = FC_SUCCESS;
break;
}
}
break;
}
case EMLXS_PARM_SET:
{
uint32_t i;
"fca_port_manage: EMLXS_PARM_GET. "
"inbuf too small.");
break;
}
"fca_port_manage: EMLXS_PARM_GET. "
"outbuf too small");
break;
}
ret = FC_BADOBJECT;
"fca_port_manage: EMLXS_PARM_SET: %s=0x%x,%d",
for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) {
/* Find matching parameter string */
/* Attempt to update parameter */
if (emlxs_set_parm(hba, i,
ret = FC_SUCCESS;
}
break;
}
}
break;
}
case EMLXS_LOG_GET:
{
/* Check command size */
break;
}
/* Get the request */
/* Calculate the response length from the request */
len = sizeof (emlxs_log_resp_t) +
/* Check the response buffer length */
break;
}
/* Get the response pointer */
/* Get the request log enties */
ret = FC_SUCCESS;
break;
}
case EMLXS_GET_BOOT_REV:
{
"fca_port_manage: EMLXS_GET_BOOT_REV");
break;
}
break;
}
case EMLXS_DOWNLOAD_BOOT:
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_DOWNLOAD_BOOT");
break;
case EMLXS_DOWNLOAD_CFL:
{
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_DOWNLOAD_CFL");
/* Extract the region number from the first word. */
/* Adjust the image length for the header word */
ret =
length);
break;
}
case EMLXS_VPD_GET:
{
"fca_port_manage: EMLXS_VPD_GET");
break;
}
sizeof (vpd_out->eng_change));
sizeof (vpd_out->manufacturer));
sizeof (vpd_out->serial_num));
sizeof (vpd_out->model_desc));
sizeof (vpd_out->prog_types));
ret = FC_SUCCESS;
break;
}
case EMLXS_GET_FCIO_REV:
{
"fca_port_manage: EMLXS_GET_FCIO_REV");
break;
}
break;
}
case EMLXS_GET_DFC_REV:
{
"fca_port_manage: EMLXS_GET_DFC_REV");
break;
}
break;
}
case EMLXS_SET_BOOT_STATE:
case EMLXS_SET_BOOT_STATE_old:
{
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_SET_BOOT_STATE");
break;
}
if (state == 0) {
"fca_port_manage: EMLXS_SET_BOOT_STATE: "
"Disable");
} else {
"fca_port_manage: EMLXS_SET_BOOT_STATE: "
"Enable");
}
break;
}
case EMLXS_GET_BOOT_STATE:
case EMLXS_GET_BOOT_STATE_old:
{
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_GET_BOOT_STATE");
break;
}
if (ret == FC_SUCCESS) {
ret = FC_SUCCESS;
} else if (ret == FC_FAILURE) {
ret = FC_SUCCESS;
}
break;
}
case EMLXS_HW_ERROR_TEST:
{
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_HW_ERROR_TEST");
/* Trigger a mailbox timeout */
break;
}
case EMLXS_TEST_CODE:
{
return (FC_OFFLINE);
}
"fca_port_manage: EMLXS_TEST_CODE");
"fca_port_manage: EMLXS_TEST_CODE. "
"inbuf to small.");
break;
}
break;
}
case EMLXS_BAR_IO:
{
uint32_t i;
"fca_port_manage: EMLXS_BAR_IO %x %x %x",
ret = FC_SUCCESS;
switch (cmd[0]) {
case 2: /* bar1read */
return (FC_BADCMD);
}
/* Registers in this range are invalid */
return (FC_BADCMD);
}
return (FC_BADCMD);
}
for (i = 0; i < pm->pm_stat_len;
i += sizeof (uint32_t)) {
if ((offset >= 0x4C00) &&
(offset < 0x5000)) {
pm->pm_stat_len = i;
break;
}
if (offset >= 0x5800) {
pm->pm_stat_len = i;
break;
}
datap++;
}
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
case 3: /* bar2read */
return (FC_BADCMD);
}
return (FC_BADCMD);
}
for (i = 0; i < pm->pm_stat_len;
i += sizeof (uint32_t)) {
datap++;
}
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
case 4: /* bar1write */
return (FC_BADCMD);
}
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
case 5: /* bar2write */
return (FC_BADCMD);
}
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
case 6: /* dumpbsmbox */
return (FC_BADCMD);
}
if (offset != 0) {
return (FC_BADCMD);
}
break;
case 7: /* pciread */
return (FC_BADCMD);
}
for (i = 0; i < pm->pm_stat_len;
i += sizeof (uint32_t)) {
offset));
datap++;
}
#ifdef FMA_SUPPORT
/* Access handle validation */
#endif /* FMA_SUPPORT */
break;
case 8: /* abortall */
return (FC_BADCMD);
}
break;
default:
break;
}
break;
}
default:
break;
}
break;
}
case FC_PORT_INITIALIZE:
return (FC_OFFLINE);
}
"fca_port_manage: FC_PORT_INITIALIZE");
break;
case FC_PORT_LOOPBACK:
return (FC_OFFLINE);
}
"fca_port_manage: FC_PORT_LOOPBACK");
break;
case FC_PORT_BYPASS:
return (FC_OFFLINE);
}
"fca_port_manage: FC_PORT_BYPASS");
break;
case FC_PORT_UNBYPASS:
return (FC_OFFLINE);
}
"fca_port_manage: FC_PORT_UNBYPASS");
break;
case FC_PORT_GET_NODE_ID:
{
"fca_port_manage: FC_PORT_GET_NODE_ID");
break;
}
"%01x%01x%02x%02x%02x%02x%02x%02x%02x",
ret = FC_SUCCESS;
break;
}
case FC_PORT_SET_NODE_ID:
{
"fca_port_manage: FC_PORT_SET_NODE_ID");
break;
}
ret = FC_SUCCESS;
break;
}
#ifdef S11
case FC_PORT_GET_P2P_INFO:
{
"fca_port_manage: FC_PORT_GET_P2P_INFO");
break;
}
"FC_PORT_GET_P2P_INFO: fca_d_id: 0x%x, "
if (ndlp) {
sizeof (la_wwn_t));
sizeof (la_wwn_t));
ret = FC_SUCCESS;
break;
}
}
}
ret = FC_FAILURE;
break;
}
#endif
default:
break;
}
return (ret);
} /* emlxs_port_manage() */
/*ARGSUSED*/
static uint32_t
{
switch (test_code) {
#ifdef TEST_SUPPORT
case 1: /* SCSI underrun */
{
break;
}
#endif /* TEST_SUPPORT */
default:
"emlxs_test: Unsupported test code. (0x%x)", test_code);
}
return (rval);
} /* emlxs_test() */
/*
* Given the device number, return the devinfo pointer or the ddiinst number.
* Note: this routine must be successful on DDI_INFO_DEVT2INSTANCE even
* before attach.
*
* Translate "dev_t" to a pointer to the associated "dev_info_t".
*/
/*ARGSUSED*/
static int
{
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
if (hba)
else
break;
case DDI_INFO_DEVT2INSTANCE:
break;
default:
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
} /* emlxs_info() */
static int32_t
{
int rval = DDI_SUCCESS;
return (DDI_FAILURE);
}
/* If we are already at the proper level then return success */
return (DDI_SUCCESS);
}
switch (level) {
case EMLXS_PM_ADAPTER_UP:
/*
* If we are already in emlxs_attach,
* let emlxs_hba_attach take care of things
*/
break;
}
/* Check if adapter is suspended */
/* Try to resume the port */
if (rval != DDI_SUCCESS) {
}
break;
}
/* Set adapter up */
break;
case EMLXS_PM_ADAPTER_DOWN:
/*
* If we are already in emlxs_detach,
* let emlxs_hba_detach take care of things
*/
break;
}
/* Check if adapter is not suspended */
/* Try to suspend the port */
if (rval != DDI_SUCCESS) {
}
break;
}
/* Set adapter down */
break;
default:
rval = DDI_FAILURE;
break;
}
return (rval);
} /* emlxs_power() */
#ifdef EMLXS_I386
#ifdef S11
/*
* quiesce(9E) entry point.
*
* This function is called when the system is single-thread at hight PIL
* with preemption disabled. Therefore, this function must not be blocked.
*
* This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
* DDI_FAILURE indicates an error condition and should almost never happen.
*/
static int
{
int rval = DDI_SUCCESS;
return (DDI_FAILURE);
}
/* The fourth arg 1 indicates the call is from quiesce */
return (rval);
} else {
return (DDI_FAILURE);
}
} /* emlxs_quiesce */
#endif
#endif /* EMLXS_I386 */
static int
{
int ddiinst;
return (ENXIO);
}
"open failed: Driver suspended.");
return (ENXIO);
}
return (EINVAL);
}
return (EPERM);
}
return (EBUSY);
}
return (EBUSY);
}
}
return (0);
} /* emlxs_open() */
/*ARGSUSED*/
static int
{
int ddiinst;
return (ENXIO);
}
return (EINVAL);
}
return (ENODEV);
}
return (0);
} /* emlxs_close() */
/*ARGSUSED*/
static int
{
int rval = 0; /* return code */
int ddiinst;
return (ENXIO);
}
"ioctl failed: Driver suspended.");
return (ENXIO);
}
return (ENXIO);
}
#ifdef IDLE_TIMER
#endif /* IDLE_TIMER */
switch (cmd) {
case EMLXS_DFC_COMMAND:
break;
default:
"ioctl: Invalid command received. cmd=%x", cmd);
}
done:
return (rval);
} /* emlxs_ioctl() */
/*
*
* Device Driver Common Routines
*
*/
/* emlxs_pm_lock must be held for this call */
static int
{
int ddiinst;
return (DDI_SUCCESS);
}
/* Take the adapter online */
if (emlxs_power_up(hba)) {
"Unable to take adapter online.");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
} /* emlxs_hba_resume() */
/* emlxs_pm_lock must be held for this call */
static int
{
int ddiinst;
return (DDI_SUCCESS);
}
/* Take the adapter offline */
if (emlxs_power_down(hba)) {
"Unable to take adapter offline.");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
} /* emlxs_hba_suspend() */
static void
{
char buf[64];
uint32_t i;
/* Initialize the power management */
for (i = 0; i < MAX_RINGS; i++) {
ddiinst, i);
}
#ifdef DUMP_SUPPORT
#endif /* DUMP_SUPPORT */
/* Create per port locks */
for (i = 0; i < MAX_VPORTS; i++) {
if (i == 0) {
ddiinst);
ddiinst);
ddiinst);
} else {
}
}
return;
} /* emlxs_lock_init() */
static void
{
uint32_t i;
for (i = 0; i < MAX_RINGS; i++) {
}
#ifdef DUMP_SUPPORT
#endif /* DUMP_SUPPORT */
/* Destroy per port locks */
for (i = 0; i < MAX_VPORTS; i++) {
}
return;
} /* emlxs_lock_destroy() */
/* init_flag values */
#define ATTACH_SOFT_STATE 0x00000001
#define ATTACH_FCA_TRAN 0x00000002
#define ATTACH_HBA 0x00000004
#define ATTACH_LOG 0x00000008
#define ATTACH_MAP_BUS 0x00000010
#define ATTACH_INTR_INIT 0x00000020
#define ATTACH_PROP 0x00000040
#define ATTACH_LOCK 0x00000080
#define ATTACH_THREAD 0x00000100
#define ATTACH_INTR_ADD 0x00000200
#define ATTACH_ONLINE 0x00000400
#define ATTACH_NODE 0x00000800
#define ATTACH_FCT 0x00001000
#define ATTACH_FCA 0x00002000
#define ATTACH_KSTAT 0x00004000
#define ATTACH_DHCHAP 0x00008000
#define ATTACH_FM 0x00010000
#define ATTACH_MAP_SLI 0x00020000
#define ATTACH_SPAWN 0x00040000
#define ATTACH_EVENTS 0x00080000
static void
{
int ddiinst;
if (init_flag & ATTACH_HBA) {
if (init_flag & ATTACH_SPAWN) {
}
if (init_flag & ATTACH_ONLINE) {
(void) emlxs_offline(hba);
}
if (init_flag & ATTACH_INTR_ADD) {
(void) EMLXS_INTR_REMOVE(hba);
}
#ifdef SFCT_SUPPORT
if (init_flag & ATTACH_FCT) {
}
#endif /* SFCT_SUPPORT */
#ifdef DHCHAP_SUPPORT
if (init_flag & ATTACH_DHCHAP) {
}
#endif /* DHCHAP_SUPPORT */
if (init_flag & ATTACH_KSTAT) {
}
if (init_flag & ATTACH_FCA) {
}
if (init_flag & ATTACH_NODE) {
}
if (init_flag & ATTACH_THREAD) {
}
if (init_flag & ATTACH_PROP) {
}
if (init_flag & ATTACH_LOCK) {
}
if (init_flag & ATTACH_INTR_INIT) {
(void) EMLXS_INTR_UNINIT(hba);
}
if (init_flag & ATTACH_MAP_BUS) {
}
if (init_flag & ATTACH_MAP_SLI) {
}
#ifdef FMA_SUPPORT
}
#endif /* FMA_SUPPORT */
if (init_flag & ATTACH_EVENTS) {
(void) emlxs_event_queue_destroy(hba);
}
if (init_flag & ATTACH_LOG) {
(void) emlxs_msg_log_destroy(hba);
}
if (init_flag & ATTACH_FCA_TRAN) {
}
if (init_flag & ATTACH_HBA) {
#ifdef DUMP_SUPPORT
#endif /* DUMP_SUPPORT */
}
}
if (init_flag & ATTACH_SOFT_STATE) {
}
return;
} /* emlxs_driver_remove() */
/* This determines which ports will be initiator mode */
static void
{
uint32_t i;
return;
}
/* Check if SFS present */
"SFS not present. Initiator mode disabled.");
goto failed;
}
/* Check if our SFS driver interface matches the current SFS stack */
"SFS present. Initiator mode disabled.");
goto failed;
}
"SFS present. Initiator mode enabled.");
return;
for (i = 0; i < MAX_VPORTS; i++) {
}
return;
} /* emlxs_fca_init() */
/* This determines which ports will be initiator or target mode */
static void
{
uint32_t i;
#ifdef SFCT_SUPPORT
if (tgt_mode) {
if (emlxs_fct_modopen() != 0) {
tgt_mode = 0;
}
}
#endif /* SFCT_SUPPORT */
/* Initialize physical port */
if (tgt_mode) {
} else {
}
/* Initialize virtual ports */
/* Virtual ports take on the mode of the parent physical port */
for (i = 1; i < MAX_VPORTS; i++) {
#ifdef SFCT_SUPPORT
#endif /* SFCT_SUPPORT */
}
/* Check if initiator mode is requested */
} else {
"Initiator mode not enabled.");
}
#ifdef SFCT_SUPPORT
/* Check if target mode is requested */
} else {
"Target mode not enabled.");
}
#endif /* SFCT_SUPPORT */
return;
} /* emlxs_set_mode() */
static void
{
/* Update our transport structure */
#if (EMLXS_MODREV >= EMLXS_MODREV5)
sizeof (NAME_TYPE));
#endif /* >= EMLXS_MODREV5 */
return;
} /* emlxs_fca_attach() */
static void
{
uint32_t i;
}
for (i = 0; i < MAX_VPORTS; i++) {
}
}
return;
} /* emlxs_fca_detach() */
static void
{
uint32_t i;
char sli_mode[16];
char msi_mode[16];
char npiv_mode[16];
/* Display firmware library one time */
if (emlxs_instance_count == 1) {
}
#ifdef EMLXS_I386
vpd->boot_version);
#else /* EMLXS_SPARC */
#endif /* EMLXS_I386 */
} else {
}
#ifdef MSI_SUPPORT
case DDI_INTR_TYPE_FIXED:
break;
case DDI_INTR_TYPE_MSI:
break;
case DDI_INTR_TYPE_MSIX:
break;
}
}
#endif
} else {
}
"WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
"WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
for (i = 0; i < MAX_VPORTS; i++) {
continue;
}
"WWPN:%02X%02X%02X%02X%02X%02X%02X%02X "
"WWNN:%02X%02X%02X%02X%02X%02X%02X%02X",
}
/*
* No dependency for Restricted login parameter.
*/
} else {
}
/*
* Announce the device: ddi_report_dev() prints a banner at boot time,
* announcing the device pointed to by dip.
*/
return;
} /* emlxs_drv_banner() */
extern void
{
char *prop_str;
int status;
/* Setup fcode version property */
status =
"fcode-version", (char **)&prop_str);
if (status == DDI_PROP_SUCCESS) {
(void) ddi_prop_free((void *)prop_str);
} else {
}
return;
} /* emlxs_get_fcode_version() */
static int
{
char *prop_str;
int ddiinst;
int status;
char local_pm_components[32];
#ifdef EMLXS_I386
uint32_t i;
#endif /* EMLXS_I386 */
if (emlxinst >= MAX_FC_BRDS) {
"?%s: fca_hba_attach failed. Too many driver ddiinsts. "
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/* An adapter can accidentally be plugged into a slave-only PCI slot */
"?%s%d: fca_hba_attach failed. Device in slave-only slot.",
return (DDI_FAILURE);
}
/* Allocate emlxs_dev_ctl structure. */
"?%s%d: fca_hba_attach failed. Unable to allocate soft "
return (DDI_FAILURE);
}
"?%s%d: fca_hba_attach failed. Unable to get soft state.",
goto failed;
}
#ifdef DUMP_SUPPORT
#endif /* DUMP_SUPPORT */
init_flag |= ATTACH_HBA;
/* Enable the physical port on this HBA */
/* Allocate a transport structure */
"?%s%d: fca_hba_attach failed. Unable to allocate fca_tran "
goto failed;
}
sizeof (fc_fca_tran_t));
/*
* Copy the global ddi_dma_attr to the local hba fields
*/
sizeof (ddi_dma_attr_t));
sizeof (ddi_dma_attr_t));
sizeof (ddi_dma_attr_t));
/* Reset the fca_tran dma_attr fields to the per-hba copies */
/* Set the transport structure pointer in our dip */
/* SFS may panic if we are in target only mode */
/* We will update the transport structure later */
/* Perform driver integrity check */
if (rval) {
"?%s%d: fca_hba_attach failed. Driver integrity check "
goto failed;
}
#ifdef MSI_SUPPORT
if ((void *)&ddi_intr_get_supported_types != NULL) {
}
#endif /* MSI_SUPPORT */
/* Create the msg log file */
if (emlxs_msg_log_create(hba) == 0) {
"?%s%d: fca_hba_attach failed. Unable to create message "
goto failed;
}
init_flag |= ATTACH_LOG;
/* We can begin to use EMLXS_MSGF from this point on */
/* Create the event queue */
if (emlxs_event_queue_create(hba) == 0) {
"Unable to create event queue");
goto failed;
}
/*
* Find the I/O bus type If it is not a SBUS card,
* then it is a PCI card. Default is PCI_FC (0).
*/
if (status == DDI_PROP_SUCCESS) {
}
(void) ddi_prop_free((void *)prop_str);
}
/*
* Copy DDS from the config method and update configuration parameters
*/
(void) emlxs_get_props(hba);
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
if (emlxs_map_bus(hba)) {
"Unable to map memory");
goto failed;
}
/* Attempt to identify the adapter */
if (rval == 0) {
"Unable to get adapter info. Id:%d Device id:0x%x "
goto failed;
}
/* Check if adapter is not supported */
"Unsupported adapter found. Id:%d Device id:0x%x "
goto failed;
}
#ifdef EMLXS_I386
/*
* TigerShark has 64K limit for SG element size
* Do this for x86 alone. For SPARC, the driver
* breaks up the single SGE later on.
*/
/* Update SGL size based on max_xfer_size */
if (i > 688128) {
/* 688128 = (((2048 / 12) - 2) * 4096) */
} else if (i > 339968) {
/* 339968 = (((1024 / 12) - 2) * 4096) */
} else {
}
#endif /* EMLXS_I386 */
} else {
#ifdef EMLXS_I386
/* Update BPL size based on max_xfer_size */
if (i > 688128) {
/* 688128 = (((2048 / 12) - 2) * 4096) */
} else if (i > 339968) {
/* 339968 = (((1024 / 12) - 2) * 4096) */
} else {
}
#endif /* EMLXS_I386 */
}
#ifdef EMLXS_I386
/* Update dma_attr_sgllen based on BPL size */
#endif /* EMLXS_I386 */
if (EMLXS_SLI_MAP_HDW(hba)) {
"Unable to map memory");
goto failed;
}
/* Initialize the interrupts. But don't add them yet */
if (status != DDI_SUCCESS) {
"Unable to initalize interrupt(s).");
goto failed;
}
/* Initialize LOCKs */
init_flag |= ATTACH_LOCK;
/* Initialize the power management */
#ifdef IDLE_TIMER
hba->pm_idle_timer = 0;
#endif /* IDLE_TIMER */
/* Set the pm component name */
ddiinst);
/* Check if power management support is enabled */
"pm-components", emlxs_pm_components,
sizeof (emlxs_pm_components) /
sizeof (emlxs_pm_components[0])) !=
"Unable to create pm components.");
goto failed;
}
}
/* Needed for suspend and resume support */
"needs-suspend-resume");
init_flag |= ATTACH_PROP;
/* Setup initiator / target ports */
/* If driver did not attach to either stack, */
/* then driver attach failed */
"Driver interfaces not enabled.");
goto failed;
}
/*
* Initialize HBA
*/
/* Set initial state */
"Unable to initialize adapter.");
goto failed;
}
/* This is to ensure that the model property is properly set */
/* Create the device node. */
DDI_FAILURE) {
"Unable to create device node.");
goto failed;
}
init_flag |= ATTACH_NODE;
/* Attach initiator now */
/* This must come after emlxs_online() */
init_flag |= ATTACH_FCA;
/* Initialize kstat information */
KSTAT_TYPE_RAW, sizeof (emlxs_stats_t),
"kstat_create failed.");
} else {
}
/* Setup virtual port properties */
#endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */
#ifdef DHCHAP_SUPPORT
#endif /* DHCHAP_SUPPORT */
/* Display the driver banner now */
/* Raise the power level */
/*
* This will not execute emlxs_hba_resume because
* EMLXS_PM_IN_ATTACH is set
*/
/* Set power up anyway. This should not happen! */
} else {
}
#ifdef SFCT_SUPPORT
/* Do this last */
init_flag |= ATTACH_FCT;
#endif /* SFCT_SUPPORT */
return (DDI_SUCCESS);
return (DDI_FAILURE);
} /* emlxs_hba_attach() */
static int
{
int ddiinst;
int count;
/* Lower the power level */
/*
* This will not suspend the driver since the
* EMLXS_PM_IN_DETACH has been set
*/
"Unable to lower power.");
return (DDI_FAILURE);
}
/* Take the adapter offline first, if not already */
if (emlxs_offline(hba) != 0) {
"Unable to take adapter offline.");
(void) emlxs_pm_raise_power(dip);
return (DDI_FAILURE);
}
/* Check ub buffer pools */
/* Wait up to 10 seconds for all ub pools to be freed */
count--;
}
"fca_unbind_port: Unsolicited buffers still "
"active. port=%p. Destroying...", port);
/* Destroy all pools */
}
}
}
init_flag &= ~ATTACH_ONLINE;
/* Remove the driver instance */
return (DDI_SUCCESS);
} /* emlxs_hba_detach() */
extern int
{
int status;
if (hba->pci_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"(SBUS) ddi_regs_map_setup PCI failed. "
"status=%x", status);
goto failed;
}
}
if (hba->sbus_pci_handle == 0) {
if (status != DDI_SUCCESS) {
"(SBUS) ddi_regs_map_setup TITAN PCI "
"failed. status=%x", status);
goto failed;
}
}
} else { /* ****** PCI ****** */
if (hba->pci_acc_handle == 0) {
if (status != DDI_SUCCESS) {
"(PCI) ddi_regs_map_setup PCI failed. "
"status=%x", status);
goto failed;
}
}
#ifdef EMLXS_I386
/* Setting up PCI configure space */
#ifdef FMA_SUPPORT
!= DDI_FM_OK) {
goto failed;
}
#endif /* FMA_SUPPORT */
#endif /* EMLXS_I386 */
}
return (0);
return (ENOMEM);
} /* emlxs_map_bus() */
extern void
{
if (hba->pci_acc_handle) {
hba->pci_acc_handle = 0;
}
if (hba->sbus_pci_handle) {
hba->sbus_pci_handle = 0;
}
return;
} /* emlxs_unmap_bus() */
static int
{
uint32_t i;
char string[256];
/* Initialize each parameter */
for (i = 0; i < NUM_CFG_PARAM; i++) {
/* Ensure strings are terminated */
/* Set the current value to the default value */
/* First check for the global setting */
/* Now check for the per adapter ddiinst setting */
/* Now check the parameter */
}
return (0);
} /* emlxs_get_props() */
extern uint32_t
{
uint32_t i;
if (index > NUM_CFG_PARAM) {
"emlxs_check_parm failed. Invalid index = %d", index);
return (new_value);
}
}
/* Perform additional checks */
switch (index) {
case CFG_NPIV_ENABLE:
"enable-npiv: Not supported in target mode. "
"Disabling.");
new_value = 0;
}
break;
#ifdef DHCHAP_SUPPORT
case CFG_AUTH_ENABLE:
"enable-auth: Not supported in target mode. "
"Disabling.");
new_value = 0;
}
break;
#endif /* DHCHAP_SUPPORT */
case CFG_NUM_NODES:
switch (new_value) {
case 1:
case 2:
/* Must have at least 3 if not 0 */
return (3);
default:
break;
}
break;
case CFG_LINK_SPEED:
if (vpd->link_speed) {
switch (new_value) {
case 0:
break;
case 1:
new_value = 0;
"link-speed: 1Gb not supported "
"by adapter. Switching to auto "
"detect.");
}
break;
case 2:
new_value = 0;
"link-speed: 2Gb not supported "
"by adapter. Switching to auto "
"detect.");
}
break;
case 4:
new_value = 0;
"link-speed: 4Gb not supported "
"by adapter. Switching to auto "
"detect.");
}
break;
case 8:
new_value = 0;
"link-speed: 8Gb not supported "
"by adapter. Switching to auto "
"detect.");
}
break;
case 10:
new_value = 0;
"link-speed: 10Gb not supported "
"by adapter. Switching to auto "
"detect.");
}
break;
default:
"link-speed: Invalid value=%d provided. "
"Switching to auto detect.",
new_value = 0;
}
} else { /* Perform basic validity check */
/* Perform additional check on link speed */
switch (new_value) {
case 0:
case 1:
case 2:
case 4:
case 8:
case 10:
/* link-speed is a valid choice */
break;
default:
}
}
break;
case CFG_TOPOLOGY:
/* Perform additional check on topology */
switch (new_value) {
case 0:
case 2:
case 4:
case 6:
/* topology is a valid choice */
break;
default:
}
break;
#ifdef DHCHAP_SUPPORT
case CFG_AUTH_TYPE:
{
/* Perform additional check on auth type */
shift = 12;
mask = 0xF000;
for (i = 0; i < 4; i++) {
}
shift -= 4;
mask >>= 4;
}
break;
}
case CFG_AUTH_HASH:
{
/* Perform additional check on auth hash */
shift = 12;
mask = 0xF000;
for (i = 0; i < 4; i++) {
}
shift -= 4;
mask >>= 4;
}
break;
}
case CFG_AUTH_GROUP:
{
/* Perform additional check on auth group */
shift = 28;
mask = 0xF0000000;
for (i = 0; i < 8; i++) {
}
shift -= 4;
mask >>= 4;
}
break;
}
case CFG_AUTH_INTERVAL:
if (new_value < 10) {
return (10);
}
break;
#endif /* DHCHAP_SUPPORT */
} /* switch */
return (new_value);
} /* emlxs_check_parm() */
extern uint32_t
{
if (index > NUM_CFG_PARAM) {
"emlxs_set_parm failed. Invalid index = %d", index);
return ((uint32_t)FC_FAILURE);
}
return ((uint32_t)FC_FAILURE);
}
/* Check new value */
"emlxs_set_parm: %s invalid. 0x%x --> 0x%x",
}
/* Return now if no actual change */
return (FC_SUCCESS);
}
"emlxs_set_parm: %s changing. 0x%x --> 0x%x",
/* React to change if needed */
switch (index) {
case CFG_PCI_MAX_READ:
/* Update MXR */
break;
case CFG_SLI_MODE:
/* Check SLI mode */
/* All vports must be disabled first */
/* Reset current value */
"emlxs_set_parm failed. %s: vpi=%d "
"still enabled. Value restored to "
return (2);
}
}
}
break;
case CFG_NPIV_ENABLE:
/* Check if NPIV is being disabled */
/* All vports must be disabled first */
/* Reset current value */
"emlxs_set_parm failed. %s: vpi=%d "
"still enabled. Value restored to "
return (2);
}
}
}
/* Trigger adapter reset */
/* (void) emlxs_reset(port, FC_FCA_RESET); */
break;
case CFG_VPORT_RESTRICTED:
continue;
}
continue;
}
if (new_value) {
} else {
}
}
break;
#ifdef DHCHAP_SUPPORT
case CFG_AUTH_ENABLE:
break;
case CFG_AUTH_TMO:
break;
case CFG_AUTH_MODE:
break;
case CFG_AUTH_BIDIR:
break;
case CFG_AUTH_TYPE:
break;
case CFG_AUTH_HASH:
break;
case CFG_AUTH_GROUP:
break;
case CFG_AUTH_INTERVAL:
break;
#endif /* DHCHAP_SUPPORT */
}
return (FC_SUCCESS);
} /* emlxs_set_parm() */
/*
* emlxs_mem_alloc OS specific routine for memory allocation / mapping
*
* The buf_info->flags field describes the memory operation requested.
*
* FC_MBUF_PHYSONLY set requests a supplied virtual address be mapped for DMA
* Virtual address is supplied in buf_info->virt
* DMA mapping flag is in buf_info->align
* (DMA_READ_ONLY, DMA_WRITE_ONLY, DMA_READ_WRITE)
* The mapped physical address is returned buf_info->phys
*
* FC_MBUF_PHYSONLY cleared requests memory be allocated for driver use and
* if FC_MBUF_DMA is set the memory is also mapped for DMA
* The byte alignment of the memory request is supplied in buf_info->align
* The byte size of the memory request is supplied in buf_info->size
* The virtual address is returned buf_info->virt
* The mapped physical address is returned buf_info->phys (for FC_MBUF_DMA)
*/
extern uint8_t *
{
int status;
}
}
goto done;
}
/*
* Allocate the DMA handle for this DMA object
*/
if (status != DDI_SUCCESS) {
"ddi_dma_alloc_handle failed: size=%x align=%x "
buf_info->dma_handle = 0;
goto done;
}
case DMA_READ_WRITE:
break;
case DMA_READ_ONLY:
break;
case DMA_WRITE_ONLY:
break;
}
/* Map this page of memory */
&cookie_count);
"ddi_dma_addr_bind_handle failed: status=%x "
(void) ddi_dma_free_handle(
buf_info->dma_handle = 0;
goto done;
}
ret_burst) == DDI_FAILURE) {
"ddi_dma_set_sbus64 failed.");
}
}
/* Save Physical address */
/*
* Just to be sure, let's add this
*/
/*
* Allocate the DMA handle for this DMA object
*/
if (status != DDI_SUCCESS) {
"ddi_dma_alloc_handle failed: size=%x align=%x "
buf_info->data_handle = 0;
buf_info->dma_handle = 0;
goto done;
}
"ddi_dma_mem_alloc failed: size=%x align=%x "
(void) ddi_dma_free_handle(
buf_info->data_handle = 0;
buf_info->dma_handle = 0;
goto done;
}
/* Map this page of memory */
&dma_cookie, &cookie_count);
"ddi_dma_addr_bind_handle failed: status=%x "
"count=%d size=%x align=%x flags=%x", status,
(void) ddi_dma_mem_free(
(void) ddi_dma_free_handle(
buf_info->dma_handle = 0;
buf_info->data_handle = 0;
goto done;
}
ret_burst) == DDI_FAILURE) {
"ddi_dma_set_sbus64 failed.");
}
}
/* Save Physical address */
/* Just to be sure, let's add this */
} else { /* allocate virtual memory */
buf_info->data_handle = 0;
buf_info->dma_handle = 0;
}
}
done:
} /* emlxs_mem_alloc() */
/*
* emlxs_mem_free:
*
* OS specific routine for memory de-allocation / unmapping
*
* The buf_info->flags field describes the memory operation requested.
*
* FC_MBUF_PHYSONLY set requests a supplied virtual address be unmapped
* for DMA, but not freed. The mapped physical address to be unmapped is in
* buf_info->phys
*
* FC_MBUF_PHYSONLY cleared requests memory be freed and unmapped for DMA only
* if FC_MBUF_DMA is set. The mapped physical address to be unmapped is in
* buf_info->phys. The virtual address to be freed is in buf_info->virt
*/
/*ARGSUSED*/
extern void
{
if (buf_info->dma_handle) {
(void) ddi_dma_free_handle(
}
if (buf_info->dma_handle) {
(void) ddi_dma_mem_free(
(void) ddi_dma_free_handle(
}
} else { /* allocate virtual memory */
}
}
} /* emlxs_mem_free() */
/*
* A channel has a association with a msi id.
* One msi id could be associated with multiple channels.
*/
static int
{
int chan;
int num_wq;
/* For SLI4 round robin all WQs associated with the msi_id */
}
} else {
}
return (chan);
}
static int
{
int channel;
/* IO to FCP2 device or a device reset always use fcp channel */
return (hba->channel_fcp);
}
/* If channel is closed, then try fcp channel */
}
return (channel);
}
static int32_t
{
/*
* This routine provides a alternative target reset provessing
* method. Instead of sending an actual target reset to the
* NPort, we will first unreg the login to that NPort. This
* will cause all the outstanding IOs the quickly complete with
* a NO RPI local error. Next we will force the ULP to relogin
* to the NPort by sending an RSCN (for that NPort) to the
* upper layer. This method should result in a fast target
* reset, as far as IOs completing; however, since an actual
* target reset is not sent to the NPort, it is not 100%
* compatable. Things like reservations will not be broken.
* By default this option is DISABLED, and its only enabled thru
* a hidden configuration parameter (fast-tgt-reset).
*/
rc = FC_TRAN_BUSY;
/* issue the mbox cmd to the sli */
#ifdef SLI3_SUPPORT
#endif /* SLI3_SUPPORT */
== MBX_SUCCESS) {
if (pkt->pkt_rsplen) {
pkt->pkt_rsplen);
}
}
}
rc = FC_SUCCESS;
}
return (rc);
}
static int32_t
{
char *cmd;
int channel;
/* Find target node object */
"Node not found. did=%x", did);
return (FC_BADPACKET);
}
/* When the fcp channel is closed we stop accepting any FCP cmd */
return (FC_TRAN_BUSY);
}
/* Snoop for target or lun reset first */
/* interrupt affinity only applies to non tgt lun reset fcp cmd */
/* Check for target reset */
/* prepare iocb */
if (rval == 0xff) {
0, 1);
rval = FC_SUCCESS;
}
return (rval);
}
#ifdef SAN_DIAG_SUPPORT
#endif /* SAN_DIAG_SUPPORT */
"Target Reset: did=%x", did);
FC_SUCCESS) {
return (FC_SUCCESS);
}
}
/* Close the node for any further normal IO */
pkt->pkt_timeout);
/* Flush the IO's on the tx queues */
/* This is the target reset fcp cmd */
reset = 1;
}
/* Check for lun reset */
/* prepare iocb */
if (rval == 0xff) {
0, 1);
rval = FC_SUCCESS;
}
return (rval);
}
#ifdef SAN_DIAG_SUPPORT
#endif /* SAN_DIAG_SUPPORT */
/* Flush the IO's on the tx queues for this lun */
/* This is the lun reset fcp cmd */
reset = 1;
}
#ifdef SAN_DIAG_SUPPORT
#endif /* SAN_DIAG_SUPPORT */
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
}
if (reset == 0) {
/*
* tgt lun reset fcp cmd has been prepared
* separately in the beginning
*/
channel)) != FC_SUCCESS) {
if (rval == 0xff) {
0, 1);
rval = FC_SUCCESS;
}
return (rval);
}
}
cp->ulpSendCmd++;
/* Initalize sbp */
if (pkt->pkt_cmdlen) {
}
}
return (FC_SUCCESS);
} /* emlxs_send_fcp_cmd() */
#ifdef SFCT_SUPPORT
static int32_t
{
/* Make sure node is still active */
if (!ndlp->nlp_active) {
"*Node not found. did=%x", did);
return (FC_BADPACKET);
}
/* If gate is closed */
return (FC_TRAN_BUSY);
}
/* 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);
}
/* Point of no return */
cp->ulpSendCmd++;
#if (EMLXS_MODREV >= EMLXS_MODREV3)
#else
#endif /* >= EMLXS_MODREV3 */
} else { /* SLI3 */
iocb->ULPBDECOUNT = 0;
}
/* Initalize iocbq */
/* Initalize iocb */
iocb->ULPRSVDBYTE =
/* Set the pkt timer */
if (pkt->pkt_cmdlen) {
}
return (FC_SUCCESS);
} /* emlxs_send_fct_status() */
static int32_t
{
/* Make sure node is still active */
"*Node not found. did=%x", did);
return (FC_BADPACKET);
}
/* If gate is closed */
return (FC_TRAN_BUSY);
}
/* 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);
}
/* Point of no return */
/*
* Don't give the abort priority, we want the IOCB
* we are aborting to be processed first.
*/
/* Create the abort IOCB */
} else {
/* Create the close IOCB */
}
iocb->ULPRSVDBYTE =
/* Set the pkt timer */
return (FC_SUCCESS);
} /* emlxs_send_fct_abort() */
#endif /* SFCT_SUPPORT */
static int32_t
{
uint32_t i;
/* Check if node exists */
/* Broadcast did is always a success */
"Node not found. did=0x%x", did);
return (FC_BADPACKET);
}
/* Check if gate is temporarily closed */
return (FC_TRAN_BUSY);
}
/* Check if an exchange has been created */
/* No exchange. Try creating one */
"Adapter Busy. Exchange not found. did=0x%x", did);
return (FC_TRAN_BUSY);
}
/* ULP PATCH: pkt_cmdlen was found to be set to zero */
/* on BROADCAST commands */
if (pkt->pkt_cmdlen == 0) {
/* Set the pkt_cmdlen to the cookie size */
#if (EMLXS_MODREV >= EMLXS_MODREV3)
for (i = 0; i < pkt->pkt_cmd_cookie_cnt; i++) {
}
#else
#endif /* >= EMLXS_MODREV3 */
}
if (rval == 0xff) {
rval = FC_SUCCESS;
}
return (rval);
}
cp->ulpSendCmd++;
/* Initalize sbp */
if (pkt->pkt_cmdlen) {
}
return (FC_SUCCESS);
} /* emlxs_send_ip() */
static int32_t
{
int i;
char fcsp_msg[32];
int rc;
fcsp_msg[0] = 0;
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
cmd &= ELS_CMD_MASK;
/* Point of no return, except for ADISC & PLOGI */
/* Check node */
switch (cmd) {
case ELS_CMD_FLOGI:
(void) emlxs_mb_init_vpi(port);
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
return (FC_FAILURE);
}
}
}
cmd = ELS_CMD_FDISC;
}
}
/* We will process these cmds at the bottom of this routine */
break;
case ELS_CMD_PLOGI:
/* Make sure we don't log into ourself */
for (i = 0; i < MAX_VPORTS; i++) {
continue;
}
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
return (FC_FAILURE);
}
}
/* Check if this is the first PLOGI */
/* after a PT_TO_PT connection */
/* ULP bug fix */
"PLOGI: P2P Fix. sid=0-->%x did=%x",
}
/* Update our service parms */
MEM_MBOX, 1))) {
mbox, MBX_NOWAIT, 0);
}
}
}
/* We will process these cmds at the bottom of this routine */
break;
default:
/* If an ADISC is being sent and we have no node, */
/* then we must fail the ADISC now */
/* Build the LS_RJT response */
"ADISC Rejected. Node not found. did=0x%x", did);
} else {
}
}
/* Return this as rejected by the target */
return (FC_SUCCESS);
}
}
/* DID == BCAST_DID is special case to indicate that */
/* RPI is being passed in seq_id field */
/* This is used by emlxs_send_logo() for target mode */
/* Initalize iocbq */
if (rval == 0xff) {
rval = FC_SUCCESS;
}
return (rval);
}
cp->ulpSendCmd++;
/* Check cmd */
switch (cmd) {
case ELS_CMD_PRLI:
{
/*
* if our firmware version is 3.20 or later,
* set the following bits for FC-TAPE support.
*/
} else {
}
break;
}
/* This is a patch for the ULP stack. */
/*
* ULP only reads our service paramters once during bind_port,
* but the service parameters change due to topology.
*/
case ELS_CMD_FLOGI:
case ELS_CMD_FDISC:
case ELS_CMD_PLOGI:
case ELS_CMD_PDISC:
{
/* Copy latest service parameters to payload */
(cmd == ELS_CMD_PLOGI)) {
}
#ifdef DHCHAP_SUPPORT
#endif /* DHCHAP_SUPPORT */
break;
}
}
/* Initialize the sbp */
if (pkt->pkt_cmdlen) {
}
/* Check node */
switch (cmd) {
case ELS_CMD_FLOGI:
/* Make sure fabric node is destroyed */
/* It should already have been destroyed at link down */
/* Unregister the fabric did and attempt a deferred */
/* iocb send */
/* Deferring iocb tx until */
/* completion of unreg */
return (FC_SUCCESS);
}
}
}
break;
case ELS_CMD_PLOGI:
/* Close the node for any further normal IO */
/* Flush tx queues */
/* Flush chip queues */
}
break;
case ELS_CMD_PRLI:
/*
* Close the node for any further FCP IO;
* Flush all outstanding I/O only if
* "Establish Image Pair" bit is set.
*/
/* Flush tx queues */
/* Flush chip queues */
(void) emlxs_chipq_node_flush(port,
}
}
break;
}
return (FC_SUCCESS);
} /* emlxs_send_els() */
static int32_t
{
int i;
char fcsp_msg[32];
fcsp_msg[0] = 0;
/* Acquire the unsolicited command this pkt is replying to */
/* This is for auto replies when no ub's are used */
#ifdef SFCT_SUPPORT
}
#endif /* SFCT_SUPPORT */
} else {
/* Find the ub buffer that goes with this reply */
"ELS reply: Invalid oxid=%x",
return (FC_BADPACKET);
}
/* Reset oxid to ELS command */
/* We do this because the ub is only valid */
/* until we return from this thread */
}
/* Save the result */
} else {
}
}
/* Check for interceptions */
switch (ucmd) {
#ifdef ULP_PATCH2
case ELS_CMD_LOGO:
break;
}
/* Check if this was generated by ULP and not us */
/*
* Since we replied to this already,
* we won't need to send this now
*/
return (FC_SUCCESS);
}
break;
#endif /* ULP_PATCH2 */
#ifdef ULP_PATCH3
case ELS_CMD_PRLI:
break;
}
/* Check if this was generated by ULP and not us */
/*
* Since we replied to this already,
* we won't need to send this now
*/
return (FC_SUCCESS);
}
break;
#endif /* ULP_PATCH3 */
#ifdef ULP_PATCH4
case ELS_CMD_PRLO:
break;
}
/* Check if this was generated by ULP and not us */
/*
* Since we replied to this already,
* we won't need to send this now
*/
return (FC_SUCCESS);
}
break;
#endif /* ULP_PATCH4 */
#ifdef ULP_PATCH6
case ELS_CMD_RSCN:
break;
}
/* Check if this RSCN was generated by us */
cmd &= ELS_CMD_MASK;
/*
* If ULP is accepting this,
* then close affected node
*/
== ELS_CMD_ACC) {
/*
* Only the Leadville code path will
* come thru here. The RSCN data is NOT
* swapped properly for the Comstar code
* path.
*/
count =
/* Close affected ports */
(void) emlxs_port_offline(port,
*lp);
}
}
"RSCN %s: did=%x oxid=%x rxid=%x. "
/*
* Since we generated this RSCN,
* we won't need to send this reply
*/
return (FC_SUCCESS);
}
break;
#endif /* ULP_PATCH6 */
case ELS_CMD_PLOGI:
/* Check if this PLOGI was generated by us */
cmd &= ELS_CMD_MASK;
"PLOGI %s: did=%x oxid=%x rxid=%x. "
/*
* Since we generated this PLOGI,
* we won't need to send this reply
*/
return (FC_SUCCESS);
}
break;
}
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
cmd &= ELS_CMD_MASK;
/* Check if modifications are needed */
switch (ucmd) {
case (ELS_CMD_PRLI):
if (cmd == ELS_CMD_ACC) {
/* This is a patch for the ULP stack. */
/* ULP does not keep track of FCP2 support */
} else {
}
}
break;
case ELS_CMD_FLOGI:
case ELS_CMD_PLOGI:
case ELS_CMD_FDISC:
case ELS_CMD_PDISC:
if (cmd == ELS_CMD_ACC) {
/* This is a patch for the ULP stack. */
/*
* ULP only reads our service parameters
* once during bind_port, but the service
* parameters change due to topology.
*/
/* Copy latest service parameters to payload */
#ifdef DHCHAP_SUPPORT
#endif /* DHCHAP_SUPPORT */
}
break;
}
/* Initalize iocbq */
if (rval == 0xff) {
rval = FC_SUCCESS;
}
return (rval);
}
cp->ulpSendCmd++;
/* Initalize sbp */
/* Process nodes */
switch (ucmd) {
case ELS_CMD_RSCN:
{
/*
* Only the Leadville code path will come thru
* here. The RSCN data is NOT swapped properly
* for the Comstar code path.
*/
/* Close affected ports */
}
}
break;
}
case ELS_CMD_PLOGI:
if (cmd == ELS_CMD_ACC) {
/* Close the node for any further normal IO */
/* Flush tx queue */
/* Flush chip queue */
}
}
break;
case ELS_CMD_PRLI:
if (cmd == ELS_CMD_ACC) {
/* Close the node for any further normal IO */
/* Flush tx queues */
/* Flush chip queues */
(void) emlxs_chipq_node_flush(port,
}
}
break;
case ELS_CMD_PRLO:
if (cmd == ELS_CMD_ACC) {
/* Close the node for any further normal IO */
/* Flush tx queues */
/* Flush chip queues */
(void) emlxs_chipq_node_flush(port,
}
}
break;
case ELS_CMD_LOGO:
if (cmd == ELS_CMD_ACC) {
/* Close the node for any further normal IO */
/* Flush tx queues */
/* Flush chip queues */
}
}
break;
}
if (pkt->pkt_cmdlen) {
}
return (FC_SUCCESS);
} /* emlxs_send_els_rsp() */
#ifdef MENLO_SUPPORT
static int32_t
{
"Node not found. did=0x%x", did);
return (FC_BADPACKET);
}
if (rval == 0xff) {
rval = FC_SUCCESS;
}
return (rval);
}
cp->ulpSendCmd++;
/* Cmd phase */
/* Initalize iocb */
iocb->ULPCONTEXT = 0;
"%s: [%08x,%08x,%08x,%08x]",
} else { /* FC_PKT_OUTBOUND */
/* MENLO_CMD_FW_DOWNLOAD Data Phase */
/* Initalize iocb */
"%s: Data: rxid=0x%x size=%d",
}
/* Initalize sbp */
return (FC_SUCCESS);
} /* emlxs_send_menlo() */
#endif /* MENLO_SUPPORT */
static int32_t
{
"Node not found. did=0x%x", did);
return (FC_BADPACKET);
}
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
if (rval == 0xff) {
rval = FC_SUCCESS;
}
return (rval);
}
cp->ulpSendCmd++;
/* Initalize sbp */
if (did == NAMESERVER_DID) {
"%s: did=%x [%08x,%08x]",
}
"%s: did=%x [%08x,%08x]",
} else {
"%s: did=%x [%08x,%08x]",
}
if (pkt->pkt_cmdlen) {
}
return (FC_SUCCESS);
} /* emlxs_send_ct() */
static int32_t
{
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
if (rval == 0xff) {
rval = FC_SUCCESS;
}
return (rval);
}
cp->ulpSendCmd++;
/* Initalize sbp */
"%s: Rsn=%x Exp=%x [%08x,%08x] rxid=%x ",
if (pkt->pkt_cmdlen) {
}
return (FC_SUCCESS);
} /* emlxs_send_ct_rsp() */
/*
* emlxs_get_instance()
* Given a ddi ddiinst, return a Fibre Channel (emlx) ddiinst.
*/
extern uint32_t
{
uint32_t i;
inst = MAX_FC_BRDS;
for (i = 0; i < emlxs_instance_count; i++) {
if (emlxs_instance[i] == ddiinst) {
inst = i;
break;
}
}
return (inst);
} /* emlxs_get_instance() */
/*
* emlxs_add_instance()
* Given a ddi ddiinst, create a Fibre Channel (emlx) ddiinst.
* emlx ddiinsts are the order that emlxs_attach gets called, starting at 0.
*/
static uint32_t
{
uint32_t i;
/* First see if the ddiinst already exists */
for (i = 0; i < emlxs_instance_count; i++) {
if (emlxs_instance[i] == ddiinst) {
break;
}
}
/* If it doesn't already exist, add it */
if (i >= emlxs_instance_count) {
if ((i = emlxs_instance_count) < MAX_FC_BRDS) {
emlxs_instance[i] = ddiinst;
}
}
return (i);
} /* emlxs_add_instance() */
/*ARGSUSED*/
extern void
{
if (!port) {
return;
}
/* Check for error conditions */
PACKET_IN_TXQ | PACKET_IN_CHIPQ)) {
"Packet already returned. sbp=%p flags=%x", sbp,
}
"Packet already completed. sbp=%p flags=%x", sbp,
}
"Pkt already on done queue. sbp=%p flags=%x", sbp,
}
"Packet already in completion. sbp=%p flags=%x",
}
"Packet still on chip queue. sbp=%p flags=%x",
}
"Packet still on tx queue. sbp=%p flags=%x", sbp,
}
return;
}
/* Packet is now in completion */
/* Set the state if not already set */
}
/* Check for parent flush packet */
/* If pkt has a parent flush packet then adjust its count now */
if (fpkt) {
/*
* We will try to NULL sbp->fpkt inside the
* fpkt's mutex if possible
*/
if (fpkt->flush_count) {
fpkt->flush_count--;
}
} else { /* fpkt has been returned already */
}
}
/* If pkt is polled, then wake up sleeping thread */
/* Don't set the PACKET_ULP_OWNED flag here */
/* because the polling thread will do it */
/* Wake up sleeping thread */
}
/* If packet was generated by our driver, */
/* then complete it immediately */
}
/* Put the pkt on the done queue for callback */
/* completion in another thread */
else {
/* Put pkt on doneq, so I/O's will be completed in order */
} else {
hba->iodone_count++;
}
/* Trigger a thread to service the doneq */
}
return;
} /* emlxs_pkt_complete() */
#ifdef SAN_DIAG_SUPPORT
/*
* This routine is called with EMLXS_PORT_LOCK held so we can just increment
* normally. Don't have to use atomic operations.
*/
extern void
{
hrtime_t t;
int i;
if ((sd_bucket.search_type == 0) ||
return;
/* Compute the iolatency time in microseconds */
t = gethrtime();
if (ndlp) {
if (delta_time >=
count++;
else {
for (i = 1; i < SD_IO_LATENCY_MAX_BUCKETS; i++) {
break;
}
}
}
}
}
#endif /* SAN_DIAG_SUPPORT */
/*ARGSUSED*/
static void
{
/* Remove one pkt from the doneq head and complete it */
hba->iodone_count = 0;
} else {
hba->iodone_count--;
}
/* Prepare the pkt for completion */
/* Complete the IO now */
/* Reacquire lock and check if more work is to be done */
}
return;
} /* End emlxs_iodone_server */
static void
{
/* Check one more time that the pkt has not already been returned */
return;
}
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#endif /* EMLXS_MODREV2X */
cp->ulpCmplCmd++;
}
return;
} /* emlxs_iodone() */
extern fc_unsol_buf_t *
{
/* Check if this is a valid ub token */
if (token < EMLXS_UB_TOKEN_OFFSET) {
return (NULL);
}
while (pool) {
/* Find a pool with the proper token range */
pool->pool_first_token)];
}
"ub_find: Buffer not in use. buffer=%p "
}
return (ubp);
}
}
return (NULL);
} /* emlxs_ub_find() */
extern fc_unsol_buf_t *
{
uint32_t i;
while (pool) {
/* Find a pool of the appropriate type and size */
if ((pool->pool_available == 0) ||
goto next_pool;
}
/* Adjust free counts based on availablity */
/* The free reserve count gets first priority */
/* Initialize reserve flag */
if (resv_flag) {
if (pool_free_resv == 0) {
if (pool_free == 0) {
goto next_pool;
}
resv_flag = 0;
}
} else if (pool_free == 0) {
goto next_pool;
}
/* Find next available free buffer in this pool */
for (i = 0; i < pool->pool_nentries; i++) {
continue;
}
/* Timeout in 5 minutes */
/* Alloc the buffer from the pool */
if (resv_flag) {
pool->pool_free_resv--;
} else {
}
"ub_get: ubp=%p token=%x (%d,%d,%d,%d)", ubp,
return (ubp);
}
}
return (NULL);
} /* emlxs_ub_get() */
extern void
{
uint32_t i;
if (lock) {
}
/* Perform table lookup */
if (iostat != IOSTAT_LOCAL_REJECT) {
for (i = 0; i < IOSTAT_MAX; i++, tptr++) {
break;
}
}
} else { /* iostate == IOSTAT_LOCAL_REJECT */
break;
}
}
}
if (entry) {
} else {
/* Set defaults */
}
/* Set the residual counts and response frame */
/* Check if response frame was received from the chip */
/* If so, then the residual counts will already be set */
/* We have to create the response frame */
if (iostat == IOSTAT_SUCCESS) {
pkt->pkt_resp_resid = 0;
pkt->pkt_data_resid = 0;
rsp_len_set = 1;
}
} else {
/* Otherwise assume no data */
/* and no response received */
}
}
}
if (lock) {
}
return;
} /* emlxs_set_pkt_state() */
#if (EMLXS_MODREVX == EMLXS_MODREV2X)
extern void
{
uint16_t *p;
int size;
int i;
for (i = 0; i < size; i++) {
p[i] = LE_SWAP16(p[i]);
}
for (i = 0; i < size; i++, p++) {
*p = LE_SWAP16(*p);
}
for (i = 0; i < size; i++, p++) {
*p = LE_SWAP16(*p);
}
for (i = 0; i < size; i++, p++) {
*p = LE_SWAP16(*p);
}
for (i = 0; i < size; i++, p++) {
*p = LE_SWAP16(*p);
}
return;
} /* emlxs_swap_service_params() */
extern void
{
}
}
}
} /* emlxs_unswap_pkt() */
extern void
{
uint32_t i;
return;
}
} else {
}
/* The size of data buffer needs to be swapped. */
/*
* Swap first 2 words of FCP CMND payload.
*/
for (i = 0; i < 4; i++) {
}
if (rsp) {
}
return;
} /* emlxs_swap_fcp_pkt() */
extern void
{
uint16_t *c;
uint32_t i;
return;
}
swapped = 1;
} else {
swapped = 0;
}
if (!swapped) {
} else {
}
if (rsp) {
}
switch (command) {
case ELS_CMD_ACC:
/* Hard address of originator */
/* N_Port ID of originator */
}
break;
case ELS_CMD_PLOGI:
case ELS_CMD_FLOGI:
case ELS_CMD_FDISC:
if (rsp) {
}
break;
case ELS_CMD_LOGO:
break;
case ELS_CMD_RLS:
if (rsp) {
for (i = 0; i < 6; i++) {
}
}
break;
case ELS_CMD_ADISC:
break;
case ELS_CMD_PRLI:
if (rsp) {
}
break;
case ELS_CMD_SCR:
break;
case ELS_CMD_LINIT:
if (rsp) {
}
break;
default:
break;
}
return;
} /* emlxs_swap_els_pkt() */
extern void
{
uint32_t i;
return;
}
swapped = 1;
} else {
swapped = 0;
}
if (!swapped) {
cmd[0] = 0x01000000;
}
if (swapped) {
}
switch ((command >> 16)) {
case SLI_CTNS_GA_NXT:
break;
case SLI_CTNS_GPN_ID:
case SLI_CTNS_GNN_ID:
case SLI_CTNS_RPN_ID:
case SLI_CTNS_RNN_ID:
case SLI_CTNS_RSPN_ID:
break;
case SLI_CTNS_RCS_ID:
case SLI_CTNS_RPT_ID:
break;
case SLI_CTNS_RFT_ID:
/* Swap FC4 types */
for (i = 0; i < 8; i++) {
}
break;
case SLI_CTNS_GFT_ID:
if (rsp) {
/* Swap FC4 types */
for (i = 0; i < 8; i++) {
}
}
break;
case SLI_CTNS_GCS_ID:
case SLI_CTNS_GSPN_ID:
case SLI_CTNS_GSNN_NN:
case SLI_CTNS_GIP_NN:
case SLI_CTNS_GIPA_NN:
case SLI_CTNS_GPT_ID:
case SLI_CTNS_GID_NN:
case SLI_CTNS_GNN_IP:
case SLI_CTNS_GIPA_IP:
case SLI_CTNS_GID_FT:
case SLI_CTNS_GID_PT:
case SLI_CTNS_GID_PN:
case SLI_CTNS_RIP_NN:
case SLI_CTNS_RIPA_NN:
case SLI_CTNS_RSNN_NN:
case SLI_CTNS_DA_ID:
case SLI_CT_RESPONSE_FS_RJT:
case SLI_CT_RESPONSE_FS_ACC:
default:
break;
}
return;
} /* emlxs_swap_ct_pkt() */
extern void
{
uint32_t i;
case ELS_CMD_RSCN:
}
break;
case ELS_CMD_FLOGI:
case ELS_CMD_PLOGI:
case ELS_CMD_FDISC:
case ELS_CMD_PDISC:
break;
/* ULP handles this */
case ELS_CMD_LOGO:
case ELS_CMD_PRLI:
case ELS_CMD_PRLO:
case ELS_CMD_ADISC:
default:
break;
}
return;
} /* emlxs_swap_els_ub() */
#endif /* EMLXS_MODREV2X */
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_elscmd_table[i].string);
}
}
return (buffer);
} /* emlxs_elscmd_xlate() */
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_ctcmd_table[i].string);
}
}
return (buffer);
} /* emlxs_ctcmd_xlate() */
#ifdef MENLO_SUPPORT
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_menlo_cmd_table[i].string);
}
}
return (buffer);
} /* emlxs_menlo_cmd_xlate() */
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_menlo_rsp_table[i].string);
}
}
return (buffer);
} /* emlxs_menlo_rsp_xlate() */
#endif /* MENLO_SUPPORT */
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_rmcmd_table[i].string);
}
}
return (buffer);
} /* emlxs_rmcmd_xlate() */
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_mscmd_table[i].string);
}
}
return (buffer);
} /* emlxs_mscmd_xlate() */
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_state_table[i].string);
}
}
return (buffer);
} /* emlxs_state_xlate() */
extern char *
{
static char buffer[32];
uint32_t i;
for (i = 0; i < count; i++) {
return (emlxs_error_table[i].string);
}
}
return (buffer);
} /* emlxs_error_xlate() */
static int
{
int ddiinst;
int emlxinst;
rval = DDI_SUCCESS;
/* Lower the power level */
rval =
} else {
/* We do not have kernel support of power management enabled */
/* therefore, call our power management routine directly */
rval =
}
return (rval);
} /* emlxs_pm_lower_power() */
static int
{
int ddiinst;
int emlxinst;
/* Raise the power level */
rval =
} else {
/* We do not have kernel support of power management enabled */
/* therefore, call our power management routine directly */
rval =
}
return (rval);
} /* emlxs_pm_raise_power() */
#ifdef IDLE_TIMER
extern int
{
int rval;
return (DDI_SUCCESS);
}
return (DDI_SUCCESS);
}
/* Attempt to notify system that we are busy */
"pm_busy_component.");
if (rval != DDI_SUCCESS) {
"pm_busy_component failed. ret=%d", rval);
/* If this attempt failed then clear our flags */
return (rval);
}
}
return (DDI_SUCCESS);
} /* emlxs_pm_busy_component() */
extern int
{
int rval;
return (DDI_SUCCESS);
}
return (DDI_SUCCESS);
}
"pm_idle_component.");
if (rval != DDI_SUCCESS) {
"pm_idle_component failed. ret=%d", rval);
/* If this attempt failed then */
/* reset our flags for another attempt */
return (rval);
}
}
return (DDI_SUCCESS);
} /* emlxs_pm_idle_component() */
extern void
{
/* Clear active flag and reset idle timer */
hba->pm_idle_timer =
}
/* Check for idle timeout */
hba->pm_idle_timer =
}
}
return;
} /* emlxs_pm_idle_timer() */
#endif /* IDLE_TIMER */
static void
{
char **arrayp;
uint8_t *s;
uint32_t i;
uint32_t j;
char buffer[64];
/* Check for the per adapter vport setting */
cnt = 0;
rval =
/* Check for the global vport setting */
cnt = 0;
rval =
}
return;
}
for (i = 0; i < cnt; i++) {
errors = 0;
if (!s) {
break;
}
for (j = 0; j < sizeof (NAME_TYPE); j++) {
c1 = *s++;
} else {
"Config error: Invalid PWWPN found. "
"entry=%d byte=%d hi_nibble=%c",
i, j, c1);
errors++;
}
c1 = *s++;
} else {
"Config error: Invalid PWWPN found. "
"entry=%d byte=%d lo_nibble=%c",
i, j, c1);
errors++;
}
}
if (*s++ != ':') {
"Config error: Invalid delimiter after PWWPN. "
"entry=%d", i);
goto out;
}
for (j = 0; j < sizeof (NAME_TYPE); j++) {
c1 = *s++;
} else {
"Config error: Invalid WWNN found. "
"entry=%d byte=%d hi_nibble=%c",
i, j, c1);
errors++;
}
c1 = *s++;
} else {
"Config error: Invalid WWNN found. "
"entry=%d byte=%d lo_nibble=%c",
i, j, c1);
errors++;
}
}
if (*s++ != ':') {
"Config error: Invalid delimiter after WWNN. "
"entry=%d", i);
goto out;
}
for (j = 0; j < sizeof (NAME_TYPE); j++) {
c1 = *s++;
} else {
"Config error: Invalid WWPN found. "
"entry=%d byte=%d hi_nibble=%c",
i, j, c1);
errors++;
}
c1 = *s++;
} else {
"Config error: Invalid WWPN found. "
"entry=%d byte=%d lo_nibble=%c",
i, j, c1);
errors++;
}
}
if (*s++ != ':') {
"Config error: Invalid delimiter after WWPN. "
"entry=%d", i);
goto out;
}
sum = 0;
do {
c1 = *s++;
"Config error: Invalid VPI found. "
goto out;
}
} while (*s != 0);
if (errors) {
continue;
}
/* Entry has been read */
/* Check if the physical port wwpn */
/* matches our physical port wwpn */
continue;
}
/* Check vpi range */
continue;
}
/* Check if port has already been configured */
continue;
}
/* Set the highest configured vpi */
}
sizeof (NAME_TYPE));
sizeof (NAME_TYPE));
}
"%s VPort-%d",
}
}
}
out:
(void) ddi_prop_free((void *) arrayp);
return;
} /* emlxs_read_vport_prop() */
extern char *
{
return (buffer);
} /* emlxs_wwn_xlate() */
/* This is called at port online and offline */
extern void
{
/* Return if nothing to do */
if (!port->ub_wait_head) {
return;
}
while (ub_priv) {
/* Check if ULP is online and we have a callback function */
port->ulp_unsol_cb) {
/* Send ULP the ub buffer */
} else { /* Drop the buffer */
}
} /* while () */
return;
} /* emlxs_ub_flush() */
extern void
{
/* Check if ULP is online */
if (port->ulp_unsol_cb) {
} else {
}
return;
} else { /* ULP offline */
/* Add buffer to queue tail */
if (port->ub_wait_tail) {
}
if (!port->ub_wait_head) {
}
} else {
}
}
return;
} /* emlxs_ub_callback() */
static uint32_t
{
size = 16;
errors++;
}
size = 8;
errors++;
}
size = 12;
errors++;
}
size = 16;
errors++;
}
size = 8;
errors++;
}
errors++;
}
size = 4;
errors++;
}
size = 124;
if (sizeof (MAILVARIANTS) != size) {
(int)sizeof (MAILVARIANTS));
errors++;
}
size = 128;
errors++;
}
errors++;
}
errors++;
}
errors++;
}
size = 260;
if (sizeof (ATTRIBUTE_ENTRY) != size) {
(int)sizeof (ATTRIBUTE_ENTRY));
errors++;
}
errors++;
}
errors++;
}
errors++;
}
return (errors);
} /* emlxs_integrity_check() */
#ifdef FMA_SUPPORT
/*
* FMA support
*/
extern void
{
return;
}
} else {
}
} else {
}
}
(void *)hba);
}
} /* emlxs_fm_init() */
extern void
{
return;
}
}
}
} /* emlxs_fm_fini() */
extern int
{
return (DDI_FM_OK);
}
/* Some S10 versions do not define the ahi_err structure */
return (DDI_FM_OK);
}
/* Some S10 versions do not define the ddi_fm_acc_err_clear function */
if ((void *)&ddi_fm_acc_err_clear != NULL) {
}
return (err.fme_status);
} /* emlxs_fm_check_acc_handle() */
extern int
{
return (DDI_FM_OK);
}
return (err.fme_status);
} /* emlxs_fm_check_dma_handle() */
extern void
{
char buf[FM_MAX_CLASS];
return;
}
return;
}
} /* emlxs_fm_ereport() */
extern void
{
return;
}
return;
}
(impact == DDI_SERVICE_DEGRADED)) {
}
} /* emlxs_fm_service_impact() */
/*
* The I/O fault service error handling callback function
*/
/*ARGSUSED*/
extern int
const void *impl_data)
{
/*
* as the driver can always deal with an error
* in any dma or access handle, we can just return
* the fme_status value.
*/
return (err->fme_status);
} /* emlxs_fm_error_cb() */
#endif /* FMA_SUPPORT */
extern void
{
uint32_t i;
for (i = 0; i < size / 4; i++) {
}
return;
} /* emlxs_swap32_buffer() */
extern void
{
uint32_t i;
for (i = 0; i < size / 4; i++) {
}
return;
} /* emlxs_swap32_buffer() */