iPXE
Data Structures | Defines | Functions | Variables
fcp.c File Reference

Fibre Channel Protocol. More...

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/refcnt.h>
#include <ipxe/list.h>
#include <ipxe/interface.h>
#include <ipxe/xfer.h>
#include <ipxe/iobuf.h>
#include <ipxe/open.h>
#include <ipxe/process.h>
#include <ipxe/uri.h>
#include <ipxe/acpi.h>
#include <ipxe/scsi.h>
#include <ipxe/device.h>
#include <ipxe/edd.h>
#include <ipxe/fc.h>
#include <ipxe/fcels.h>
#include <ipxe/fcp.h>

Go to the source code of this file.

Data Structures

struct  fcp_device
 An FCP device. More...
struct  fcp_command
 An FCP command. More...

Defines

#define ERANGE_READ_DATA_ORDERING   __einfo_error ( EINFO_ERANGE_READ_DATA_ORDERING )
#define EINFO_ERANGE_READ_DATA_ORDERING   __einfo_uniqify ( EINFO_ERANGE, 0x01, "Read data out of order" )
#define ERANGE_READ_DATA_OVERRUN   __einfo_error ( EINFO_ERANGE_READ_DATA_OVERRUN )
#define EINFO_ERANGE_READ_DATA_OVERRUN   __einfo_uniqify ( EINFO_ERANGE, 0x02, "Read data overrun" )
#define ERANGE_WRITE_DATA_STUCK   __einfo_error ( EINFO_ERANGE_WRITE_DATA_STUCK )
#define EINFO_ERANGE_WRITE_DATA_STUCK   __einfo_uniqify ( EINFO_ERANGE, 0x03, "Write data stuck" )
#define ERANGE_WRITE_DATA_OVERRUN   __einfo_error ( EINFO_ERANGE_WRITE_DATA_OVERRUN )
#define EINFO_ERANGE_WRITE_DATA_OVERRUN   __einfo_uniqify ( EINFO_ERANGE, 0x04, "Write data overrun" )
#define ERANGE_DATA_UNDERRUN   __einfo_error ( EINFO_ERANGE_DATA_UNDERRUN )
#define EINFO_ERANGE_DATA_UNDERRUN   __einfo_uniqify ( EINFO_ERANGE, 0x05, "Data underrun" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int fcp_prli_tx (struct fc_els *els)
 Transmit FCP PRLI.
static int fcp_prli_rx (struct fc_els *els, void *data, size_t len)
 Receive FCP PRLI.
static int fcp_prli_detect (struct fc_els *els, const void *data, size_t len)
 Detect FCP PRLI.
static struct fcp_devicefcpdev_get (struct fcp_device *fcpdev)
 Get reference to FCP device.
static void fcpdev_put (struct fcp_device *fcpdev)
 Drop reference to FCP device.
static struct fcp_commandfcpcmd_get (struct fcp_command *fcpcmd)
 Get reference to FCP command.
static void fcpcmd_put (struct fcp_command *fcpcmd)
 Drop reference to FCP command.
static void fcpcmd_start_send (struct fcp_command *fcpcmd, int(*send)(struct fcp_command *fcpcmd))
 Start FCP command sending.
static void fcpcmd_stop_send (struct fcp_command *fcpcmd)
 Stop FCP command sending.
static void fcpcmd_free (struct refcnt *refcnt)
 Free FCP command.
static void fcpcmd_close (struct fcp_command *fcpcmd, int rc)
 Close FCP command.
static void fcpcmd_close_err (struct fcp_command *fcpcmd, int rc)
 Close FCP command in error.
static int fcpcmd_send_cmnd (struct fcp_command *fcpcmd)
 Send FCP command IU.
static int fcpcmd_recv_rddata (struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Handle FCP read data IU.
static int fcpcmd_send_wrdata (struct fcp_command *fcpcmd)
 Send FCP write data IU.
static int fcpcmd_recv_xfer_rdy (struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Handle FCP transfer ready IU.
static int fcpcmd_recv_rsp (struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Handle FCP response IU.
static int fcpcmd_recv_unknown (struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Handle unknown FCP IU.
static void fcpcmd_step (struct fcp_command *fcpcmd)
 Transmit FCP frame.
static int fcpcmd_deliver (struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive FCP frame.
static int fcpdev_scsi_command (struct fcp_device *fcpdev, struct interface *parent, struct scsi_cmd *command)
 Issue FCP SCSI command.
static void fcpdev_close (struct fcp_device *fcpdev, int rc)
 Close FCP device.
static size_t fcpdev_window (struct fcp_device *fcpdev)
 Check FCP device flow-control window.
static int fcpdev_edd_describe (struct fcp_device *fcpdev, struct edd_interface_type *type, union edd_device_path *path)
 Describe FCP device using EDD.
static struct devicefcpdev_identify_device (struct fcp_device *fcpdev)
 Identify device underlying FCP device.
static void fcpdev_examine (struct fc_ulp_user *user)
 Examine FCP ULP link state.
static int fcpdev_open (struct interface *parent, struct fc_name *wwn, struct scsi_lun *lun)
 Open FCP device.
static int fcp_parse_uri (struct uri *uri, struct fc_name *wwn, struct scsi_lun *lun)
 Parse FCP URI.
static int fcp_open (struct interface *parent, struct uri *uri)
 Open FCP URI.

Variables

struct fc_els_prli_descriptor
fcp_prli_descriptor 
__fc_els_prli_descriptor
 FCP PRLI descriptor.
struct fc_els_handler
fcp_prli_handler 
__fc_els_handler
 FCP PRLI ELS handler.
static struct interface_operation fcpcmd_scsi_op []
 FCP command SCSI interface operations.
static struct interface_descriptor fcpcmd_scsi_desc
 FCP command SCSI interface descriptor.
static struct interface_operation fcpcmd_xchg_op []
 FCP command Fibre Channel exchange interface operations.
static struct interface_descriptor fcpcmd_xchg_desc
 FCP command Fibre Channel exchange interface descriptor.
static struct process_descriptor fcpcmd_process_desc
 FCP command process descriptor.
static struct interface_operation fcpdev_scsi_op []
 FCP device SCSI interface operations.
static struct interface_descriptor fcpdev_scsi_desc
 FCP device SCSI interface descriptor.
struct uri_opener fcp_uri_opener __uri_opener
 FCP URI opener.

Detailed Description

Fibre Channel Protocol.

Definition in file fcp.c.


Define Documentation

Definition at line 57 of file fcp.c.

Referenced by fcpcmd_recv_rddata().

#define EINFO_ERANGE_READ_DATA_ORDERING   __einfo_uniqify ( EINFO_ERANGE, 0x01, "Read data out of order" )

Definition at line 59 of file fcp.c.

Definition at line 61 of file fcp.c.

Referenced by fcpcmd_recv_rddata().

#define EINFO_ERANGE_READ_DATA_OVERRUN   __einfo_uniqify ( EINFO_ERANGE, 0x02, "Read data overrun" )

Definition at line 63 of file fcp.c.

Definition at line 65 of file fcp.c.

Referenced by fcpcmd_send_wrdata().

#define EINFO_ERANGE_WRITE_DATA_STUCK   __einfo_uniqify ( EINFO_ERANGE, 0x03, "Write data stuck" )

Definition at line 67 of file fcp.c.

Definition at line 69 of file fcp.c.

Referenced by fcpcmd_send_wrdata().

#define EINFO_ERANGE_WRITE_DATA_OVERRUN   __einfo_uniqify ( EINFO_ERANGE, 0x04, "Write data overrun" )

Definition at line 71 of file fcp.c.

Definition at line 73 of file fcp.c.

Referenced by fcpcmd_recv_rsp().

#define EINFO_ERANGE_DATA_UNDERRUN   __einfo_uniqify ( EINFO_ERANGE, 0x05, "Data underrun" )

Definition at line 75 of file fcp.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int fcp_prli_tx ( struct fc_els els) [static]

Transmit FCP PRLI.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 93 of file fcp.c.

References fc_els_prli_tx(), FCP_PRLI_INITIATOR, FCP_PRLI_NO_READ_RDY, fcp_prli_service_parameters::flags, htonl, and memset().

                                              {
        struct fcp_prli_service_parameters param;

        /* Build service parameter page */
        memset ( &param, 0, sizeof ( param ) );
        param.flags = htonl ( FCP_PRLI_NO_READ_RDY | FCP_PRLI_INITIATOR );

        return fc_els_prli_tx ( els, &fcp_prli_descriptor, &param );
}
static int fcp_prli_rx ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive FCP PRLI.

Parameters:
elsFibre Channel ELS transaction
frameELS frame
lenLength of ELS frame
Return values:
rcReturn status code

Definition at line 111 of file fcp.c.

References fc_els_prli_rx().

                                                                      {
        return fc_els_prli_rx ( els, &fcp_prli_descriptor, data, len );
}
static int fcp_prli_detect ( struct fc_els els,
const void *  data,
size_t  len 
) [static]

Detect FCP PRLI.

Parameters:
elsFibre Channel ELS transaction
dataELS frame
lenLength of ELS frame
Return values:
rcReturn status code

Definition at line 123 of file fcp.c.

References fc_els_prli_detect().

                                          {
        return fc_els_prli_detect ( els, &fcp_prli_descriptor, data, len );
}
static struct fcp_device* fcpdev_get ( struct fcp_device fcpdev) [static, read]

Get reference to FCP device.

Parameters:
fcpdevFCP device
Return values:
fcpdevFCP device

Definition at line 204 of file fcp.c.

References ref_get.

Referenced by fcpdev_scsi_command().

                                         {
        ref_get ( &fcpdev->refcnt );
        return fcpdev;
}
static void fcpdev_put ( struct fcp_device fcpdev) [inline, static]

Drop reference to FCP device.

Parameters:
fcpdevFCP device

Definition at line 215 of file fcp.c.

References ref_put.

Referenced by fcpcmd_free().

                                         {
        ref_put ( &fcpdev->refcnt );
}
static struct fcp_command* fcpcmd_get ( struct fcp_command fcpcmd) [static, read]

Get reference to FCP command.

Parameters:
fcpcmdFCP command
Return values:
fcpcmdFCP command

Definition at line 226 of file fcp.c.

References ref_get.

Referenced by fcpdev_close().

                                          {
        ref_get ( &fcpcmd->refcnt );
        return fcpcmd;
}
static void fcpcmd_put ( struct fcp_command fcpcmd) [inline, static]

Drop reference to FCP command.

Parameters:
fcpcmdFCP command

Definition at line 237 of file fcp.c.

References ref_put.

Referenced by fcpdev_close().

                                          {
        ref_put ( &fcpcmd->refcnt );
}
static void fcpcmd_start_send ( struct fcp_command fcpcmd,
int(*)(struct fcp_command *fcpcmd)  send 
) [inline, static]

Start FCP command sending.

Parameters:
fcpcmdFCP command
sendSend method

Definition at line 248 of file fcp.c.

References process_add(), and send.

Referenced by fcpcmd_recv_xfer_rdy(), and fcpdev_scsi_command().

                                                                    {
        fcpcmd->send = send;
        process_add ( &fcpcmd->process );
}
static void fcpcmd_stop_send ( struct fcp_command fcpcmd) [inline, static]

Stop FCP command sending.

Parameters:
fcpcmdFCP command

Definition at line 260 of file fcp.c.

References process_del().

Referenced by fcpcmd_close(), fcpcmd_send_cmnd(), and fcpcmd_send_wrdata().

                                                {
        process_del ( &fcpcmd->process );
}
static void fcpcmd_free ( struct refcnt refcnt) [static]

Free FCP command.

Parameters:
refcntReference count

Definition at line 269 of file fcp.c.

References container_of, fcp_command::fcpdev, fcpdev_put(), free, fcp_command::list, and list_del.

Referenced by fcpdev_scsi_command().

                                                  {
        struct fcp_command *fcpcmd =
                container_of ( refcnt, struct fcp_command, refcnt );

        /* Remove from list of commands */
        list_del ( &fcpcmd->list );
        fcpdev_put ( fcpcmd->fcpdev );

        /* Free command */
        free ( fcpcmd );
}
static void fcpcmd_close ( struct fcp_command fcpcmd,
int  rc 
) [static]

Close FCP command.

Parameters:
fcpcmdFCP command
rcReason for close

Definition at line 287 of file fcp.c.

References DBGC, fcpcmd_stop_send(), fcp_command::fcpdev, intf_shutdown(), fcp_command::scsi, strerror(), fcp_command::xchg, and fcp_command::xchg_id.

Referenced by fcpcmd_close_err(), fcpcmd_deliver(), fcpcmd_recv_rsp(), fcpcmd_step(), fcpdev_close(), and fcpdev_scsi_command().

                                                                {
        struct fcp_device *fcpdev = fcpcmd->fcpdev;

        if ( rc != 0 ) {
                DBGC ( fcpdev, "FCP %p xchg %04x closed: %s\n",
                       fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
        }

        /* Stop sending */
        fcpcmd_stop_send ( fcpcmd );

        /* Shut down interfaces */
        intf_shutdown ( &fcpcmd->scsi, rc );
        intf_shutdown ( &fcpcmd->xchg, rc );
}
static void fcpcmd_close_err ( struct fcp_command fcpcmd,
int  rc 
) [static]

Close FCP command in error.

Parameters:
fcpcmdFCP command
rcReason for close

Definition at line 309 of file fcp.c.

References EPIPE, and fcpcmd_close().

                                                                    {
        if ( rc == 0 )
                rc = -EPIPE;
        fcpcmd_close ( fcpcmd, rc );
}
static int fcpcmd_send_cmnd ( struct fcp_command fcpcmd) [static]

Send FCP command IU.

Parameters:
fcpcmdFCP command
Return values:
rcReturn status code

Definition at line 321 of file fcp.c.

References assert, fcp_cmnd::cdb, scsi_cmd::cdb, fcp_command::command, scsi_cmd::data_in_len, scsi_cmd::data_out_len, DBGC, DBGC2, fcp_cmnd::dirn, ENOMEM, ENOTSUP, FCP_CMND_RDDATA, FCP_CMND_WRDATA, fcpcmd_stop_send(), fcp_command::fcpdev, xfer_metadata::flags, htonl, iob_disown, iob_put, fcp_cmnd::len, fcp_cmnd::lun, scsi_cmd::lun, memcpy(), memset(), ntohl, rc, SCSI_CDB_DATA, SCSI_CDB_FORMAT, strerror(), fcp_command::xchg, fcp_command::xchg_id, xfer_alloc_iob(), xfer_deliver(), XFER_FL_CMD_STAT, and XFER_FL_OVER.

Referenced by fcpdev_scsi_command().

                                                           {
        struct fcp_device *fcpdev = fcpcmd->fcpdev;
        struct scsi_cmd *command = &fcpcmd->command;
        struct io_buffer *iobuf;
        struct fcp_cmnd *cmnd;
        struct xfer_metadata meta;
        int rc;

        /* Sanity check */
        if ( command->data_in_len && command->data_out_len ) {
                DBGC ( fcpdev, "FCP %p xchg %04x cannot handle bidirectional "
                       "command\n", fcpdev, fcpcmd->xchg_id );
                return -ENOTSUP;
        }

        /* Allocate I/O buffer */
        iobuf = xfer_alloc_iob ( &fcpcmd->xchg, sizeof ( *cmnd ) );
        if ( ! iobuf ) {
                DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate command IU\n",
                       fcpdev, fcpcmd->xchg_id );
                return -ENOMEM;
        }

        /* Construct command IU frame */
        cmnd = iob_put ( iobuf, sizeof ( *cmnd ) );
        memset ( cmnd, 0, sizeof ( *cmnd ) );
        memcpy ( &cmnd->lun, &command->lun, sizeof ( cmnd->lun ) );
        assert ( ! ( command->data_in_len && command->data_out_len ) );
        if ( command->data_in_len )
                cmnd->dirn |= FCP_CMND_RDDATA;
        if ( command->data_out_len )
                cmnd->dirn |= FCP_CMND_WRDATA;
        memcpy ( &cmnd->cdb, &fcpcmd->command.cdb, sizeof ( cmnd->cdb ) );
        cmnd->len = htonl ( command->data_in_len + command->data_out_len );
        memset ( &meta, 0, sizeof ( meta ) );
        meta.flags = ( XFER_FL_CMD_STAT | XFER_FL_OVER );
        DBGC2 ( fcpdev, "FCP %p xchg %04x CMND " SCSI_CDB_FORMAT " %04x\n",
                fcpdev, fcpcmd->xchg_id, SCSI_CDB_DATA ( cmnd->cdb ),
                ntohl ( cmnd->len ) );

        /* No further data to send within this IU */
        fcpcmd_stop_send ( fcpcmd );

        /* Send command IU frame */
        if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
                                   &meta ) ) != 0 ) {
                DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver command IU: "
                       "%s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int fcpcmd_recv_rddata ( struct fcp_command fcpcmd,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Handle FCP read data IU.

Parameters:
fcpcmdFCP command
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 383 of file fcp.c.

References assert, fcp_command::command, copy_to_user(), io_buffer::data, scsi_cmd::data_in, scsi_cmd::data_in_len, DBGC, DBGC2, done, ERANGE_READ_DATA_ORDERING, ERANGE_READ_DATA_OVERRUN, fcp_command::fcpdev, xfer_metadata::flags, free_iob(), iob_len(), len, xfer_metadata::offset, fcp_command::offset, offset, rc, fcp_command::xchg_id, and XFER_FL_ABS_OFFSET.

Referenced by fcpcmd_deliver().

                                                             {
        struct fcp_device *fcpdev = fcpcmd->fcpdev;
        struct scsi_cmd *command = &fcpcmd->command;
        size_t offset = meta->offset;
        size_t len = iob_len ( iobuf );
        int rc;

        /* Sanity checks */
        if ( ! ( meta->flags & XFER_FL_ABS_OFFSET ) ) {
                DBGC ( fcpdev, "FCP %p xchg %04x read data missing offset\n",
                       fcpdev, fcpcmd->xchg_id );
                rc = -ERANGE_READ_DATA_ORDERING;
                goto done;
        }
        if ( offset != fcpcmd->offset ) {
                DBGC ( fcpdev, "FCP %p xchg %04x read data out of order "
                       "(expected %zd, received %zd)\n",
                       fcpdev, fcpcmd->xchg_id, fcpcmd->offset, offset );
                rc = -ERANGE_READ_DATA_ORDERING;
                goto done;
        }
        if ( ( offset + len ) > command->data_in_len ) {
                DBGC ( fcpdev, "FCP %p xchg %04x read data overrun (max %zd, "
                       "received %zd)\n", fcpdev, fcpcmd->xchg_id,
                       command->data_in_len, ( offset + len ) );
                rc = -ERANGE_READ_DATA_OVERRUN;
                goto done;
        }
        DBGC2 ( fcpdev, "FCP %p xchg %04x RDDATA [%08zx,%08zx)\n",
                fcpdev, fcpcmd->xchg_id, offset, ( offset + len ) );

        /* Copy to user buffer */
        copy_to_user ( command->data_in, offset, iobuf->data, len );
        fcpcmd->offset += len;
        assert ( fcpcmd->offset <= command->data_in_len );

        rc = 0;
 done:
        free_iob ( iobuf );
        return rc;
}
static int fcpcmd_send_wrdata ( struct fcp_command fcpcmd) [static]

Send FCP write data IU.

Parameters:
fcpcmdFCP command
Return values:
rcReturn status code

Definition at line 433 of file fcp.c.

References assert, fcp_command::command, copy_from_user(), scsi_cmd::data_out, scsi_cmd::data_out_len, DBGC, DBGC2, ENOMEM, ERANGE_WRITE_DATA_OVERRUN, ERANGE_WRITE_DATA_STUCK, fcpcmd_stop_send(), fcp_command::fcpdev, xfer_metadata::flags, iob_disown, iob_len(), iob_put, len, memset(), xfer_metadata::offset, fcp_command::offset, rc, fcp_command::remaining, strerror(), fcp_command::xchg, fcp_command::xchg_id, xfer_alloc_iob(), xfer_deliver(), XFER_FL_ABS_OFFSET, XFER_FL_OVER, XFER_FL_RESPONSE, and xfer_window().

Referenced by fcpcmd_recv_xfer_rdy().

                                                             {
        struct fcp_device *fcpdev = fcpcmd->fcpdev;
        struct scsi_cmd *command = &fcpcmd->command;
        struct io_buffer *iobuf;
        struct xfer_metadata meta;
        size_t len;
        int rc;

        /* Calculate length to be sent */
        len = xfer_window ( &fcpcmd->xchg );
        if ( len > fcpcmd->remaining )
                len = fcpcmd->remaining;

        /* Sanity checks */
        if ( len == 0 ) {
                DBGC ( fcpdev, "FCP %p xchg %04x write data stuck\n",
                       fcpdev, fcpcmd->xchg_id );
                return -ERANGE_WRITE_DATA_STUCK;
        }
        if ( ( fcpcmd->offset + len ) > command->data_out_len ) {
                DBGC ( fcpdev, "FCP %p xchg %04x write data overrun (max %zd, "
                       "requested %zd)\n", fcpdev, fcpcmd->xchg_id,
                       command->data_out_len, ( fcpcmd->offset + len ) );
                return -ERANGE_WRITE_DATA_OVERRUN;
        }

        /* Allocate I/O buffer */
        iobuf = xfer_alloc_iob ( &fcpcmd->xchg, len );
        if ( ! iobuf ) {
                DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate write data "
                       "IU for %zd bytes\n", fcpdev, fcpcmd->xchg_id, len );
                return -ENOMEM;
        }

        /* Construct data IU frame */
        copy_from_user ( iob_put ( iobuf, len ), command->data_out,
                         fcpcmd->offset, len );
        memset ( &meta, 0, sizeof ( meta ) );
        meta.flags = ( XFER_FL_RESPONSE | XFER_FL_ABS_OFFSET );
        meta.offset = fcpcmd->offset;
        DBGC2 ( fcpdev, "FCP %p xchg %04x WRDATA [%08zx,%04zx)\n",
                fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
                ( fcpcmd->offset + iob_len ( iobuf ) ) );

        /* Calculate amount of data remaining to be sent within this IU */
        assert ( len <= fcpcmd->remaining );
        fcpcmd->offset += len;
        fcpcmd->remaining -= len;
        assert ( fcpcmd->offset <= command->data_out_len );
        if ( fcpcmd->remaining == 0 ) {
                fcpcmd_stop_send ( fcpcmd );
                meta.flags |= XFER_FL_OVER;
        }

        /* Send data IU frame */
        if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
                                   &meta ) ) != 0 ) {
                DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver write data "
                       "IU: %s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int fcpcmd_recv_xfer_rdy ( struct fcp_command fcpcmd,
struct io_buffer iobuf,
struct xfer_metadata *meta  __unused 
) [static]

Handle FCP transfer ready IU.

Parameters:
fcpcmdFCP command
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 506 of file fcp.c.

References io_buffer::data, DBGC, DBGC2, DBGC_HDA, done, EPROTO, fcpcmd_send_wrdata(), fcpcmd_start_send(), fcp_command::fcpdev, free_iob(), iob_len(), fcp_xfer_rdy::len, ntohl, fcp_xfer_rdy::offset, fcp_command::offset, rc, fcp_command::remaining, and fcp_command::xchg_id.

Referenced by fcpcmd_deliver().

                                                                        {
        struct fcp_device *fcpdev = fcpcmd->fcpdev;
        struct fcp_xfer_rdy *xfer_rdy = iobuf->data;
        int rc;

        /* Sanity checks */
        if ( iob_len ( iobuf ) != sizeof ( *xfer_rdy ) ) {
                DBGC ( fcpdev, "FCP %p xchg %04x received invalid transfer "
                       "ready IU:\n", fcpdev, fcpcmd->xchg_id );
                DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EPROTO;
                goto done;
        }
        if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) {
                /* We do not advertise out-of-order delivery */
                DBGC ( fcpdev, "FCP %p xchg %04x cannot support out-of-order "
                       "delivery (expected %zd, requested %d)\n",
                       fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
                       ntohl ( xfer_rdy->offset ) );
                rc = -EPROTO;
                goto done;
        }
        DBGC2 ( fcpdev, "FCP %p xchg %04x XFER_RDY [%08x,%08x)\n",
                fcpdev, fcpcmd->xchg_id, ntohl ( xfer_rdy->offset ),
                ( ntohl ( xfer_rdy->offset ) + ntohl ( xfer_rdy->len ) ) );

        /* Start sending requested data */
        fcpcmd->remaining = ntohl ( xfer_rdy->len );
        fcpcmd_start_send ( fcpcmd, fcpcmd_send_wrdata );

        rc = 0;
 done:
        free_iob ( iobuf );
        return rc;
}
static int fcpcmd_recv_rsp ( struct fcp_command fcpcmd,
struct io_buffer iobuf,
struct xfer_metadata *meta  __unused 
) [static]

Handle FCP response IU.

Parameters:
fcpcmdFCP command
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 552 of file fcp.c.

References fcp_command::command, io_buffer::data, scsi_cmd::data_in_len, scsi_cmd::data_out_len, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, done, EPROTO, ERANGE_DATA_UNDERRUN, FCP_RSP_RESIDUAL_OVERRUN, FCP_RSP_RESIDUAL_UNDERRUN, fcp_rsp_response_data(), fcp_rsp_response_data_len(), FCP_RSP_RESPONSE_LEN_VALID, fcp_rsp_sense_data(), fcp_rsp_sense_data_len(), FCP_RSP_SENSE_LEN_VALID, fcpcmd_close(), fcp_command::fcpdev, fcp_rsp::flags, free_iob(), iob_disown, iob_len(), memset(), ntohl, fcp_command::offset, scsi_rsp::overrun, rc, fcp_rsp::residual, rsp, fcp_command::scsi, scsi_parse_sense(), scsi_response(), scsi_rsp::sense, fcp_rsp::status, scsi_rsp::status, and fcp_command::xchg_id.

Referenced by fcpcmd_deliver().

                                                                   {
        struct fcp_device *fcpdev = fcpcmd->fcpdev;
        struct scsi_cmd *command = &fcpcmd->command;
        struct fcp_rsp *rsp = iobuf->data;
        struct scsi_rsp response;
        int rc;

        /* Sanity check */
        if ( ( iob_len ( iobuf ) < sizeof ( *rsp ) ) ||
             ( iob_len ( iobuf ) < ( sizeof ( *rsp ) +
                                     fcp_rsp_response_data_len ( rsp ) +
                                     fcp_rsp_sense_data_len ( rsp ) ) ) ) {
                DBGC ( fcpdev, "FCP %p xchg %04x received invalid response "
                       "IU:\n", fcpdev, fcpcmd->xchg_id );
                DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EPROTO;
                goto done;
        }
        DBGC2 ( fcpdev, "FCP %p xchg %04x RSP stat %02x resid %08x flags %02x"
                "%s%s%s%s\n", fcpdev, fcpcmd->xchg_id, rsp->status,
                ntohl ( rsp->residual ), rsp->flags,
                ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ? " resp" : "" ),
                ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ? " sense" : "" ),
                ( ( rsp->flags & FCP_RSP_RESIDUAL_OVERRUN ) ? " over" : "" ),
                ( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "" ));
        if ( fcp_rsp_response_data ( rsp ) ) {
                DBGC2 ( fcpdev, "FCP %p xchg %04x response data:\n",
                        fcpdev, fcpcmd->xchg_id );
                DBGC2_HDA ( fcpdev, 0, fcp_rsp_response_data ( rsp ),
                            fcp_rsp_response_data_len ( rsp ) );
        }
        if ( fcp_rsp_sense_data ( rsp ) ) {
                DBGC2 ( fcpdev, "FCP %p xchg %04x sense data:\n",
                        fcpdev, fcpcmd->xchg_id );
                DBGC2_HDA ( fcpdev, 0, fcp_rsp_sense_data ( rsp ),
                            fcp_rsp_sense_data_len ( rsp ) );
        }

        /* Check for locally-detected command underrun */
        if ( ( rsp->status == 0 ) &&
             ( fcpcmd->offset != ( command->data_in_len +
                                   command->data_out_len ) ) ) {
                DBGC ( fcpdev, "FCP %p xchg %04x data underrun (expected %zd, "
                       "got %zd)\n", fcpdev, fcpcmd->xchg_id,
                       ( command->data_in_len + command->data_out_len ),
                       fcpcmd->offset );
                rc = -ERANGE_DATA_UNDERRUN;
                goto done;
        }

        /* Build SCSI response */
        memset ( &response, 0, sizeof ( response ) );
        response.status = rsp->status;
        if ( rsp->flags & ( FCP_RSP_RESIDUAL_OVERRUN |
                            FCP_RSP_RESIDUAL_UNDERRUN ) ) {
                response.overrun = ntohl ( rsp->residual );
                if ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN )
                        response.overrun = -response.overrun;
        }
        scsi_parse_sense ( fcp_rsp_sense_data ( rsp ),
                           fcp_rsp_sense_data_len ( rsp ), &response.sense );

        /* Free buffer before sending response, to minimise
         * out-of-memory errors.
         */
        free_iob ( iob_disown ( iobuf ) );

        /* Send SCSI response */
        scsi_response ( &fcpcmd->scsi, &response );

        /* Terminate command */
        fcpcmd_close ( fcpcmd, 0 );

        rc = 0;
 done:
        free_iob ( iobuf );
        return rc;
}
static int fcpcmd_recv_unknown ( struct fcp_command fcpcmd,
struct io_buffer iobuf,
struct xfer_metadata *meta  __unused 
) [static]

Handle unknown FCP IU.

Parameters:
fcpcmdFCP command
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 641 of file fcp.c.

References io_buffer::data, DBGC, DBGC_HDA, EPROTO, fcp_command::fcpdev, free_iob(), iob_len(), and fcp_command::xchg_id.

Referenced by fcpcmd_deliver().

                                                                       {
        struct fcp_device *fcpdev = fcpcmd->fcpdev;

        DBGC ( fcpdev, "FCP %p xchg %04x received unknown IU:\n",
               fcpdev, fcpcmd->xchg_id );
        DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
        free_iob ( iobuf );
        return -EPROTO;
}
static void fcpcmd_step ( struct fcp_command fcpcmd) [static]

Transmit FCP frame.

Parameters:
fcpcmdFCP command

Definition at line 658 of file fcp.c.

References fcpcmd_close(), rc, and fcp_command::send.

                                                       {
        int rc;

        /* Send the current IU */
        if ( ( rc = fcpcmd->send ( fcpcmd ) ) != 0 ) {
                /* Treat failure as a fatal error */
                fcpcmd_close ( fcpcmd, rc );
        }
}
static int fcpcmd_deliver ( struct fcp_command fcpcmd,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Receive FCP frame.

Parameters:
fcpcmdFCP command
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 676 of file fcp.c.

References fcpcmd_close(), fcpcmd_recv_rddata(), fcpcmd_recv_rsp(), fcpcmd_recv_unknown(), fcpcmd_recv_xfer_rdy(), xfer_metadata::flags, iob_disown, meta(), rc, XFER_FL_CMD_STAT, and XFER_FL_RESPONSE.

                                                         {
        int ( * fcpcmd_recv ) ( struct fcp_command *fcpcmd,
                                struct io_buffer *iobuf,
                                struct xfer_metadata *meta );
        int rc;

        /* Determine handler */
        switch ( meta->flags & ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ) ) {
        case ( XFER_FL_RESPONSE ) :
                fcpcmd_recv = fcpcmd_recv_rddata;
                break;
        case ( XFER_FL_CMD_STAT ) :
                fcpcmd_recv = fcpcmd_recv_xfer_rdy;
                break;
        case ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ) :
                fcpcmd_recv = fcpcmd_recv_rsp;
                break;
        default:
                fcpcmd_recv = fcpcmd_recv_unknown;
                break;
        }

        /* Handle IU */
        if ( ( rc = fcpcmd_recv ( fcpcmd, iob_disown ( iobuf ), meta ) ) != 0 ){
                /* Treat any error as fatal to the command */
                fcpcmd_close ( fcpcmd, rc );
        }

        return rc;
}
static int fcpdev_scsi_command ( struct fcp_device fcpdev,
struct interface parent,
struct scsi_cmd command 
) [static]

Issue FCP SCSI command.

Parameters:
fcpdevFCP device
parentParent interface
commandSCSI command
Return values:
tagCommand tag, or negative error

Definition at line 740 of file fcp.c.

References assert, fcp_command::command, DBGC, ENOMEM, ENOTTY, FC_TYPE_FCP, fc_xchg_originate(), FCP_PRLI_TARGET, FCP_TAG_MAGIC, fcpcmd_close(), fcpcmd_free(), fcpcmd_send_cmnd(), fcpcmd_start_send(), fcp_device::fcpcmds, fcp_command::fcpdev, fcpdev_get(), fcp_prli_service_parameters::flags, htonl, intf_init(), intf_plug_plug(), fc_ulp::link, fcp_command::list, list_add, memcpy(), NULL, param, fc_ulp::param, fc_ulp::param_len, fc_ulp::peer, fc_peer::port, fc_peer::port_id, fcp_command::process, process_init_stopped(), fc_link_state::rc, rc, ref_init, ref_put, fcp_command::refcnt, fcp_command::scsi, strerror(), fc_ulp_user::ulp, fcp_device::user, fcp_command::xchg, fcp_command::xchg_id, and zalloc().

                                                            {
        struct fcp_prli_service_parameters *param = fcpdev->user.ulp->param;
        struct fcp_command *fcpcmd;
        int xchg_id;
        int rc;

        /* Check link */
        if ( ( rc = fcpdev->user.ulp->link.rc ) != 0 ) {
                DBGC ( fcpdev, "FCP %p could not issue command while link is "
                       "down: %s\n", fcpdev, strerror ( rc ) );
                goto err_link;
        }

        /* Check target capability */
        assert ( param != NULL );
        assert ( fcpdev->user.ulp->param_len >= sizeof ( *param ) );
        if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
                DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
                       fcpdev );
                rc = -ENOTTY;
                goto err_target;
        }

        /* Allocate and initialise structure */
        fcpcmd = zalloc ( sizeof ( *fcpcmd ) );
        if ( ! fcpcmd ) {
                rc = -ENOMEM;
                goto err_zalloc;
        }
        ref_init ( &fcpcmd->refcnt, fcpcmd_free );
        intf_init ( &fcpcmd->scsi, &fcpcmd_scsi_desc, &fcpcmd->refcnt );
        intf_init ( &fcpcmd->xchg, &fcpcmd_xchg_desc, &fcpcmd->refcnt );
        process_init_stopped ( &fcpcmd->process, &fcpcmd_process_desc,
                               &fcpcmd->refcnt );
        fcpcmd->fcpdev = fcpdev_get ( fcpdev );
        list_add ( &fcpcmd->list, &fcpdev->fcpcmds );
        memcpy ( &fcpcmd->command, command, sizeof ( fcpcmd->command ) );

        /* Create new exchange */
        if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
                                             fcpdev->user.ulp->peer->port,
                                             &fcpdev->user.ulp->peer->port_id,
                                             FC_TYPE_FCP ) ) < 0 ) {
                rc = xchg_id;
                DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
                       fcpdev, strerror ( rc ) );
                goto err_xchg_originate;
        }
        fcpcmd->xchg_id = xchg_id;

        /* Start sending command IU */
        fcpcmd_start_send ( fcpcmd, fcpcmd_send_cmnd );

        /* Attach to parent interface, mortalise self, and return */
        intf_plug_plug ( &fcpcmd->scsi, parent );
        ref_put ( &fcpcmd->refcnt );
        return ( FCP_TAG_MAGIC | fcpcmd->xchg_id );

 err_xchg_originate:
        fcpcmd_close ( fcpcmd, rc );
        ref_put ( &fcpcmd->refcnt );
 err_zalloc:
 err_target:
 err_link:
        return rc;
}
static void fcpdev_close ( struct fcp_device fcpdev,
int  rc 
) [static]

Close FCP device.

Parameters:
fcpdevFCP device
rcReason for close

Definition at line 815 of file fcp.c.

References DBGC, fc_ulp_detach(), fcpcmd_close(), fcpcmd_get(), fcpcmd_put(), fcp_device::fcpcmds, intf_shutdown(), fcp_command::list, list_for_each_entry_safe, fcp_device::scsi, strerror(), and fcp_device::user.

Referenced by fcpdev_open().

                                                               {
        struct fcp_command *fcpcmd;
        struct fcp_command *tmp;

        DBGC ( fcpdev, "FCP %p closed: %s\n", fcpdev, strerror ( rc ) );

        /* Shut down interfaces */
        intf_shutdown ( &fcpdev->scsi, rc );

        /* Shut down any active commands */
        list_for_each_entry_safe ( fcpcmd, tmp, &fcpdev->fcpcmds, list ) {
                fcpcmd_get ( fcpcmd );
                fcpcmd_close ( fcpcmd, rc );
                fcpcmd_put ( fcpcmd );
        }

        /* Drop reference to ULP */
        fc_ulp_detach ( &fcpdev->user );
}
static size_t fcpdev_window ( struct fcp_device fcpdev) [static]

Check FCP device flow-control window.

Parameters:
fcpdevFCP device
Return values:
lenLength of window

Definition at line 841 of file fcp.c.

References fc_link_ok(), fc_ulp::link, fc_ulp_user::ulp, and fcp_device::user.

                                                          {
        return ( fc_link_ok ( &fcpdev->user.ulp->link ) ?
                 ~( ( size_t ) 0 ) : 0 );
}
static int fcpdev_edd_describe ( struct fcp_device fcpdev,
struct edd_interface_type type,
union edd_device_path path 
) [static]

Describe FCP device using EDD.

Parameters:
fcpdevFCP device
typeEDD interface type
pathEDD device path
Return values:
rcReturn status code

Definition at line 854 of file fcp.c.

References be64_to_cpu, cpu_to_le64, EDD_INTF_TYPE_FIBRE, edd_device_path::lun, lun, fcp_device::lun, memcpy(), edd_interface_type::type, edd_device_path::wwn, wwn, and fcp_device::wwn.

                                                               {
        union {
                struct fc_name fc;
                uint64_t u64;
        } wwn;
        union {
                struct scsi_lun scsi;
                uint64_t u64;
        } lun;

        type->type = cpu_to_le64 ( EDD_INTF_TYPE_FIBRE );
        memcpy ( &wwn.fc, &fcpdev->wwn, sizeof ( wwn.fc ) );
        path->fibre.wwn = be64_to_cpu ( wwn.u64 );
        memcpy ( &lun.scsi, &fcpdev->lun, sizeof ( lun.scsi ) );
        path->fibre.lun = be64_to_cpu ( lun.u64 );
        return 0;
}
static struct device* fcpdev_identify_device ( struct fcp_device fcpdev) [static, read]

Identify device underlying FCP device.

Parameters:
fcpdevFCP device
Return values:
deviceUnderlying device

Definition at line 880 of file fcp.c.

References assert, DBGC, fc_link_ok(), identify_device(), fc_ulp::link, NULL, fc_ulp::peer, fc_peer::port, fc_port::transport, fc_ulp_user::ulp, and fcp_device::user.

                                                                            {

        /* We know the underlying device only if the link is up;
         * otherwise we don't have a port to examine.
         */
        if ( ! fc_link_ok ( &fcpdev->user.ulp->link ) ) {
                DBGC ( fcpdev, "FCP %p doesn't know underlying device "
                       "until link is up\n", fcpdev );
                return NULL;
        }

        /* Hand off to port's transport interface */
        assert ( fcpdev->user.ulp->peer->port != NULL );
        return identify_device ( &fcpdev->user.ulp->peer->port->transport );
}
static void fcpdev_examine ( struct fc_ulp_user user) [static]

Examine FCP ULP link state.

Parameters:
userFibre Channel upper-layer protocol user

Definition at line 915 of file fcp.c.

References container_of, DBGC, fc_link_ok(), fc_ulp::link, fc_link_state::rc, fcp_device::scsi, strerror(), fc_ulp_user::ulp, fcp_device::user, and xfer_window_changed().

Referenced by fcpdev_open().

                                                        {
        struct fcp_device *fcpdev =
                container_of ( user, struct fcp_device, user );

        if ( fc_link_ok ( &fcpdev->user.ulp->link ) ) {
                DBGC ( fcpdev, "FCP %p link is up\n", fcpdev );
        } else {
                DBGC ( fcpdev, "FCP %p link is down: %s\n",
                       fcpdev, strerror ( fcpdev->user.ulp->link.rc ) );
        }

        /* Notify SCSI layer of window change */
        xfer_window_changed ( &fcpdev->scsi );
}
static int fcpdev_open ( struct interface parent,
struct fc_name wwn,
struct scsi_lun lun 
) [static]

Open FCP device.

Parameters:
parentParent interface
wwnFibre Channel WWN
lunSCSI LUN
Return values:
rcReturn status code

Definition at line 938 of file fcp.c.

References DBGC, ENOMEM, fc_ntoa(), FC_TYPE_FCP, fc_ulp_attach(), fc_ulp_get_wwn_type(), fc_ulp_put(), fc_ulp_user_init(), fcp_device::fcpcmds, fcpdev_close(), fcpdev_examine(), INIT_LIST_HEAD, intf_init(), fcp_device::lun, memcpy(), NULL, rc, ref_init, ref_put, fcp_device::refcnt, fcp_device::scsi, scsi_open(), strerror(), fcp_device::user, fcp_device::wwn, and zalloc().

Referenced by fcp_open().

                                                {
        struct fc_ulp *ulp;
        struct fcp_device *fcpdev;
        int rc;

        /* Get Fibre Channel ULP interface */
        ulp = fc_ulp_get_wwn_type ( wwn, FC_TYPE_FCP );
        if ( ! ulp ) {
                rc = -ENOMEM;
                goto err_ulp_get;
        }

        /* Allocate and initialise structure */
        fcpdev = zalloc ( sizeof ( *fcpdev ) );
        if ( ! fcpdev ) {
                rc = -ENOMEM;
                goto err_zalloc;
        }
        ref_init ( &fcpdev->refcnt, NULL );
        intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
        INIT_LIST_HEAD ( &fcpdev->fcpcmds );
        fc_ulp_user_init ( &fcpdev->user, fcpdev_examine, &fcpdev->refcnt );

        DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );

        /* Attach to Fibre Channel ULP */
        fc_ulp_attach ( ulp, &fcpdev->user );

        /* Preserve parameters required for boot firmware table */
        memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
        memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );

        /* Attach SCSI device to parent interface */
        if ( ( rc = scsi_open ( parent, &fcpdev->scsi, lun ) ) != 0 ) {
                DBGC ( fcpdev, "FCP %p could not create SCSI device: %s\n",
                       fcpdev, strerror ( rc ) );
                goto err_scsi_open;
        }

        /* Drop temporary reference to ULP */
        fc_ulp_put ( ulp );

        /* Mortalise self and return */
        ref_put ( &fcpdev->refcnt );
        return 0;

 err_scsi_open:
        fcpdev_close ( fcpdev, rc );
        ref_put ( &fcpdev->refcnt );
 err_zalloc:
        fc_ulp_put ( ulp );
 err_ulp_get:
        return rc;
}
static int fcp_parse_uri ( struct uri uri,
struct fc_name wwn,
struct scsi_lun lun 
) [static]

Parse FCP URI.

Parameters:
uriURI
Return values:
wwnFibre Channel WWN
lunSCSI LUN
rcReturn status code

An FCP URI has the form "fcp:<wwn>:<lun>" or "fcp://<wwn>/<lun>"

Definition at line 1011 of file fcp.c.

References EINVAL, fc_aton(), FC_NAME_STRLEN, uri::host, uri::opaque, uri::path, rc, scsi_parse_lun(), and snprintf().

Referenced by fcp_open().

                                                  {
        char wwn_buf[ FC_NAME_STRLEN + 1 /* NUL */ ];
        const char *wwn_text;
        const char *lun_text;
        int rc;

        /* Extract WWN and LUN texts from URI */
        if ( uri->opaque ) {
                /* "fcp:<wwn>:<lun>" */
                if ( snprintf ( wwn_buf, sizeof ( wwn_buf ), "%s",
                                uri->opaque ) < ( FC_NAME_STRLEN + 1 /* : */ ) )
                        return -EINVAL;
                if ( uri->opaque[FC_NAME_STRLEN] != ':' )
                        return -EINVAL;
                wwn_text = wwn_buf;
                lun_text = &uri->opaque[FC_NAME_STRLEN + 1];
        } else {
                /* If host exists, path must also exist */
                if ( ! ( uri->host && uri->path ) )
                        return -EINVAL;
                if ( uri->path[0] != '/' )
                        return -EINVAL;
                wwn_text = uri->host;
                lun_text = ( uri->path + 1 );
        }

        /* Parse WWN */
        if ( ( rc = fc_aton ( wwn_text, wwn ) ) != 0 )
                return rc;

        /* Parse LUN */
        if ( ( rc = scsi_parse_lun ( lun_text, lun ) ) != 0 )
                return rc;

        return 0;
}
static int fcp_open ( struct interface parent,
struct uri uri 
) [static]

Open FCP URI.

Parameters:
parentParent interface
uriURI
Return values:
rcReturn status code

Definition at line 1056 of file fcp.c.

References fcp_parse_uri(), fcpdev_open(), and rc.

                                                                  {
        struct fc_name wwn;
        struct scsi_lun lun;
        int rc;

        /* Parse URI */
        if ( ( rc = fcp_parse_uri ( uri, &wwn, &lun ) ) != 0 )
                return rc;

        /* Open FCP device */
        if ( ( rc = fcpdev_open ( parent, &wwn, &lun ) ) != 0 )
                return rc;

        return 0;
}

Variable Documentation

Initial value:
 {
        .type           = FC_TYPE_FCP,
        .param_len      = sizeof ( struct fcp_prli_service_parameters ),
        .handler        = &fcp_prli_handler,
}

FCP PRLI descriptor.

Definition at line 85 of file fcp.c.

struct fc_els_handler fcp_prli_handler __fc_els_handler
Initial value:
 {
        .name           = "PRLI-FCP",
        .tx             = fcp_prli_tx,
        .rx             = fcp_prli_rx,
        .detect         = fcp_prli_detect,
}

FCP PRLI ELS handler.

Definition at line 129 of file fcp.c.

Initial value:

FCP command SCSI interface operations.

Definition at line 710 of file fcp.c.

Initial value:

FCP command SCSI interface descriptor.

Definition at line 715 of file fcp.c.

Initial value:

FCP command Fibre Channel exchange interface operations.

Definition at line 719 of file fcp.c.

Initial value:

FCP command Fibre Channel exchange interface descriptor.

Definition at line 725 of file fcp.c.

Initial value:

FCP command process descriptor.

Definition at line 729 of file fcp.c.

Initial value:

FCP device SCSI interface operations.

Definition at line 897 of file fcp.c.

Initial value:
        INTF_DESC ( struct fcp_device, scsi, fcpdev_scsi_op )

FCP device SCSI interface descriptor.

Definition at line 907 of file fcp.c.

struct uri_opener fcp_uri_opener __uri_opener
Initial value:
 {
        .scheme = "fcp",
        .open = fcp_open,
}

FCP URI opener.

Definition at line 1073 of file fcp.c.