emlxs_fct.c revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
/*
* 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 2008 Emulex. All rights reserved.
* Use is subject to License terms.
*/
#include "emlxs.h"
#ifdef SFCT_SUPPORT
/* #define FCT_API_TRACE Extra debug */
/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
#ifndef PORT_SPEED_10G
#define PORT_SPEED_10G 0x10
#endif /* PORT_SPEED_10G */
struct fct_flogi_xchg *fx);
fc_packet_t *pkt);
#ifdef MODSYM_SUPPORT
static int
{
int err;
if (emlxs_modsym.mod_fct) {
return (1);
}
/* 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 */
emlxs_modsym.fct_scsi_task_alloc = (void *(*) ())
goto failed;
}
err = 0;
/* Check if the fct fct_register_local_port is present */
emlxs_modsym.fct_register_local_port = (int (*) ())
goto failed;
}
err = 0;
/* Check if the fct fct_deregister_local_port is present */
emlxs_modsym.fct_deregister_local_port = (void (*) ())
goto failed;
}
err = 0;
/* Check if the fct fct_handle_event is present */
emlxs_modsym.fct_handle_event = (void (*) ())
"?%s: drv/fct: fct_handle_event not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fct fct_post_rcvd_cmd is present */
emlxs_modsym.fct_post_rcvd_cmd = (void (*) ())
"?%s: drv/fct: fct_post_rcvd_cmd not present", DRIVER_NAME);
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_send_response_done is present */
emlxs_modsym.fct_send_response_done = (void (*) ())
goto failed;
}
err = 0;
/* Check if the fct fct_send_cmd_done is present */
emlxs_modsym.fct_send_cmd_done = (void (*) ())
"?%s: drv/fct: fct_send_cmd_done not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fct fct_scsi_xfer_data_done is present */
emlxs_modsym.fct_scsi_data_xfer_done = (void (*) ())
goto failed;
}
err = 0;
/* Check if the fct fct_port_shutdown is present */
"?%s: drv/fct: fct_port_shutdown not present", DRIVER_NAME);
goto failed;
}
err = 0;
/* Check if the fct fct_port_initialize is present */
goto failed;
}
err = 0;
/* Check if the fct fct_handle_rcvd_flogi is present */
goto failed;
}
/* Comstar (stmf) */
err = 0;
/* Check if the stmf stmf_alloc is present */
emlxs_modsym.stmf_alloc = (void *(*) ())
"?%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 (1);
return (0);
} /* emlxs_fct_modopen() */
extern void
{
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 */
extern void
{
/* mutex_exit(&cmd_sbp->mtx); */
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
}
/* Online & Link up */
} else {
#ifdef FCT_API_TRACE
"fct_post_rcvd_cmd:1 %p: portid x%x",
#endif /* FCT_API_TRACE */
}
} else { /* Online & Link down */
/* Add buffer to queue tail */
if (port->fct_wait_tail) {
}
if (!port->fct_wait_head) {
}
}
return;
} /* emlxs_fct_unsol_callback() */
/* This is called at port online and offline */
static void
{
return;
}
/* Return if nothing to do */
if (!port->fct_wait_head) {
return;
}
while (cmd_sbp) {
"Completing fct_cmd: %p", fct_cmd);
} else {
#ifdef FCT_API_TRACE
"fct_post_rcvd_cmd:2 %p: portid x%x",
#endif /* FCT_API_TRACE */
}
} else { /* Drop the cmd */
/* mutex_exit(&cmd_sbp->mtx); */
#ifdef FCT_API_TRACE
"fct_free:2 %p", 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;
for (i = 0; i < cnt; i++) {
if (datap == 0)
break;
datap++;
datap++;
datap++;
datap++;
/* Check for a bad entry */
"Bad fct-bufpool entry %d %d",
}
if (i >= FCT_MAX_BUCKETS)
break;
}
}
static void
{
char **arrayp;
char buf[32];
int status;
cnt = 0;
} else {
} else {
sizeof (port->dmem_bucket));
}
}
cnt = 0;
(DDI_PROP_DONTPASS), buf, 0);
(DDI_PROP_DONTPASS), "fct-queue-depth", 0);
if (cnt == DDI_PROP_NOT_FOUND) {
cnt = 64;
}
}
return;
} /* emlxs_fct_cfg_init() */
extern void
{
uint32_t i;
return;
}
#ifdef MODSYM_SUPPORT
/* Open COMSTAR */
(void) emlxs_fct_modopen();
#endif /* MODSYM_SUPPORT */
/* Check if COMSTAR is present */
"Comstar not present. Target mode disabled.");
goto failed;
}
"Comstar present. Target mode enabled.");
#ifdef NPIV_SUPPORT
"enable-npiv: Not supported in target mode. Disabling.");
/* Temporary patch to disable npiv */
}
#endif /* NPIV_SUPPORT */
#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++) {
}
} /* 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;
}
}
}
return;
} /* emlxs_fct_detach() */
extern void
{
char node_name[32];
return;
}
return;
}
/* Destroy & flush all port nodes, if they exist */
if (port->node_count) {
}
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
#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 "
"fct 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 "
"fct port provider.");
goto failed;
}
flag |= 0x00000004;
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
"emlxs_fct_bind_port: Unable to allocate fct port.");
goto failed;
}
flag |= 0x00000008;
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
"emlxs_fct_bind_port: Unable to allocate dbuf store.");
goto failed;
}
flag |= 0x00000010;
"Unable to create SFCT device node.");
goto failed;
}
flag |= 0x00000020;
/* Intialize */
< hba->io_throttle)) {
} 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
#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() */
static void
{
}
}
}
}
}
"Port attr: model_description = %s",
"Port attr: option_rom_version = %s",
"Port attr: vendor_specific_id = 0x%x",
"Port attr: supported_speed = 0x%x",
return;
} /* emlxs_populate_hba_details() */
/* 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 */
(void) emlxs_reset_link(hba, 0);
"STATE: OFFLINE");
}
break;
"STATE: OFFLINE ack");
break;
"STATE: ONLINE ack");
break;
}
return;
} /* emlxs_fct_ctl() */
extern int
{
int i;
if (!fct_port) {
return (0);
}
"fct_port_shutdown");
"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);
}
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() */
static fct_status_t
{
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
case FCT_CMD_FCP_XCHG:
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
goto failure;
}
return (emlxs_fct_send_fcp_status(fct_cmd));
case FCT_CMD_RCVD_ELS:
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
goto failure;
}
return (emlxs_fct_send_els_rsp(fct_cmd));
case FCT_CMD_RCVD_ABTS:
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
fct_cmd->cmd_handle = 0;
}
return (emlxs_fct_send_abts_rsp(fct_cmd));
default:
if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
fct_cmd->cmd_handle = 0;
}
"emlxs_fct_send_cmd_rsp: Invalid cmd type found. type=%x",
return (FCT_FAILURE);
}
"emlxs_fct_send_cmd_rsp: Unable to handle FCT_IOF_FORCE_FCA_DONE. "
return (FCT_FAILURE);
} /* emlxs_fct_send_cmd_rsp() */
static fct_status_t
{
#ifdef FCT_API_TRACE
"emlxs_flogi_xchg: Sending FLOGI: %p", fct_port);
#else
"emlxs_flogi_xchg: Sending FLOGI.");
#endif /* FCT_API_TRACE */
"emlxs_flogi_xchg: FLOGI failed. Link down.");
return (FCT_FAILURE);
}
"emlxs_flogi_xchg: FLOGI failed. Unable allocate packet.");
return (FCT_FAILURE);
}
/* Make this a polled IO */
/* Build the fc header */
/* Build the command */
/*
* Service paramters will be added automatically later by the driver
* (See emlxs_send_els())
*/
"emlxs_flogi_xchg: FLOGI failed. Unable to send packet.");
return (FCT_FAILURE);
}
return (FCT_TIMEOUT);
return (FCT_NOT_FOUND);
}
"emlxs_flogi_xchg: FLOGI failed. state=%x reason=%x",
return (FCT_FAILURE);
}
} else { /* FC_PKT_SUCCESS */
}
return (FCT_SUCCESS);
} /* emlxs_flogi_xchg() */
/* 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() */
static fct_status_t
{
#ifdef FCT_API_TRACE
"emlxs_fct_register_remote_port %p", fct_port);
#endif /* FCT_API_TRACE */
/* mutex_enter(&cmd_sbp->mtx); */
} else {
}
}
/* Check for unsolicited PLOGI */
} 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
*/
iptr[0] =
iptr[1] =
iptr[0] =
iptr[1] =
}
"emlxs_fct_register_remote_port: Registering did=%x. "
fct_cmd);
/* Create a new node */
"emlxs_fct_register_remote_port: Reg login failed. "
goto done;
}
/* Wait for completion */
pkt_ret = 0;
while ((pkt_ret != -1) &&
}
}
done:
if (ndlp) {
"emlxs_fct_register_remote_port: did=%x hdl=%x",
return (FCT_SUCCESS);
} else {
"emlxs_fct_register_remote_port: failed. did=%x hdl=%x",
return (FCT_FAILURE);
}
} /* emlxs_fct_register_remote_port() */
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 */
}
#ifdef FCT_API_TRACE
"fct_scsi_task_alloc %p: FCP rcvd: cmd=%x sid=%x rxid=%x "
#endif /* FCT_API_TRACE */
"FCP rcvd: sid=%x xid=%x. Unable to allocate scsi task. "
goto dropped;
}
/* Initialize fct_cmd */
/* Initialize cmd_sbp */
/* mutex_enter(&cmd_sbp->mtx); */
/*
* bcopy((uint8_t*)iocb, (uint8_t*)&cmd_sbp->iocbq,
* sizeof(emlxs_iocb_t));
*/
/* Set task_flags */
case 0:
break;
case 1:
break;
case 2:
break;
case 4:
break;
case 5:
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;
return (0);
return (1);
} /* emlxs_fct_handle_unsol_req() */
/* ARGSUSED */
static fct_status_t
{
emlxs_port_t *port =
/* Initialize cmd_sbp */
/*
* This check is here because task_max_nbufs is set to 1. This
* ensures we will only have 1 outstanding call to this routine.
*/
"Adapter Busy. Processing IO. did=0x%x", did);
return (FCT_BUSY);
}
} else {
timeout = 0x80000000;
}
#ifdef FCT_API_TRACE
"emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d",
#endif /* FCT_API_TRACE */
/* Get the iotag by registering the packet */
if (!iotag) {
/* No more command slots available, retry later */
"Adapter Busy. Unable to allocate iotag. did=0x%x", did);
return (FCT_BUSY);
}
/* Unregister the packet */
"Adapter Busy. Unable to setup buffer list. did=%x", did);
return (FCT_BUSY);
}
/* Point of no return */
}
/* Initalize iocbq */
/* Initalize iocb */
} else { /* TF_READ_DATA */
}
#if 0
"FCT reply: icmd=%x did=%x oxid=%x rxid=%x sbp=%p",
cmd_sbp);
#endif
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_fcp_data() */
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.");
return (FCT_FAILURE);
}
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 a residual is reported on non-SCSI_GOOD READ
* status
*/
}
}
if (fct_task->task_sense_length) {
}
"emlxs_fct_send_fcp_status: Unable to send packet.");
}
return (FCT_FAILURE);
}
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 */
return (1);
}
#ifdef FCT_API_TRACE
"emlxs_fct_handle_fcp_event: %p: cmd=%x status=%x",
#endif /* FCT_API_TRACE */
}
return (0);
}
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:
/* Wake up sleeping thread */
break;
}
if (status == 0) {
}
fct_task->task_scsi_status = 0;
(void) emlxs_fct_send_fcp_status(fct_cmd);
break;
}
}
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
break;
/* FCP Status completion */
case CMD_FCP_TRSP_CX:
case CMD_FCP_TRSP64_CX:
/* Wake up sleeping thread */
/* mutex_exit(&cmd_sbp->mtx); */
#ifdef FCT_API_TRACE
"fct_scsi_data_xfer_done:2 %p %p",
#endif /* FCT_API_TRACE */
} else {
/* mutex_exit(&cmd_sbp->mtx); */
#ifdef FCT_API_TRACE
"fct_send_response_done:1 %p: x%x",
#endif /* FCT_API_TRACE */
}
break;
default:
return (1);
} /* switch(iocb->ulpCommand) */
if (status == IOSTAT_SUCCESS) {
} else {
}
return (0);
} /* emlxs_fct_handle_fcp_event() */
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:
break;
case ELS_CMD_PLOGI:
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 */
/* Initialize cmd_sbp */
/* mutex_enter(&cmd_sbp->mtx); */
sizeof (emlxs_iocb_t));
if (cmd_code == ELS_CMD_FLOGI) {
}
done:
return (0);
} /* emlxs_fct_handle_unsol_els() */
static void
{
/* Init the xchg object */
#ifdef FCT_API_TRACE
#endif /* FCT_API_TRACE */
if (status == FCT_SUCCESS) {
ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0);
} else { /* ELS_OP_LSRJT */
}
} else {
"FLOGI: sid=%x. fct_handle_rcvd_flogi failed. Rejecting.",
}
/* mutex_exit(&cmd_sbp->mtx); */
#ifdef FCT_API_TRACE
"fct_free:7 %p", fct_cmd);
#endif /* FCT_API_TRACE */
return;
} /* emlxs_fct_handle_rcvd_flogi() */
/* 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 *
{
return (cmd_sbp);
} /* emlxs_fct_cmd_init() */
/* Mutex must be held */
static int
{
return (FC_FAILURE);
}
"Pkt still registered! ringo=%d iotag=%d sbp=%p",
}
}
return (FC_SUCCESS);
} /* emlxs_fct_cmd_uninit() */
static void
{
/* Wake up sleeping thread */
goto done;
}
case FCT_CMD_FCP_XCHG:
/* mutex_exit(&cmd_sbp->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->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->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->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->mtx); */
}
done:
return;
} /* emlxs_fct_pkt_comp() */
static fct_status_t
{
emlxs_port_t *port =
#if 0
"emlxs_fct_send_els_cmd() called.");
#endif
"emlxs_fct_send_els_cmd: Unable to allocate packet.");
return (FCT_FAILURE);
}
/* mutex_enter(&cmd_sbp->mtx); */
pkt->pkt_timeout =
"emlxs_fct_send_els_cmd: pkt_timeout=%d ratov=%d",
/* Build the fc header */
/* Copy the cmd payload */
"emlxs_fct_send_els_cmd: Unable to send packet.");
}
return (FCT_FAILURE);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_els_cmd() */
static fct_status_t
{
emlxs_port_t *port =
"emlxs_fct_send_abts_rsp: cmd=%p", fct_cmd);
/* Create the abort IOCB */
"emlxs_fct_send_abts_rsp: Aborting xid=%x. sbp=%p "
} else {
"emlxs_fct_send_abts_rsp: Closing xid=%x. sbp=%p state=%d "
}
/* mutex_exit(&cmd_sbp->mtx); */
#ifdef FCT_API_TRACE
"fct_send_response_done:4 %p: x%x",
#endif /* FCT_API_TRACE */
return (FCT_SUCCESS);
} /* emlxs_fct_send_abts_rsp() */
static fct_status_t
{
emlxs_port_t *port =
#if 0
"emlxs_fct_send_els_rsp: cmd=%p", fct_cmd);
#endif
if (!(pkt =
"emlxs_fct_send_els_rsp: Unable to allocate packet.");
return (FCT_FAILURE);
}
pkt->pkt_timeout =
/* Build the fc header */
/* Copy the resp payload to pkt_cmd buffer */
"emlxs_fct_send_els_rsp: Unable to send packet.");
}
return (FCT_FAILURE);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_els_rsp() */
static fct_status_t
{
emlxs_port_t *port =
#if 0
"emlxs_fct_send_ct_cmd() called.");
#endif
"emlxs_fct_send_ct_cmd: Unable to allocate packet.");
return (FCT_FAILURE);
}
/* mutex_enter(&cmd_sbp->mtx); */
pkt->pkt_timeout =
/* Build the fc header */
/* Copy the cmd payload */
"emlxs_fct_send_ct_cmd: Unable to send packet.");
}
return (FCT_FAILURE);
}
return (FCT_SUCCESS);
} /* emlxs_fct_send_ct_cmd() */
/* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */
/* FCT_SUCCESS indicates abort will occur asyncronously */
static fct_status_t
{
"emlxs_fct_abort: Invalid cmd_sbp=%p.", cmd_sbp);
return (FCT_NOT_FOUND);
}
"emlxs_fct_abort: Invalid cmd_sbp=%p.", cmd_sbp);
return (FCT_NOT_FOUND);
}
if (flags & FCT_IOF_FORCE_FCA_DONE) {
fct_cmd->cmd_handle = 0;
}
case 0:
case EMLXS_FCT_REQ_CREATED:
case EMLXS_FCT_REG_PENDING:
case EMLXS_FCT_REG_COMPLETE:
case EMLXS_FCT_REQ_COMPLETE:
case EMLXS_FCT_DATA_COMPLETE:
case EMLXS_FCT_RSP_COMPLETE:
"emlxs_fct_abort: Aborted. cmd_sbp=%p state=%d "
/* mutex_exit(&cmd_sbp->mtx); */
return (FCT_ABORT_SUCCESS);
case EMLXS_FCT_CMD_RECEIVED:
/* Create the abort IOCB */
"emlxs_fct_abort: Aborted. xid=%x. cmd_sbp=%p "
} else {
"emlxs_fct_abort: Closed. xid=%x. cmd_sbp=%p "
}
/* mutex_exit(&cmd_sbp->mtx); */
return (FCT_ABORT_SUCCESS);
case EMLXS_FCT_REQ_PENDING:
case EMLXS_FCT_STATUS_PENDING:
case EMLXS_FCT_RSP_PENDING:
"emlxs_fct_abort: Aborted. cmd_sbp=%p state=%d "
/* mutex_exit(&cmd_sbp->mtx); */
}
return (FCT_ABORT_SUCCESS);
case EMLXS_FCT_DATA_PENDING:
PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
"emlxs_fct_abort: Completing. cmd_sbp=%p state=%d "
return (FCT_NOT_FOUND);
}
if (rval == FCT_ABORT_SUCCESS) {
"emlxs_fct_abort: Aborted. cmd_sbp=%p state=%d "
/* mutex_exit(&cmd_sbp->mtx); */
}
} else {
"emlxs_fct_abort: Not found. cmd_sbp=%p state=%d "
}
return (rval);
} /* switch */
return (FCT_SUCCESS);
} /* emlxs_fct_abort() */
/* Returns FCT_ABORT_SUCCESS or FCT_NOT_FOUND */
static fct_status_t
{
/* Check packet */
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 1. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
return (FCT_NOT_FOUND);
}
/* Check again if we still own this */
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 2. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
return (FCT_NOT_FOUND);
}
/* Check again if we still own this */
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 3. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
goto done;
}
pass++;
/* Check the transmit queue */
/* Find it on the queue */
found = 0;
/* Search the priority queue */
while (next) {
/* Remove it */
if (prev) {
}
(void *)iocbq) {
(void *)prev;
}
(void *)iocbq) {
}
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) {
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 4. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
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 ring queue pointers to next
* node
*/
}
} else {
/* Remove node from ring queue */
/* If this is the last node on list */
} else {
/* Remove node from head */
}
/* Clear node */
}
}
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 5. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
/* Now complete it */
}
goto done;
}
/* Check the chip queue */
/* Create the abort IOCB */
"emlxs_fct_pkt_abort: Aborting. sbp=%p "
sbp->abort_attempts++;
} else {
"emlxs_fct_pkt_abort: Closing. sbp=%p flags=%x,%x",
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))) {
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 9. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
goto done;
}
/* Apparently the pkt was not found. Let's delay and try again */
if (pass < 5) {
/* Check packet */
PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) {
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 10. sbp=%p flags=%x,%x",
* sbp, cmd_sbp->fct_flags, sbp->pkt_flags);
*/
goto done;
}
goto begin;
}
/* Force the completion now */
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 11. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
/* Unregister the pkt */
/* Now complete it */
}
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) &&
}
}
/*
* Check if timeout occured. This is not good. Something
* happened to our IO.
*/
/* Force the completion now */
goto force_it;
}
}
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_pkt_abort: 12. sbp=%p flags=%x,%x", sbp,
* cmd_sbp->fct_flags, sbp->pkt_flags);
*/
return (FCT_ABORT_SUCCESS);
} /* emlxs_fct_pkt_abort() */
static uint32_t
{
struct stmf_sglist_ent *sgl;
sgl++;
}
if (resid > 0) {
"emlxs_fct_bde_setup: Not enough scatter gather buffers "
return (1);
}
#ifdef SLI3_SUPPORT
} else {
}
#else /* !SLI3_SUPPORT */
#endif /* SLI3_SUPPORT */
return (rval);
} /* emlxs_fct_bde_setup() */
/* Only used for FCP Data xfers */
static uint32_t
{
struct stmf_sglist_ent *sgl;
iocb->ulpBdeCount = 0;
return (0);
}
#ifdef EMLXS_SPARC
/* Use FCP MEM_BPL table to get BPL buffer */
#else
/* Use MEM_BPL pool to get BPL buffer */
#endif /* EMLXS_SPARC */
if (!bmp) {
"emlxs_fct_sli2_bde_setup: Unable to BPL buffer. iotag=%x",
iocb->ulpBdeCount = 0;
return (1);
}
/* size = fct_task->task_cmd_xfer_length; */
/* Init the buffer list */
bpl++;
sgl++;
}
/* Init the IOCB */
return (0);
} /* emlxs_fct_sli2_bde_setup */
#ifdef SLI3_SUPPORT
/* ARGSUSED */
static uint32_t
{
struct stmf_sglist_ent *sgl;
iocb->ulpBdeCount = 0;
return (0);
}
/* Init first BDE */
sgl++;
/* Init remaining BDE's */
bde++;
sgl++;
}
iocb->ulpBdeCount = 0;
return (0);
} /* emlxs_fct_sli3_bde_setup */
#endif /* SLI3_SUPPORT */
extern void
{
"emlxs_fct_link_up event.");
#ifdef FCT_API_TRACE
"fct_handle_event LINK_UP");
#endif /* FCT_API_TRACE */
FCT_EVENT_LINK_UP, 0, 0);
} else {
/* Take link down and hold it down */
(void) emlxs_reset_link(hba, 0);
} 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 */
FCT_EVENT_LINK_DOWN, 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;
}
"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: 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() */
/* ARGSUSED */
static stmf_data_buf_t *
{
uint32_t i;
/*
* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
* "emlxs_fct_dbuf_alloc: size=%d min=%d", size, *pminsize);
*/
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 size %p: %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() */
/* ARGSUSED */
static void
{
#ifdef FCT_API_TRACE
"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() */
void
{
(void) ddi_dma_sync(p->dmem_dma_handle,
} /* emlxs_fct_dbuf_dma_sync() */
#endif /* SFCT_SUPPORT */