/*
* 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
*/
/*
*/
/*
* The following notice accompanied the original version of this file:
*
* BSD LICENSE
*
* Copyright(c) 2007 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Driver kernel header files
*/
#include <sys/byteorder.h>
#include <sys/ethernet.h>
/*
* COMSTAR header files
*/
#include <sys/stmf_defines.h>
#include <sys/fct_defines.h>
/*
* FCoE header files
*/
/*
* Driver's own header files
*/
#include "fcoet.h"
#include "fcoet_eth.h"
#include "fcoet_fc.h"
/*
* static function forward declaration
*/
static void fcoet_watchdog(void *arg);
static uint_t
static uint_t
/*
* Driver identificaton stuff
*/
0,
};
0,
NULL,
};
};
};
/*
* Driver's global variables
*/
/*
* Common loadable module entry points _init, _fini, _info
*/
int
_init(void)
{
int ret;
if (ret == 0) {
fcoet_pp = (stmf_port_provider_t *)
stmf_alloc(STMF_STRUCT_PORT_PROVIDER, 0, 0);
return (EIO);
}
if (ret) {
(void) stmf_deregister_port_provider(fcoet_pp);
}
}
return (ret);
}
int
_fini(void)
{
int ret;
if (ret == 0) {
(void) stmf_deregister_port_provider(fcoet_pp);
}
return (ret);
}
int
{
}
/*
* Autoconfiguration entry points: attach, detach, getinfo
*/
static int
{
int instance;
switch (cmd) {
case DDI_ATTACH:
if (ret != DDI_SUCCESS) {
return (ret);
}
if (ret != FCOE_SUCCESS) {
ret = DDI_FAILURE;
}
break;
case DDI_RESUME:
ret = DDI_SUCCESS;
break;
default:
break;
}
return (ret);
}
static int
{
int fcoe_ret;
int instance;
return (ret);
}
switch (cmd) {
case DDI_DETACH:
if (fcoe_ret == FCOE_SUCCESS) {
ret = DDI_SUCCESS;
}
fcoe_ret);
break;
case DDI_SUSPEND:
ret = DDI_SUCCESS;
break;
default:
break;
}
return (ret);
}
/*
* Device access entry points
*/
static int
{
int instance;
return (EINVAL);
}
/*
* Since this is for debugging only, only allow root to issue ioctl now
*/
return (EPERM);
}
return (ENXIO);
}
/*
* It is already open for exclusive access.
* So shut the door on this caller.
*/
return (EBUSY);
}
/*
* Exclusive operation not possible
* as it is already opened
*/
return (EBUSY);
}
}
return (0);
}
/* ARGSUSED */
static int
{
int instance;
return (EINVAL);
}
return (ENXIO);
}
return (ENODEV);
}
/*
* It looks there's one hole here, maybe there could several concurrent
* shareed open session, but we never check this case.
* But it will not hurt too much, disregard it now.
*/
return (0);
}
/* ARGSUSED */
static int
{
int ret = 0;
return (EPERM);
}
return (ENXIO);
}
switch (cmd) {
default:
break;
}
return (ret);
}
static fct_status_t
{
int ret;
/*
* FCoE (fcoe is fcoet's dependent driver)
* First we need register fcoet to FCoE as one client
*/
if (ret == -1) {
return (DDI_FAILURE);
} else {
}
/*
* It's FCoE's responsiblity to initialize eport's all elements
*/
goto fail_register_client;
}
/*
* Now it's time to register local port to FCT
*/
goto fail_init_dbuf;
}
goto fail_alloc_dbuf;
} else {
}
goto fail_alloc_port;
} else {
/*
* Do ss's initialization now
*/
ss->ss_instance);
if (ret != DDI_SUCCESS) {
goto fail_minor_node;
}
ss->ss_rportid_in_dereg = 0;
ss->ss_rport_dereg_state = 0;
"ss_sol_oxid_hash", FCOET_SOL_HASH_SIZE,
"ss_unsol_rxid_hash", FCOET_SOL_HASH_SIZE,
ss->ss_watch_count = 0;
ss->ss_ioctl_flags = 0;
ss->ss_change_state_flags = 0;
}
/*
* Do port's initialization
*
* port_fct_private and port_lport have been initialized by fct_alloc
*/
port->port_hard_address = 0;
port->port_fca_rp_private_size = 0;
goto fail_register_port;
}
/*
* Start watchdog thread
*/
goto fail_create_taskq;
}
delay(10);
}
return (DDI_SUCCESS);
delay(10);
}
}
return (DDI_FAILURE);
}
static fct_status_t
{
ss->ss_state_not_acked) {
return (FCOE_FAILURE);
}
/*
* Avoid modunload before running fcinfo remove-target-port
*/
return (FCOE_FAILURE);
}
return (FCOE_SUCCESS);
}
return (FCOE_FAILURE);
}
/*
* We need offline the port manually, before we want to detach it
* or it will not succeed.
*/
FCOET_LOG("fcoet_detach_uninit",
"fct_deregister_local_port failed");
return (FCOE_FAILURE);
}
/*
* Stop watchdog
*/
delay(10);
}
}
/*
* Release all resources
*/
}
return (FCOE_SUCCESS);
}
static void
{
ss->ss_watch_count++;
}
/* xchg abort done */
if (xchg->xch_dbuf_num) {
xchg->xch_dbuf_num *
sizeof (void *));
xchg->xch_dbuf_num = 0;
}
}
}
}
/*
* Ensure no ongoing FLOGI, before terminate the watchdog
*/
if (ss->ss_sol_flogi) {
}
}
static void
{
}
switch (ss->ss_sol_flogi_state) {
case SFS_WAIT_LINKUP:
if (ss->ss_sol_flogi) {
}
}
break;
case SFS_FLOGI_INIT:
if (ss->ss_sol_flogi) {
/*
* wait for the response to finish
*/
break;
}
ss->ss_sol_flogi_state++;
break;
case SFS_FLOGI_CHECK_TIMEOUT:
ddi_get_lbolt()) {
ss->ss_sol_flogi_state++;
}
break;
case SFS_ABTS_INIT:
ss->ss_sol_flogi_state++;
break;
case SFS_CLEAR_FLOGI:
if (ss->ss_sol_flogi) {
break;
}
}
goto check_state_again;
case SFS_FLOGI_ACC:
ss->ss_sol_flogi_state++;
goto check_state_again;
case SFS_FLOGI_DONE:
ss->ss_sol_flogi) {
}
/*
* We'd better to offline it first, and delay 0.1 seconds,
* before we say it's on again.
*/
FCT_EVENT_LINK_DOWN, 0, NULL);
FCT_EVENT_LINK_UP, 0, NULL);
break;
default:
ASSERT(0);
break;
}
}
/* ARGSUSED */
static int
{
return (FCOE_SUCCESS);
}
/* ARGSUSED */
static void
{
}
/* ARGSUSED */
static stmf_data_buf_t *
{
int add_size;
int sge_num;
int sge_size;
int idx;
int ii;
void *netb;
if (size > FCOET_MAX_DBUF_LEN) {
if (*pminsize > FCOET_MAX_DBUF_LEN) {
return (NULL);
}
}
return (NULL);
}
dbuf->db_sglist_length = 0;
/*
* Initialize non-last sg entries
*/
}
return (NULL);
}
sizeof (fcoe_fc_frame_header_t);
}
/*
* Initialize the last sg entry
*/
} else {
}
sizeof (fcoe_fc_frame_header_t) +
}
return (NULL);
}
sizeof (fcoe_fc_frame_header_t);
/*
* Let COMSTAR know how many sg entries we will use
*/
return (dbuf);
}
static void
{
int idx;
}
}
}
/*
* We should have initialized fcoe_frame_t before
*/
void
{
}
/* ARGSUSED */
static uint_t
{
ss->ss_sol_oxid_hash_empty = 0;
return (MH_WALK_CONTINUE);
}
/* ARGSUSED */
static uint_t
{
ss->ss_sol_oxid_hash_empty = 0;
return (MH_WALK_CONTINUE);
}
/* ARGSUSED */
void
{
}