emlxs_fct.c revision e2ca2865a6870e9c6cbef6becbcc68cafde64537
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Emulex. All rights reserved.
* Use is subject to license terms.
*/
#include <emlxs.h>
#ifdef SFCT_SUPPORT
/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
struct fct_flogi_xchg *fx);
#ifdef FCT_IO_TRACE
int emlxs_iotrace_cnt = 0;
/*
*
* FCT_CMD (cmd_sbp->fct_state)
*
* STATE LOCK STATUS OWNER
* -----------------------------------------------------------------------------
* EMLXS_FCT_ABORT_DONE Lock Destroyed COMSTAR
* EMLXS_FCT_IO_DONE Lock Destroyed COMSTAR
*
* EMLXS_FCT_CMD_POSTED Lock Released COMSTAR
* EMLXS_FCT_OWNED Lock Released COMSTAR
*
* EMLXS_FCT_CMD_WAITQ Lock Released DRIVER
* EMLXS_FCT_RSP_PENDING Lock Released DRIVER
* EMLXS_FCT_REQ_PENDING Lock Released DRIVER
* EMLXS_FCT_REG_PENDING Lock Released DRIVER
* EMLXS_FCT_DATA_PENDING Lock Released DRIVER
* EMLXS_FCT_STATUS_PENDING Lock Released DRIVER
* EMLXS_FCT_CLOSE_PENDING Lock Released DRIVER
* EMLXS_FCT_ABORT_PENDING Lock Released DRIVER
*
* EMLXS_FCT_FCP_CMD_RECEIVED Transistional, lock held DRIVER
* EMLXS_FCT_ELS_CMD_RECEIVED Transistional, lock held DRIVER
* EMLXS_FCT_SEND_CMD_RSP Transistional, lock held DRIVER
* EMLXS_FCT_SEND_ELS_RSP Transistional, lock held DRIVER
* EMLXS_FCT_SEND_ELS_REQ Transistional, lock held DRIVER
* EMLXS_FCT_SEND_CT_REQ Transistional, lock held DRIVER
* EMLXS_FCT_REG_COMPLETE Transistional, lock held DRIVER
* EMLXS_FCT_SEND_FCP_DATA Transistional, lock held DRIVER
* EMLXS_FCT_SEND_FCP_STATUS Transistional, lock held DRIVER
* EMLXS_FCT_PKT_COMPLETE Transistional, lock held DRIVER
* EMLXS_FCT_PKT_FCPRSP_COMPLETE Transistional, lock held DRIVER
* EMLXS_FCT_PKT_ELSRSP_COMPLETE Transistional, lock held DRIVER
* EMLXS_FCT_PKT_ELSCMD_COMPLETE Transistional, lock held DRIVER
* EMLXS_FCT_PKT_CTCMD_COMPLETE Transistional, lock held DRIVER
* EMLXS_FCT_REQ_COMPLETE Transistional, lock held DRIVER
*
*
* COMSTAR OWNED DRIVER OWNED
* ------------- ---------------------------------------------------
* ------- > @ Accept---- >Release @ Acquire--- >+
* |
*
* @ :Indicates COMSTAR use of emlxs_fct_abort()
* Abort requests set the EMLXS_FCT_ABORT_INP flag.
*
* Accept :Indicates use of emlxs_fct_cmd_accept()
* Acquire :Indicates use of emlxs_fct_cmd_acquire()
* Post :Indicates use of emlxs_fct_cmd_post()
* Done :Indicates use of emlxs_fct_cmd_done()
*/
void
{
int i;
if (!iop) {
return;
}
switch (data) {
/* New entry */
case EMLXS_FCT_SEND_ELS_REQ:
case EMLXS_FCT_SEND_CT_REQ:
for (i = 0; i < iotrace_cnt; i++) {
break;
iop++;
}
if (i < iotrace_cnt) {
/* New entry already exists */
"IOTRACE: New entry already exists: fct_cmd: %p",
fct_cmd);
return;
}
for (i = 0; i < iotrace_cnt; i++) {
break;
iop++;
}
if (i >= iotrace_cnt) {
/* No new slots available */
"IOTRACE: No new slots: fct_cmd: %p data: %d",
return;
}
port->iotrace_index++;
port->iotrace_index = 0;
return;
}
for (i = 0; i < iotrace_cnt; i++) {
break;
iop++;
}
if (i >= iotrace_cnt) {
/* Cannot find existing slot for fct_cmd */
if ((data != EMLXS_FCT_REG_PENDING) &&
(data != EMLXS_FCT_REG_COMPLETE)) {
"IOTRACE: Missing slot: fct_cmd: %p data: %d",
}
return;
}
/* trc overrun for fct_cmd */
"IOTRACE: trc overrun slot: fct_cmd: %p data: %d",
return;
}
/* xri mismatch for fct_cmd */
"IOTRACE: xri mismatch %x != %x: fct_cmd: %p data: %d",
return;
}
/* IOCB ULPCOMMAND is saved after EMLXS_FCT_IOCB_ISSUED */
} else {
} else {
}
return;
} /* emlxs_fct_io_trace() */
#endif /* FCT_IO_TRACE */
#ifdef MODSYM_SUPPORT
extern int
{
int err;
if (emlxs_modsym.fct_modopen) {
return (0);
}
/* Comstar (fct) */
err = 0;
if (!emlxs_modsym.mod_fct) {
DRIVER_NAME, err);
goto failed;
}
/* Comstar (stmf) */
err = 0;
if (!emlxs_modsym.mod_stmf) {
DRIVER_NAME, err);
goto failed;
}
err = 0;
/* Check if the fct fct_alloc is present */
"fct_alloc", &err);
"?%s: drv/fct: fct_alloc not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fct fct_free is present */
"fct_free", &err);
"?%s: drv/fct: fct_free not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fct fct_scsi_task_alloc is present */
"fct_scsi_task_alloc", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_register_local_port is present */
"fct_register_local_port", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_deregister_local_port is present */
"fct_deregister_local_port", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_handle_event is present */
&err);
goto failed;
}
err = 0;
/* Check if the fct fct_post_rcvd_cmd is present */
&err);
goto failed;
}
err = 0;
/* Check if the fct fct_alloc is present */
"fct_ctl", &err);
"?%s: drv/fct: fct_ctl not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fct fct_queue_cmd_for_termination is present */
"fct_queue_cmd_for_termination", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_send_response_done is present */
"fct_send_response_done", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_send_cmd_done is present */
&err);
goto failed;
}
err = 0;
/* Check if the fct fct_scsi_xfer_data_done is present */
"fct_scsi_data_xfer_done", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_port_shutdown is present */
"fct_port_shutdown", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_port_initialize is present */
"fct_port_initialize", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_cmd_fca_aborted is present */
"fct_cmd_fca_aborted", &err);
goto failed;
}
err = 0;
/* Check if the fct fct_handle_rcvd_flogi is present */
"fct_handle_rcvd_flogi", &err);
goto failed;
}
/* Comstar (stmf) */
err = 0;
/* Check if the stmf stmf_alloc is present */
&err);
"?%s: drv/stmf: stmf_alloc not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the stmf stmf_free is present */
"stmf_free", &err);
"?%s: drv/stmf: stmf_free not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the stmf stmf_deregister_port_provider is present */
"stmf_deregister_port_provider", &err);
goto failed;
}
err = 0;
/* Check if the stmf stmf_register_port_provider is present */
"stmf_register_port_provider", &err);
goto failed;
}
return (0);
return (1);
} /* emlxs_fct_modopen() */
extern void
{
if (emlxs_modsym.fct_modopen == 0) {
return;
}
if (emlxs_modsym.fct_modopen) {
return;
}
if (emlxs_modsym.mod_fct) {
emlxs_modsym.mod_fct = 0;
}
if (emlxs_modsym.mod_stmf) {
emlxs_modsym.mod_stmf = 0;
}
} /* emlxs_fct_modclose() */
#endif /* MODSYM_SUPPORT */
/*
* This routine is called to handle an unsol FLOGI exchange
* fx save
* 0 1 Process or save port->fx
* 0 0 Process or reject port->fx
* 1 1 Process port->fx, Process or save fx
* 1 0 Process or reject port->fx, Process or reject fx
*/
static void
{
/* Check if there is an old saved FLOGI */
/* Get it now */
if (fx) {
/* Save new FLOGI */
/* Reject old stale FLOGI */
goto reject_it;
} else {
}
} else if (!fx) {
/* Nothing to do, just return */
return;
}
/* We have a valid FLOGI here */
/* There is no saved FLOGI at this point either */
/* Check if COMSTAR is ready to accept it */
#ifdef FCT_API_TRACE
"fct_handle_rcvd_flogi %p: status=%x",
#endif /* FCT_API_TRACE */
if (status == FCT_SUCCESS) {
ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0);
} else { /* ELS_OP_LSRJT */
}
} else {
"FLOGI: sid=%x xid=%x. "
"fct_handle_rcvd_flogi failed. Rejecting.",
}
return;
}
if (save) {
/* Save FLOGI for later */
return;
}
"FLOGI: sid=%x xid=%x. Stale. Rejecting.",
/* If we have an FLOGI saved, try sending it now */
goto begin;
}
} else {
"FLOGI: sid=%x xid=%x. Link down. "
"Dropping.",
}
return;
} /* emlxs_fct_handle_unsol_flogi() */
/* This is called at port online and offline */
static void
{
return;
}
/* First handle any pending FLOGI */
/* Wait queue */
/*
* Next process any outstanding ELS commands. It doesn't
* matter if the Link is up or not, always post them to FCT.
*/
while (cmd_sbp) {
/* Reacquire ownership of the fct_cmd */
if (rval) {
"emlxs_fct_unsol_flush: %s: sid=%x xid=%x "
"Unable to reacquire fct_cmd.",
continue;
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
"Completing %s: sid=%x xid=%x %p",
fct_cmd);
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_post_rcvd_cmd:2 %p: portid x%x", fct_cmd,
#endif /* FCT_API_TRACE */
} /* while () */
return;
} /* emlxs_fct_unsol_flush() */
int
{
return (1);
}
return (0);
} /* emlxs_is_digit */
/*
* Convert an ASCII decimal numeric string to integer.
* Negation character '-' is not handled.
*/
{
int i = 0;
while (string[i]) {
if (!emlxs_is_digit(string[i])) {
return (num);
}
}
return (num);
} /* emlxs_str_atoi() */
static void
{
int i;
int bck;
int nbufs;
int maxbufs;
int size;
bck = 0;
for (i = 0; i < cnt; i++) {
if (datap == 0)
break;
datap++;
datap++;
datap++;
datap++;
/* Check for a bad entry */
size = 0;
nbufs = 0;
}
while (nbufs) {
/*
* We are not going to try to allocate a chunk
* of memory > FCT_DMEM_MAX_BUF_SEGMENT
* to accomidate the buffer pool of the
* requested size.
*/
bck++;
if (bck >= FCT_MAX_BUCKETS)
break;
} else {
bck++;
nbufs = 0;
}
}
if (bck >= FCT_MAX_BUCKETS) {
"fct-bufpool entry %d %d Exceeds available buckets",
break;
}
}
}
static void
{
char **arrayp;
char buf[32];
int status;
cnt = 0;
} else {
} else {
sizeof (port->dmem_bucket));
}
}
cnt = 0;
/*
* 0 means use HBA throttle for target queue depth,
* non-0 value is the actual target queue depth,
* default is EMLXS_FCT_DFLT_QDEPTH.
*/
(DDI_PROP_DONTPASS), "fct-queue-depth",
if (cnt == DDI_PROP_NOT_FOUND) {
}
}
#ifdef FCT_IO_TRACE
port->iotrace_index = 0;
if (cnt)
KM_SLEEP);
"FCT_ABORT_SUCCESS:%lx FCT_SUCCESS:%lx", FCT_ABORT_SUCCESS,
#endif /* FCT_IO_TRACE */
return;
} /* emlxs_fct_cfg_init() */
extern void
{
uint32_t i;
return;
}
/* Check if COMSTAR is present */
"Comstar not present. Target mode disabled.");
goto failed;
}
"Comstar present. Target mode enabled.");
"enable-npiv: Not supported in target mode. Disabling.");
/* Temporary patch to disable npiv */
}
#ifdef DHCHAP_SUPPORT
"enable-auth: Not supported in target mode. Disabling.");
/* Temporary patch to disable auth */
}
#endif /* DHCHAP_SUPPORT */
return;
for (i = 0; i < MAX_VPORTS; i++) {
}
return;
} /* emlxs_fct_init() */
extern void
{
return;
}
/* Bind the physical port */
/* Bind virtual ports */
continue;
}
}
}
return;
} /* emlxs_fct_attach() */
extern void
{
uint32_t i;
for (i = 0; i < MAX_VPORTS; i++) {
continue;
}
}
}
#ifdef FCT_IO_TRACE
{
}
#endif /* FCT_IO_TRACE */
return;
} /* emlxs_fct_detach() */
extern void
{
char node_name[32];
return;
}
return;
}
/* Destroy & flush all port nodes, if they exist */
if (port->node_count) {
(void) emlxs_sli4_unreg_all_rpi_by_port(port);
} else {
0);
}
}
hba->num_of_ports--;
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
if (port->port_provider) {
#ifdef FCT_API_TRACE
"stmf_deregister_port_provider:1 %p",
#endif /* FCT_API_TRACE */
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
if (port->dmem_bucket) {
}
return;
} /* emlxs_fct_unbind_port() */
extern void
{
char node_name[32];
return;
}
return;
}
/* Perform generic port initialization */
} else {
}
"emlxs_fct_bind_port: Unable to allocate fct memory.");
goto failed;
}
flag |= 0x00000001;
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
"emlxs_fct_bind_port: Unable to allocate port provider.");
goto failed;
}
flag |= 0x00000002;
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
/* register port provider with framework */
STMF_SUCCESS) {
"emlxs_fct_bind_port: Unable to register port provider.");
goto failed;
}
flag |= 0x00000004;
0);
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
"emlxs_fct_bind_port: Unable to allocate fct port.");
goto failed;
}
flag |= 0x00000008;
0);
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
"emlxs_fct_bind_port: Unable to allocate dbuf store.");
goto failed;
}
flag |= 0x00000010;
NULL, 0) == DDI_FAILURE) {
"Unable to create SFCT device node.");
goto failed;
}
flag |= 0x00000020;
/* Intialize */
"%02x%02x%02x%02x%02x%02x%02x%02x",
"%02x%02x%02x%02x%02x%02x%02x%02x",
if ((port->fct_queue_depth) &&
} else {
}
#ifdef FCT_API_TRACE
"fct_register_local_port %p", fct_port);
#endif /* FCT_API_TRACE */
/* register this local port with the fct module */
"emlxs_fct_bind_port: Unable to register fct port.");
goto failed;
}
/* Set the bound flag */
hba->num_of_ports++;
return;
if (flag & 0x20) {
}
if (flag & 0x10) {
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
if (flag & 0x8) {
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
if (flag & 0x4) {
#ifdef FCT_API_TRACE
"stmf_deregister_port_provider:2 %p",
#endif /* FCT_API_TRACE */
}
if (flag & 0x2) {
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
if (flag & 0x1) {
}
"Target mode disabled.");
return;
} /* emlxs_fct_bind_port() */
/* COMSTAR ENTER POINT */
/*ARGSUSED*/
static fct_status_t
{
switch (cmd) {
case FC_TGT_PORT_RLS:
if ((*size) < sizeof (fct_port_link_status_t)) {
"FC_TGT_PORT_RLS: Buffer too small. %d < %d",
*size, sizeof (fct_port_link_status_t));
rval = FCT_FAILURE;
break;
}
"FC_TGT_PORT_RLS: Unable to allocate mailbox.");
break;
}
!= MBX_SUCCESS) {
"FC_TGT_PORT_RLS: Unable to send request.");
} else {
}
break;
default:
"emlxs_fct_port_info: Invalid request. cmd=%x",
cmd);
rval = FCT_FAILURE;
break;
}
return (rval);
} /* emlxs_fct_port_info() */
/* COMSTAR ENTER POINT */
static void
{
}
}
}
}
}
"Port attr: model_description = %s",
"Port attr: hardware_version = %s",
"Port attr: option_rom_version = %s",
"Port attr: firmware_version = %s",
"Port attr: vendor_specific_id = 0x%x",
"Port attr: supported_cos = 0x%x",
"Port attr: supported_speed = 0x%x",
"Port attr: max_frame_size = 0x%x",
return;
} /* emlxs_fct_populate_hba_details() */
/* COMSTAR ENTER POINT */
/* ARGSUSED */
static void
{
switch (cmd) {
case FCT_CMD_PORT_ONLINE:
/* If the HBA is offline, we cannot bring the tgtport online */
break;
}
"STATE: ONLINE chk");
} else {
"STATE: OFFLINE --> ONLINE");
/* Try to bring the link up */
}
"STATE: ONLINE");
}
break;
case FCT_CMD_PORT_OFFLINE:
"STATE: OFFLINE chk");
} else {
"STATE: ONLINE --> OFFLINE");
/* Take link down and flush */
/* Declare this port offline now */
/* Take link down and hold it down */
"STATE: OFFLINE");
}
break;
"STATE: OFFLINE ack");
break;
"STATE: ONLINE ack");
break;
case FCT_CMD_FORCE_LIP:
"emlxs_fct_ctl: FCT_CMD_FORCE_LIP");
/* Reset the link */
break;
}
return;
} /* emlxs_fct_ctl() */
extern int
{
int i;
if (!fct_port) {
return (0);
}
"emlxs shutdown");
i = 0;
i++;
if (i > 300) { /* 30 seconds */
"fct_port_shutdown failed to ACK");
break;
}
}
return (1);
}
extern int
{
int i;
if (!fct_port) {
return (0);
}
"fct_port_initialize");
"emlxs initialize");
i = 0;
i++;
if (i > 300) { /* 30 seconds */
"fct_port_initialize failed to ACK");
break;
}
}
return (1);
}
/* COMSTAR ENTER POINT */
static fct_status_t
{
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
case FCT_CMD_SOL_ELS:
return (emlxs_fct_send_els_cmd(fct_cmd));
case FCT_CMD_SOL_CT:
return (emlxs_fct_send_ct_cmd(fct_cmd));
default:
"emlxs_fct_send_cmd: Invalid cmd type found. type=%x",
return (FCT_FAILURE);
}
} /* emlxs_fct_send_cmd() */
/* COMSTAR ENTER POINT */
static fct_status_t
{
if (rval) {
"emlxs_fct_send_cmd_rsp: "
"Unable to accept fct_cmd. type=%x",
return (rval);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"emlxs_fct_send_cmd_rsp %p: x%x, %x, %x",
#endif /* FCT_API_TRACE */
case FCT_CMD_FCP_XCHG:
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
goto failure;
}
/* Firmware already sent out resp */
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_send_response_done:4 %p: x%x",
#endif /* FCT_API_TRACE */
return (FCT_SUCCESS);
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (rval);
case FCT_CMD_RCVD_ELS:
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
goto failure;
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (rval);
default:
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
fct_cmd->cmd_handle = 0;
}
"emlxs_fct_send_cmd_rsp: Invalid cmd type found. type=%x",
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_FAILURE);
}
"emlxs_fct_send_cmd_rsp: "
"Unable to handle FCT_IOF_FORCE_FCA_DONE. type=%x",
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_FAILURE);
} /* emlxs_fct_send_cmd_rsp() */
/* COMSTAR ENTER POINT */
static fct_status_t
{
#ifdef FCT_API_TRACE
"emlxs_fct_flogi_xchg: Sending FLOGI: %p", fct_port);
#else
"emlxs_fct_flogi_xchg: Sending FLOGI.");
#endif /* FCT_API_TRACE */
"emlxs_fct_flogi_xchg: FLOGI failed. Link down.");
rval = FCT_FAILURE;
goto done;
}
/* Use this entyr point as the link up acknowlegment */
"emlxs_fct_link_up acked.");
/* Now flush any pending unsolicited requests */
"emlxs_fct_flogi_xchg: FLOGI failed. "
"Unable allocate packet.");
rval = FCT_FAILURE;
goto done;
}
/* Make this a polled IO */
/* Build the fc header */
/* Build the command */
/* Service paramters will be added automatically later by the driver */
"emlxs_fct_flogi_xchg: FLOGI failed. "
"Unable to send packet.");
rval = FCT_FAILURE;
goto done;
}
rval = FCT_TIMEOUT;
} else {
rval = FCT_FAILURE;
}
"emlxs_fct_flogi_xchg: FLOGI failed. state=%x reason=%x",
goto done;
}
} else { /* FC_PKT_SUCCESS */
}
done:
if (pkt) {
}
return (rval);
} /* emlxs_fct_flogi_xchg() */
/* COMSTAR ENTER POINT */
/* This is called right after we report that link has come online */
static fct_status_t
{
"emlxs_fct_get_link_info %p", fct_port);
return (FCT_SUCCESS);
}
} else {
}
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;
}
link->port_no_fct_flogi = 0;
link->port_fca_flogi_done = 0;
link->port_fct_flogi_done = 0;
return (FCT_SUCCESS);
} /* emlxs_fct_get_link_info() */
/* COMSTAR ENTER POINT */
static fct_status_t
{
#ifdef FCT_API_TRACE
"emlxs_fct_register_remote_port %p", fct_port);
#endif /* FCT_API_TRACE */
/* mutex_enter(&cmd_sbp->fct_mtx); */
} else {
if (rval) {
"emlxs_fct_register_remote_port: "
"Unable to accept fct_cmd. did=%x",
return (rval);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
}
}
/* Check for unsolicited PLOGI */
sizeof (uint32_t));
} else { /* Solicited PLOGI */
sizeof (SERV_PARM));
/*
* Create temporary WWN's from fct_cmd address
* This simply allows us to get an RPI from the
* adapter until we get real service params.
* The PLOGI ACC reply will trigger a REG_LOGIN
* update later
*/
}
"emlxs_fct_register_remote_port: Register did=%x. (%x,%p)",
/* mutex_exit(&cmd_sbp->fct_mtx); */
/* Create a new node */
"emlxs_fct_register_remote_port: "
"Reg login failed. did=%x",
} else {
/* Wait for completion */
pkt_ret = 0;
while ((pkt_ret != -1) &&
}
}
/* Reacquire ownership of the fct_cmd */
if (rval2) {
"emlxs_fct_register_remote_port: "
"Unable to reacquire fct_cmd. did=%x",
return (rval2);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
}
done:
if (ndlp) {
"emlxs_fct_register_remote_port: did=%x hdl=%x",
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_SUCCESS);
} else {
"emlxs_fct_register_remote_port: failed. did=%x hdl=%x",
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_FAILURE);
}
} /* emlxs_fct_register_remote_port() */
/* COMSTAR ENTER POINT */
static fct_status_t
{
#ifdef FCT_API_TRACE
"emlxs_fct_deregister_remote_port: did=%x hdl=%x",
#else
"emlxs_fct_deregister_remote_port: did=%x hdl=%x",
#endif /* FCT_API_TRACE */
return (FCT_SUCCESS);
} /* emlxs_fct_deregister_remote_port() */
/* ARGSUSED */
extern int
{
if (!ndlp) {
"FCP rcvd: Unknown RPI. rpi=%x rxid=%x. Dropping...",
goto dropped;
}
"FCP rcvd: Target unbound. rpi=%x rxid=%x. Dropping...",
goto dropped;
}
"FCP rcvd: Target offline. rpi=%x rxid=%x. Dropping...",
goto dropped;
}
/* Get lun id */
}
fct_cmd =
lun, 16, 0);
#ifdef FCT_API_TRACE
"fct_scsi_task_alloc %p: FCP rcvd: "
"cmd=%x sid=%x rxid=%x lun=%02x%02x dl=%d",
#endif /* FCT_API_TRACE */
"FCP rcvd: sid=%x xid=%x. "
"Unable to allocate scsi task. Returning QFULL.",
goto dropped;
}
/* Initialize fct_cmd */
/* mutex_enter(&cmd_sbp->fct_mtx); */
/* Initialize cmd_sbp */
/* Set task_flags */
case SIMPLE_Q:
break;
case HEAD_OF_Q:
break;
case ORDERED_Q:
break;
case ACA_Q:
break;
case UNTAGGED:
break;
}
case 0:
break;
case 1:
break;
case 2:
break;
}
fct_task->task_priority = 0;
/* task_mgmt_function */
if (tm) {
} else {
}
}
/* Parallel buffers support - future */
fct_task->task_cur_nbufs = 0;
fct_task->task_cmd_seq_no = 0;
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_post_rcvd_cmd:3 %p: portid x%x, %d", fct_cmd,
#endif /* FCT_API_TRACE */
return (0);
return (1);
} /* emlxs_fct_handle_unsol_req() */
/* COMSTAR ENTER POINT */
/* ARGSUSED */
static fct_status_t
{
emlxs_port_t *port =
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
int channel;
int channelno;
if (rval) {
"emlxs_fct_send_fcp_data: "
"Unable to accept fct_cmd. did=%x",
return (rval);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
#ifdef FCT_API_TRACE
"emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d, %d",
#endif /* FCT_API_TRACE */
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_BUSY);
}
}
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_SUCCESS);
} /* emlxs_fct_send_fcp_data() */
/* cmd_sbp->fct_mtx must be held to enter */
/* cmd_sbp->fct_mtx must be released before exiting */
static fct_status_t
{
emlxs_port_t *port =
/* Initialize cmd_sbp */
size = 24;
if (fct_task->task_sense_length) {
}
#ifdef FCT_API_TRACE
"emlxs_fct_send_fcp_status %p: stat=%d resid=%d size=%d rx=%x",
#endif /* FCT_API_TRACE */
"emlxs_fct_send_fcp_status: Unable to allocate packet.");
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_BUSY);
}
pkt->pkt_timeout =
/* Build the fc header */
/* Build the status payload */
if (fct_task->task_resid) {
}
}
if (fct_task->task_scsi_status) {
} else {
}
/* Make sure residual reported on non-SCSI_GOOD READ status */
}
}
if (fct_task->task_sense_length) {
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
"emlxs_fct_send_fcp_status: Unable to send packet.");
/* Reacquire ownership of the fct_cmd */
if (rval) {
"emlxs_fct_send_fcp_status: "
"Unable to acquire fct_cmd.");
return (rval);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_BUSY);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_fcp_status() */
static fct_status_t
{
size = 24;
"emlxs_fct_send_qfull_reply: Unable to allocate packet.");
return (FCT_FAILURE);
}
pkt->pkt_timeout =
/* Build the fc header */
"emlxs_fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d",
/* Build the status payload */
"emlxs_fct_send_qfull_reply: Unable to send packet.");
return (FCT_FAILURE);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_qfull_reply() */
/* ARGSUSED */
extern int
{
if (!sbp) {
/* completion with missing xmit command */
/* emlxs_stray_fcp_completion_msg */
"FCP event cmd=%x status=%x error=%x iotag=%x",
return (1);
}
#ifdef FCT_API_TRACE
"emlxs_fct_handle_fcp_event: %p: cmd=%x status=%x, %x",
#endif /* FCT_API_TRACE */
/* For driver generated QFULL response */
}
return (0);
}
if (rval) {
"emlxs_fct_handle_fcp_event: "
"Unable to reacquire fct_cmd. type=%x",
return (1);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
if (status) {
/*
* The error indicates this IO should be terminated
* immediately.
*/
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_queue_cmd_for_termination:1 %p: x%x",
#endif /* FCT_API_TRACE */
goto done;
}
switch (iocb->ULPCOMMAND) {
/*
* FCP Data completion
*/
case CMD_FCP_TSEND_CX:
case CMD_FCP_TSEND64_CX:
case CMD_FCP_TRECEIVE_CX:
case CMD_FCP_TRECEIVE64_CX:
}
fct_task =
fct_task->task_scsi_status = 0;
(void) emlxs_fct_send_fcp_status(fct_cmd);
/* mutex_exit(&cmd_sbp->fct_mtx); */
break;
/* Auto-resp has been sent out by firmware */
/* We can assume this is really a FC_TRSP_CX */
fct_task =
fct_task->task_scsi_status = 0;
goto auto_resp;
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
break;
/* FCP Status completion */
case CMD_FCP_TRSP_CX:
case CMD_FCP_TRSP64_CX:
/* Copy these before calling emlxs_fct_cmd_done */
/* mutex_exit(&cmd_sbp->fct_mtx); */
if (fct_flags & EMLXS_FCT_SEND_STATUS) {
#ifdef FCT_API_TRACE
"fct_scsi_data_xfer_done:2 %p %p",
#endif /* FCT_API_TRACE */
} else {
#ifdef FCT_API_TRACE
"fct_send_response_done:1 %p: x%x",
#endif /* FCT_API_TRACE */
}
break;
default:
/* mutex_exit(&cmd_sbp->fct_mtx); */
if (pkt) {
}
} /* switch(iocb->ULPCOMMAND) */
done:
if (pkt) {
}
if (status == IOSTAT_SUCCESS) {
} else {
}
return (0);
} /* emlxs_fct_handle_fcp_event() */
/* ARGSUSED */
extern int
{
if (!sbp) {
/* completion with missing xmit command */
/* emlxs_stray_fcp_completion_msg */
"ABORT event cmd=%x status=%x error=%x iotag=%x",
return (1);
}
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
if (pkt) {
}
return (0);
} /* emlxs_fct_handle_abort() */
extern int
{
"%s: sid=%x. Target unbound. Rejecting...",
goto done;
}
"%s: sid=%x. Target offline. Rejecting...",
goto done;
}
/* Process the request */
switch (cmd_code) {
case ELS_CMD_FLOGI:
if (!rval) {
/* Save the FLOGI exchange information */
}
goto done;
case ELS_CMD_PLOGI:
rval =
break;
default:
rval = 0;
break;
}
if (rval) {
goto done;
}
#ifdef FCT_API_TRACE
{
"fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x",
}
#endif /* FCT_API_TRACE */
"%s: sid=%x. Out of memory. Rejecting...",
goto done;
}
/* Initialize fct_cmd */
/* mutex_enter(&cmd_sbp->fct_mtx); */
/* Initialize cmd_sbp */
sizeof (emlxs_iocb_t));
/* Check if Offline */
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_post_rcvd_cmd:4 %p: portid x%x", fct_cmd,
#endif /* FCT_API_TRACE */
goto done;
}
/* Online */
/* Check if Link up is acked */
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_post_rcvd_cmd:1 %p: portid x%x", fct_cmd,
#endif /* FCT_API_TRACE */
goto done;
}
/* Defer processing of fct_cmd till later (after link up ack). */
/* mutex_exit(&cmd_sbp->fct_mtx); */
/* Add cmd_sbp to queue tail */
if (port->fct_wait_tail) {
}
if (!port->fct_wait_head) {
}
done:
return (0);
} /* emlxs_fct_handle_unsol_els() */
/* ARGSUSED */
static uint32_t
{
char buffer[64];
buffer[0] = 0;
/* Perform processing of FLOGI payload */
return (1);
}
return (0);
} /* emlxs_fct_process_unsol_flogi() */
/* ARGSUSED */
static uint32_t
{
char buffer[64];
buffer[0] = 0;
/* Perform processing of PLOGI payload */
return (1);
}
return (0);
} /* emlxs_fct_process_unsol_plogi() */
/* ARGSUSED */
static emlxs_buf_t *
{
return (sbp);
} /* emlxs_fct_pkt_init() */
/* Mutex will be acquired */
static emlxs_buf_t *
{
/* Flags fct_cmd as inuse */
}
if (fct_state) {
}
return (cmd_sbp);
} /* emlxs_fct_cmd_init() */
/* Called after receiving fct_cmd from COMSTAR */
static fct_status_t
{
"emlxs_fct_cmd_accept: "
"Invalid fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_accept:2 "
"Invalid fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_accept: "
"Aborted fct_cmd found! fct_cmd=%p state=%x",
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_accept: "
"Busy fct_cmd found! fct_cmd=%p state=%x",
return (FCT_BUSY);
}
if (fct_state) {
}
return (FCT_SUCCESS);
} /* emlxs_fct_cmd_accept() */
/* Called after receiving fct_cmd from driver */
static fct_status_t
{
"emlxs_fct_cmd_acquire: "
"Bad fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_acquire: "
"Invalid fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_acquire: "
"Returned fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_acquire:2 "
"Bad fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_acquire:2 "
"Invalid fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_acquire:2 "
"Returned fct_cmd found! fct_cmd=%p state=%x",
return (FCT_NOT_FOUND);
}
"emlxs_fct_cmd_acquire: "
"Aborting cmd. fct_cmd=%p state=%x",
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_NOT_FOUND);
}
if (fct_state) {
}
return (FCT_SUCCESS);
} /* emlxs_fct_cmd_acquire() */
/* cmd_sbp->fct_mtx must be held to enter */
/* cmd_sbp->fct_mtx must be released before exiting */
/* Called before transitionally sending fct_cmd to driver */
/*ARGSUSED*/
static void
{
if (fct_state) {
}
return;
} /* emlxs_fct_cmd_release() */
/* cmd_sbp->fct_mtx must be held to enter */
/* cmd_sbp->fct_mtx must be released before exiting */
/* Called before posting fct_cmd back to COMSTAR */
/*ARGSUSED*/
static void
{
if (fct_state) {
}
if (pkt) {
}
return;
} /* emlxs_fct_cmd_post() */
/* cmd_sbp->fct_mtx must be held to enter */
/* Called before completing fct_cmd back to COMSTAR */
static void
{
/* Flags fct_cmd is no longer used */
"Pkt still registered! channel=%d iotag=%d sbp=%p",
} else {
}
}
}
if (fct_state) {
}
if (pkt) {
}
return;
} /* emlxs_fct_cmd_done() */
static void
{
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
#ifdef FMA_SUPPORT
#endif /* FMA_SUPPORT */
if (rval) {
"emlxs_fct_pkt_comp: "
"Unable to reacquire fct_cmd.");
return;
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
case FCT_CMD_FCP_XCHG:
/*
* The error indicates this IO should be terminated
* immediately.
*/
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_queue_cmd_for_termination:2 %p: x%x",
#endif /* FCT_API_TRACE */
break;
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_send_response_done:2 %p: x%x",
#else
"emlxs_fct_pkt_comp: fct_send_response_done. dbuf=%p",
#endif /* FCT_API_TRACE */
break;
case FCT_CMD_RCVD_ELS:
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_send_response_done:3 %p: x%x",
#endif /* FCT_API_TRACE */
break;
case FCT_CMD_SOL_ELS:
if (fct_els->els_resp_payload) {
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_send_cmd_done:1 %p: x%x",
#endif /* FCT_API_TRACE */
break;
case FCT_CMD_SOL_CT:
if (fct_ct->ct_resp_payload) {
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
#ifdef FCT_API_TRACE
"fct_send_cmd_done:2 %p: x%x",
#endif /* FCT_API_TRACE */
break;
default:
"emlxs_fct_pkt_comp: Invalid cmd type found. type=%x",
/* mutex_exit(&cmd_sbp->fct_mtx); */
break;
}
return;
} /* emlxs_fct_pkt_comp() */
static void
{
#ifdef FCT_API_TRACE_11
#endif /* FCT_API_TRACE */
return;
} /* emlxs_fct_abort_pkt_comp() */
/* COMSTAR ENTER POINT (INDIRECT) */
static fct_status_t
{
emlxs_port_t *port =
"emlxs_fct_send_els_cmd: Unable to allocate packet.");
return (FCT_BUSY);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
pkt->pkt_timeout =
"emlxs_fct_send_els_cmd: pkt_timeout=%d ratov=%d",
/* Build the fc header */
/* Copy the cmd payload */
/* mutex_exit(&cmd_sbp->fct_mtx); */
"emlxs_fct_send_els_cmd: Unable to send packet.");
/* Reacquire ownership of the fct_cmd */
if (rval) {
"emlxs_fct_send_els_cmd: "
"Unable to reacquire fct_cmd.");
return (rval);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_BUSY);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_els_cmd() */
/* cmd_sbp->fct_mtx must be held to enter */
/* cmd_sbp->fct_mtx must be released before exiting */
static fct_status_t
{
emlxs_port_t *port =
KM_NOSLEEP))) {
"emlxs_fct_send_els_rsp: Unable to allocate packet.");
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_FAILURE);
}
pkt->pkt_timeout =
/* Build the fc header */
/* Copy the resp payload to pkt_cmd buffer */
/* mutex_exit(&cmd_sbp->fct_mtx); */
"emlxs_fct_send_els_rsp: Unable to send packet.");
/* Reacquire ownership of the fct_cmd */
if (rval) {
"emlxs_fct_send_els_rsp: "
"Unable to reacquire fct_cmd.");
return (rval);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_FAILURE);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_els_rsp() */
/* COMSTAR ENTER POINT (INDIRECT) */
static fct_status_t
{
emlxs_port_t *port =
"emlxs_fct_send_ct_cmd: Unable to allocate packet.");
return (FCT_BUSY);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
pkt->pkt_timeout =
/* Build the fc header */
/* Copy the cmd payload */
/* mutex_exit(&cmd_sbp->fct_mtx); */
"emlxs_fct_send_ct_cmd: Unable to send packet.");
/* Reacquire ownership of the fct_cmd */
if (rval) {
"emlxs_fct_send_ct_cmd: "
"Unable to reacquire fct_cmd.");
return (rval);
}
/* mutex_enter(&cmd_sbp->fct_mtx); */
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_BUSY);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_ct_cmd() */
/* cmd_sbp->fct_mtx must be held to enter */
{
/* Check the transmit queue */
/* The IOCB could point to a cmd_sbp (no packet) or a sbp (packet) */
if (pkt) {
goto done;
}
} else {
}
if (pkt_flags & PACKET_IN_TXQ) {
/* 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) {
goto done;
}
/* Check if node still needs servicing */
/*
* If this is the base node, don't shift the pointers
*/
/* We want to drain the base node before moving on */
/* Shift channel queue pointers to next node */
}
} else {
/* Remove node from channel queue */
/* If this is the last node on list */
} else {
/* Remove node from head */
}
/* Clear node */
}
/* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */
} else {
}
if (pkt) {
}
return (1);
}
done:
return (0);
} /* emlxs_fct_pkt_abort_txq() */
/* COMSTAR ENTER POINT */
/* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */
/* FCT_SUCCESS indicates abort will occur asyncronously */
static fct_status_t
{
top:
/* Sanity check */
"emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd);
return (FCT_NOT_FOUND);
}
"emlxs_fct_abort: Pkt invalid. cmd_sbp=%p",
cmd_sbp);
return (FCT_NOT_FOUND);
}
if (mutex_tryenter(fct_mtx) == 0) {
/*
* This code path handles a race condition if
* an IO completes, in emlxs_fct_handle_fcp_event(),
* and we get an abort at the same time.
*/
goto top;
}
/* At this point, we have entered the mutex */
/* Sanity check */
"emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd);
return (FCT_NOT_FOUND);
}
"emlxs_fct_abort: Pkt invalid. cmd_sbp=%p",
cmd_sbp);
return (FCT_NOT_FOUND);
}
"emlxs_fct_abort: HbaLink %d. "
"xid=%x. cmd_sbp=%p state=%d flags=%x,%x,%x",
/* If Abort is already in progress */
return (FCT_SUCCESS);
}
if (flags & FCT_IOF_FORCE_FCA_DONE) {
fct_cmd->cmd_handle = 0;
}
/* These are currently owned by COMSTAR. */
/* They were last processed by emlxs_fct_cmd_post() */
case EMLXS_FCT_CMD_POSTED:
case EMLXS_FCT_OWNED:
goto abort_it_now;
/* These are on the unsol waitQ in the driver */
case EMLXS_FCT_CMD_WAITQ:
/* Find and remove it */
while (cmd_sbp2) {
/* Remove it */
if (prev) {
}
}
}
break;
}
}
goto abort_it_now;
/* These are active in the driver */
/* They were last processed by emlxs_fct_cmd_release() */
case EMLXS_FCT_RSP_PENDING:
case EMLXS_FCT_REQ_PENDING:
case EMLXS_FCT_REG_PENDING:
case EMLXS_FCT_DATA_PENDING:
case EMLXS_FCT_STATUS_PENDING:
/* Abort anything pending */
}
goto abort_it_now;
}
/* If we're not online, then all IO will be flushed anyway */
"emlxs_fct_abort: Not online. fct_cmd=%p.",
fct_cmd);
/* mutex_exit(&cmd_sbp->fct_mtx); */
/* The cmd will be aborted on the */
/* next emlxs_fct_cmd_acquire */
/* because EMLXS_FCT_ABORT_INP is set. */
break;
}
/* Try to send abort request */
"emlxs_fct_abort: Unable to allocate packet. "
"fct_cmd=%p",
fct_cmd);
/* mutex_exit(&cmd_sbp->fct_mtx); */
/* The cmd will be aborted on the */
/* next emlxs_fct_cmd_acquire anyway */
/* because EMLXS_FCT_ABORT_INP is set. */
break;
}
pkt->pkt_timeout =
/* Build the fc header */
/* Now disassociate the sbp / pkt from the fct_cmd */
"emlxs_fct_abort: ABORT: %p xri x%x",
} else {
"emlxs_fct_abort: CLOSE: %p xri x%x",
}
/* mutex_exit(&cmd_sbp->fct_mtx); */
"emlxs_fct_abort: Unable to send abort packet.");
/* The cmd will be aborted on the */
/* next emlxs_fct_cmd_acquire anyway */
/* because EMLXS_FCT_ABORT_INP is set. */
}
break;
default:
"emlxs_fct_abort: Unexpected fct_state. "
"fct_cmd=%p state=%x",
/* mutex_exit(&cmd_sbp->fct_mtx); */
/* The cmd will be aborted on the */
/* next emlxs_fct_cmd_acquire anyway */
/* because EMLXS_FCT_ABORT_INP is set. */
} /* switch */
return (FCT_SUCCESS);
/* mutex_exit(&cmd_sbp->fct_mtx); */
return (FCT_ABORT_SUCCESS);
} /* emlxs_fct_abort() */
extern void
{
"emlxs_fct_link_up event.");
#ifdef FCT_API_TRACE
"fct_handle_event LINK_UP");
#endif /* FCT_API_TRACE */
0, 0);
} else {
/* Take link down and hold it down */
} else {
}
}
return;
} /* emlxs_fct_link_up() */
extern void
{
"emlxs_fct_link_down event.");
#ifdef FCT_API_TRACE
"fct_handle_event LINK_DOWN");
#endif /* FCT_API_TRACE */
0, 0);
} else {
}
return;
} /* emlxs_fct_link_down() */
/* DMA FUNCTIONS */
{
int32_t j;
int32_t i;
char buf[64];
p = port->dmem_bucket;
for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
if (!p->dmem_nbufs) {
continue;
}
sizeof (emlxs_fct_dmem_bctl_t), KM_NOSLEEP);
"emlxs_fct_dmem_init: Unable to allocate bctl.");
goto alloc_bctl_failed;
}
p->dmem_bctls_mem = bctl;
"emlxs_fct_dmem_init: Unable to allocate handle.");
goto alloc_handle_failed;
}
&p->dmem_acc_handle) != DDI_SUCCESS) {
"emlxs_fct_dmem_init: Unable to allocate memory.");
goto mem_alloc_failed;
}
"emlxs_fct_dmem_init: Unable to bind handle.");
goto addr_bind_handle_failed;
}
if (ncookie != 1) {
"emlxs_fct_dmem_init: DMEM init failed.");
goto dmem_init_failed;
}
p->dmem_host_addr = addr;
p->dmem_dev_addr = dev_addr;
p->dmem_bctl_free_list = bctl;
p->dmem_nbufs_free = p->dmem_nbufs;
bsize = p->dmem_buf_size;
for (j = 0; j < p->dmem_nbufs; j++) {
#ifdef FCT_API_TRACE
"stmf_alloc data_buf %p", db);
#endif /* FCT_API_TRACE */
"emlxs_fct_dmem_init: alloc failed.");
goto dmem_init_failed;
}
bctl->bctl_bucket = p;
bctl++;
}
}
return (FCT_SUCCESS);
mutex_destroy(&p->dmem_lock);
while (bc) {
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
(void) ddi_dma_mem_free(&p->dmem_acc_handle);
(void) ddi_dma_free_handle(&p->dmem_dma_handle);
p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t));
if (--i >= 0) {
p = &port->dmem_bucket[i];
bctl = p->dmem_bctl_free_list;
goto dmem_failure_loop;
}
return (FCT_FAILURE);
} /* emlxs_fct_dmem_init() */
void
{
uint32_t i;
p = port->dmem_bucket;
for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
if (!p->dmem_nbufs) {
continue;
}
bctl = p->dmem_bctl_free_list;
while (bctl) {
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
bctl = p->dmem_bctl_free_list;
(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
(void) ddi_dma_mem_free(&p->dmem_acc_handle);
(void) ddi_dma_free_handle(&p->dmem_dma_handle);
(p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t)));
mutex_destroy(&p->dmem_lock);
}
return;
} /* emlxs_fct_dmem_fini() */
/* COMSTAR ENTER POINT */
/* ARGSUSED */
static stmf_data_buf_t *
{
uint32_t i;
if (size > FCT_DMEM_MAX_BUF_SIZE) {
}
p = port->dmem_bucket;
for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) {
if (!p->dmem_nbufs) {
continue;
}
if (p->dmem_buf_size >= size) {
mutex_enter(&p->dmem_lock);
if (p->dmem_nbufs_free) {
if (p->dmem_buf_size < *pminsize) {
*pminsize = p->dmem_buf_size;
"emlxs_fct_dbuf_alloc: Failed(1).");
mutex_exit(&p->dmem_lock);
return (NULL);
}
bctl = p->dmem_bctl_free_list;
mutex_exit(&p->dmem_lock);
continue;
}
p->dmem_nbufs_free--;
mutex_exit(&p->dmem_lock);
#ifdef FCT_API_TRACE
"emlx_fct_buf_alloc: bctl_buf %p: size %d",
#endif /* FCT_API_TRACE */
}
mutex_exit(&p->dmem_lock);
"emlx_fct_buf_alloc size %d Nothing free bck %d",
size, i);
}
}
*pminsize = 0;
"emlxs_fct_dbuf_alloc: Failed(2).");
return (NULL);
} /* emlxs_fct_dbuf_alloc() */
/* COMSTAR ENTER POINT */
/*ARGSUSED*/
static void
{
#ifdef FCT_API_TRACE_1
"emlx_fct_buf_free %p", dbuf);
#endif /* FCT_API_TRACE */
mutex_enter(&p->dmem_lock);
p->dmem_bctl_free_list = bctl;
p->dmem_nbufs_free++;
mutex_exit(&p->dmem_lock);
} /* emlxs_fct_dbuf_free() */
static void
{
(void) ddi_dma_sync(p->dmem_dma_handle,
} /* emlxs_fct_dbuf_dma_sync() */
#endif /* SFCT_SUPPORT */