/*
* 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.
*/
/*
* This file defines interfaces between fcoe and fcoet driver.
*/
/*
* 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"
/*
* function forward declaration
*/
/*
* rx_frame & release_sol_frame
* RXID -> unsol_rxid_hash
* OXID -> sol_oxid_hash
*/
void
{
switch (rctl) {
case 0x01:
/*
* Solicited data
*/
if (fcoet_process_sol_fcp_data(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_sol_fcp_data failed");
}
break;
case 0x06:
/*
* Unsolicited fcp_cmnd
*/
if (fcoet_process_unsol_fcp_cmd(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_unsol_fcp_cmd failed");
}
break;
case 0x22:
/*
* unsolicited ELS req
*/
if (fcoet_process_unsol_els_req(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_unsol_els_req failed");
}
break;
case 0x23:
/*
* solicited ELS rsp
*/
if (fcoet_process_sol_els_rsp(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_sol_els_rsp failed");
}
break;
case 0x81:
/*
* unsolicted ABTS req
*/
if (fcoet_process_unsol_abts_req(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_unsol_abts_req failed");
}
break;
case 0x84:
/*
* solicited ABTS acc response
*/
if (fcoet_process_sol_abts_acc(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_sol_abts_acc failed");
}
break;
case 0x85:
/*
* solcited ABTS rjt response
*/
if (fcoet_process_sol_abts_rjt(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_sol_abts_rjt failed");
}
break;
case 0x02:
/*
* unsolicited CT req
*/
if (fcoet_process_unsol_ct_req(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_sol_ct_rsp failed");
}
break;
case 0x03:
/*
* sol ct rsp
*/
if (fcoet_process_sol_ct_rsp(frm)) {
FCOET_LOG("fcoet_rx_frame",
"fcoet_process_sol_ct_rsp failed");
}
break;
default:
/*
* Unsupported frame
*/
break;
}
/*
* Release the frame in the end
*/
}
/*
* For solicited frames, after FCoE has sent it out, it will call this
*/
void
{
/*
* From now, we should not access both frm_hdr and frm_payload. Its
* mblk could have been released by MAC driver.
*/
case 0x01:
break;
}
if (fcoet_send_sol_fcp_data_done(frm)) {
ASSERT(0);
}
break;
case 0x05:
break;
case 0x07:
break;
}
if (fcoet_send_fcp_status_done(frm)) {
ASSERT(0);
}
break;
case 0x23:
break;
}
if (fcoet_send_unsol_els_rsp_done(frm)) {
ASSERT(0);
}
break;
case 0x22:
if (fcoet_send_sol_els_req_done(frm)) {
ASSERT(0);
}
break;
case 0x84:
if (fcoet_send_unsol_bls_acc_done(frm)) {
ASSERT(0);
}
break;
case 0x85:
if (fcoet_send_unsol_bls_rjt_done(frm)) {
ASSERT(0);
}
break;
case 0x81:
if (fcoet_send_sol_bls_req_done(frm)) {
ASSERT(0);
}
break;
case 0x02:
if (fcoet_send_sol_ct_req_done(frm)) {
ASSERT(0);
}
break;
case 0x03:
default:
/*
* Unsupported frame
*/
break;
}
/*
* We should release the frame
*/
}
void
{
switch (event) {
} else {
}
break;
FCT_EVENT_LINK_DOWN, 0, 0);
/* Need clear up all other things */
break;
default:
break;
}
}
/*
* For unsolicited exchanges, FCoET is only responsible for allocation of
* req_payload. FCT will allocate resp_payload after the exchange is
* passed on.
*/
static fcoet_exchange_t *
{
int cdb_size;
switch (r_ctl) {
case 0x22:
/*
* FCoET's unsolicited ELS
*/
frm->frm_payload_size, 0);
FCOET_EXT_LOG(0, "can't get cmd");
return (NULL);
}
break;
case 0x06:
/*
* FCoET's unsolicited SCSI cmd
*/
FCOET_EXT_LOG(0, "can't get fcp cmd");
return (NULL);
}
break;
default:
return (NULL);
}
/*
* xch initialization
*/
xch->xch_left_data_size = 0;
if (task_expected_len) {
xch->xch_dbuf_num =
KM_SLEEP);
}
do {
}
(mod_hash_val_t)&xch_tmp) == 0);
xch->xch_sequence_no = 0;
/*
* cmd initialization
*/
return (xch);
}
int
{
if (xch->xch_dbuf_num) {
xch->xch_dbuf_num * sizeof (void *));
xch->xch_dbuf_num = 0;
}
return (FCOE_SUCCESS);
}
"hash table", xch);
return (FCOE_FAILURE);
}
void
{
}
}
static int
{
int sge_idx;
int data_offset;
return (FCOE_FAILURE);
}
/*
* we will always have a buf waiting there
*/
if ((xch->xch_left_data_size <= 0) ||
fc_st = FCT_SUCCESS;
iof = 0;
}
return (FCOE_SUCCESS);
}
static int
{
return (FCOE_FAILURE);
}
task->task_flags |=
if (tm) {
} else {
}
}
return (FCOE_SUCCESS);
}
/*
* It must be from link
* req_payload has been allocated when create_unsol_exchange
*/
static int
{
/*
* For the reason of keeping symmetric, we do copy here as in
* process_sol_els instead of in create_unsol_exchange.
* req_payload depends on how to allocate buf in create_unsol_exchange
*/
/*
* Ensure LINK_UP event has been handled, or PLOIG has
* been processed by FCT, or else it will be discarded.
* It need more consideration later ???
*/
}
}
} else {
/*
* We always handle FLOGI internally
* Save dst mac address from FLOGI request to restore later
*/
}
return (ret);
}
/*
* It must be from link, but could be incomplete because of network problems
*/
static int
{
return (FCOE_FAILURE);
}
}
}
/*
* We handle FLOGI internally
*/
} else {
fc_st = FCT_SUCCESS;
}
return (ret);
}
/*
* It's still in the context of being aborted exchange, but FCT can't support
* this scheme, so there are two fct_cmd_t that are bound with one exchange.
*/
static int
{
FCOET_LOG("fcoet_process_unsol_abts_req",
"can't find aborted exchange");
return (FCOE_SUCCESS);
}
if (!FRM_IS_LAST_FRAME(frm)) {
FCOET_LOG("fcoet_process_unsol_abts_req",
"not supported this kind frame");
return (FCOE_FAILURE);
}
FCOET_LOG("fcoet_process_unsol_abts_req",
"can't alloc fct_cmd_t");
return (FCOE_FAILURE);
}
FCOET_LOG("fcoet_process_unsol_abts_req",
"abts now: xch/%p, frm/%p - time/%p",
return (FCOE_SUCCESS);
}
static int
{
(mod_hash_val_t *)&xch) != 0) {
/*
* So far ABTS for FLOGI might be removed from ss_sol_oxid_hash
* in fcoet_watch_handle_sol_flogi, Will improve it later
*/
return (FCOE_SUCCESS);
}
if (!FRM_IS_LAST_FRAME(frm)) {
FCOET_LOG("fcoet_process_sol_abts_acc",
"not supported this kind frame");
return (FCOE_FAILURE);
}
FCOET_LOG("fcoet_process_sol_abts_acc",
"ABTS received but there is nothing to do");
return (FCOE_SUCCESS);
}
static int
{
(mod_hash_val_t *)&xch) != 0) {
/*
* So far ABTS for FLOGI might be removed from ss_sol_oxid_hash
* in fcoet_watch_handle_sol_flogi, Will improve it later
*/
return (FCOE_SUCCESS);
}
if (!FRM_IS_LAST_FRAME(frm)) {
FCOET_LOG("fcoet_process_sol_abts_rjt",
"not supported this kind frame");
return (FCOE_FAILURE);
}
FCOET_LOG("fcoet_process_sol_abts_rjt",
"ABTS_RJT received rjt reason %x but there is nothing to do",
return (FCOE_SUCCESS);
}
static int
{
/*
* gateway, you can do it here
*/
if (!FRM_IS_LAST_FRAME(frm)) {
FCOET_LOG("fcoet_process_unsol_ct_req",
"not supported this kind frame");
return (FCOE_FAILURE);
}
FCOET_LOG("fcoet_process_unsol_ct_req",
"No support for unsolicited CT request");
return (FCOE_SUCCESS);
}
static int
{
(mod_hash_val_t *)&xch) != 0) {
return (FCOE_SUCCESS);
}
}
fc_st = FCT_SUCCESS;
return (FCOE_SUCCESS);
}
static int
{
int dbuf_index;
/*
* We decrease db_sglist_length only for READ-type commands.
* For INQUIRY, resid could be non-zero, then db_sglist_length will
* be useful.
*/
dbuf->db_sglist_length--;
iof = 0;
return (FCOE_FAILURE);
}
} else {
}
}
return (FCOE_SUCCESS);
}
static int
{
return (FCOE_SUCCESS);
}
} else {
/* Already cleared from hash table by abort */
}
return (FCOE_SUCCESS);
}
/*
* Solicited frames callback area
*/
static int
{
FCOET_EXT_LOG("fcoet_send_unsol_els_rsp_done",
return (FCOE_SUCCESS);
}
return (FCOE_SUCCESS);
}
fc_st = FCT_SUCCESS;
} else {
/*
* We need update ss_link_info and flags.
*/
}
}
return (FCOE_SUCCESS);
}
/* ARGSUSED */
static int
{
return (FCOE_SUCCESS);
}
/*
* FCT have released relevant fct_cmd_t and fcoet_exchange_t now, so it's not
* needed to notify FCT anything. Just do nothing.
*/
/* ARGSUSED */
static int
{
FCOET_LOG("fcoet_send_unsol_bls_acc_done",
"Unsolicited BA_ACC sent out and released ");
return (FCOE_SUCCESS);
}
/* ARGSUSED */
static int
{
FCOET_LOG("fcoet_send_unsol_bls_rjt_done",
"Unsolicited BA_RJT sent out and released");
return (FCOE_SUCCESS);
}
/* ARGSUSED */
static int
{
FCOET_LOG("fcoet_send_sol_bls_req_done",
"Soclited ABTS was sent out and released");
return (FCOE_SUCCESS);
}
/* ARGSUSED */
static int
{
FCOET_LOG("fcoet_send_sol_ct_req_done",
"CT request was sent out and released");
return (FCOE_SUCCESS);
}
/*
* FCoET can only interpret solicited and unsolicited FLOGI, all the other
*/
static int
{
/*
* In spec, common service parameter should indicate if it's from
* N-port or F-port, but the initial intel implementation is not
* spec-compliant, so we use eport_flags to workaround the problem
*/
/*
* The topology is switch P2P, so there's no need to respond
* to this FLOGI
*/
FCOET_LOG("fcoet_process_unsol_flogi_req",
"skip FLOGI, since we are in switch topology");
return (FCOE_SUCCESS);
}
/*
* Send ACC according to the spec.
*/
FLOGI_ACC_PAYLOAD_SIZE + FCFH_SIZE, 0);
ASSERT(0);
return (FCOE_FAILURE);
} else {
}
/*
* ACC
*/
/*
* Common Svc Parameters
*/
/*
* Class3 Svc Parameters
*/
/*
* Send FLOGI ACC out
* After this, we should never use the exchange, because it could
* have been released. Please pay attention to other similiar cases.
*/
return (FCOE_SUCCESS);
}
static int
{
/*
* We need always update ss_link_info and flags for solicited
* FLOGI, because someone has assigned address for you. The
* initial intel implementation will always assign address for
* you even you are in back-to-back mode (direct P2P).
*/
/*
* The status is not correct, this response may be
* obsolete.
*/
FCOET_LOG("fcoet_process_sol_flogi_rsp",
"FLOGI response is obsolete");
return (FCOE_FAILURE);
}
/*
* Check the bit 28 in 3rd word of the payload
* in common service parameters to know the
* remote port is F_PORT or N_PORT
*/
} else {
}
FCOET_LOG("fcoet_process_sol_flogi_rsp",
"FLOGI is accecpted");
} else {
FCOET_LOG("fcoet_process_sol_flogi_rsp",
ret = FCOE_FAILURE;
}
} else {
ret = FCOE_FAILURE;
}
return (ret);
}