iPXE
Data Structures | Defines | Enumerations | Functions | Variables
scsi.c File Reference

SCSI block device. More...

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <byteswap.h>
#include <errno.h>
#include <ipxe/list.h>
#include <ipxe/process.h>
#include <ipxe/xfer.h>
#include <ipxe/blockdev.h>
#include <ipxe/scsi.h>

Go to the source code of this file.

Data Structures

struct  scsi_device
 A SCSI device. More...
struct  scsi_command
 A SCSI command. More...
struct  scsi_command_type
 A SCSI command type. More...
struct  scsi_read_capacity_private
 SCSI READ CAPACITY private data. More...

Defines

#define SCSI_READY_MAX_RETRIES   10
 Maximum number of TEST UNIT READY retries.
#define EIO_NO_SENSE   __einfo_error ( EINFO_EIO_NO_SENSE )
#define EINFO_EIO_NO_SENSE   __einfo_uniqify ( EINFO_EIO, 0x00, "No sense" )
#define EIO_RECOVERED_ERROR   __einfo_error ( EINFO_EIO_RECOVERED_ERROR )
#define EINFO_EIO_RECOVERED_ERROR   __einfo_uniqify ( EINFO_EIO, 0x01, "Recovered error" )
#define EIO_NOT_READY   __einfo_error ( EINFO_EIO_NOT_READY )
#define EINFO_EIO_NOT_READY   __einfo_uniqify ( EINFO_EIO, 0x02, "Not ready" )
#define EIO_MEDIUM_ERROR   __einfo_error ( EINFO_EIO_MEDIUM_ERROR )
#define EINFO_EIO_MEDIUM_ERROR   __einfo_uniqify ( EINFO_EIO, 0x03, "Medium error" )
#define EIO_HARDWARE_ERROR   __einfo_error ( EINFO_EIO_HARDWARE_ERROR )
#define EINFO_EIO_HARDWARE_ERROR   __einfo_uniqify ( EINFO_EIO, 0x04, "Hardware error" )
#define EIO_ILLEGAL_REQUEST   __einfo_error ( EINFO_EIO_ILLEGAL_REQUEST )
#define EINFO_EIO_ILLEGAL_REQUEST   __einfo_uniqify ( EINFO_EIO, 0x05, "Illegal request" )
#define EIO_UNIT_ATTENTION   __einfo_error ( EINFO_EIO_UNIT_ATTENTION )
#define EINFO_EIO_UNIT_ATTENTION   __einfo_uniqify ( EINFO_EIO, 0x06, "Unit attention" )
#define EIO_DATA_PROTECT   __einfo_error ( EINFO_EIO_DATA_PROTECT )
#define EINFO_EIO_DATA_PROTECT   __einfo_uniqify ( EINFO_EIO, 0x07, "Data protect" )
#define EIO_BLANK_CHECK   __einfo_error ( EINFO_EIO_BLANK_CHECK )
#define EINFO_EIO_BLANK_CHECK   __einfo_uniqify ( EINFO_EIO, 0x08, "Blank check" )
#define EIO_VENDOR_SPECIFIC   __einfo_error ( EINFO_EIO_VENDOR_SPECIFIC )
#define EINFO_EIO_VENDOR_SPECIFIC   __einfo_uniqify ( EINFO_EIO, 0x09, "Vendor specific" )
#define EIO_COPY_ABORTED   __einfo_error ( EINFO_EIO_COPY_ABORTED )
#define EINFO_EIO_COPY_ABORTED   __einfo_uniqify ( EINFO_EIO, 0x0a, "Copy aborted" )
#define EIO_ABORTED_COMMAND   __einfo_error ( EINFO_EIO_ABORTED_COMMAND )
#define EINFO_EIO_ABORTED_COMMAND   __einfo_uniqify ( EINFO_EIO, 0x0b, "Aborted command" )
#define EIO_RESERVED   __einfo_error ( EINFO_EIO_RESERVED )
#define EINFO_EIO_RESERVED   __einfo_uniqify ( EINFO_EIO, 0x0c, "Reserved" )
#define EIO_VOLUME_OVERFLOW   __einfo_error ( EINFO_EIO_VOLUME_OVERFLOW )
#define EINFO_EIO_VOLUME_OVERFLOW   __einfo_uniqify ( EINFO_EIO, 0x0d, "Volume overflow" )
#define EIO_MISCOMPARE   __einfo_error ( EINFO_EIO_MISCOMPARE )
#define EINFO_EIO_MISCOMPARE   __einfo_uniqify ( EINFO_EIO, 0x0e, "Miscompare" )
#define EIO_COMPLETED   __einfo_error ( EINFO_EIO_COMPLETED )
#define EINFO_EIO_COMPLETED   __einfo_uniqify ( EINFO_EIO, 0x0f, "Completed" )
#define EIO_SENSE(key)

Enumerations

enum  scsi_device_flags { SCSIDEV_UNIT_TESTED = 0x0001, SCSIDEV_UNIT_READY = 0x0002 }
 SCSI device flags. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int scsi_parse_lun (const char *lun_string, struct scsi_lun *lun)
 Parse SCSI LUN.
void scsi_parse_sense (const void *data, size_t len, struct scsi_sns_descriptor *sense)
 Parse SCSI sense data.
int scsi_command (struct interface *control, struct interface *data, struct scsi_cmd *command)
 Issue SCSI command.
void scsi_response (struct interface *intf, struct scsi_rsp *response)
 Report SCSI response.
static struct scsi_devicescsidev_get (struct scsi_device *scsidev)
 Get reference to SCSI device.
static void scsidev_put (struct scsi_device *scsidev)
 Drop reference to SCSI device.
static struct scsi_commandscsicmd_get (struct scsi_command *scsicmd)
 Get reference to SCSI command.
static void scsicmd_put (struct scsi_command *scsicmd)
 Drop reference to SCSI command.
static void * scsicmd_priv (struct scsi_command *scsicmd)
 Get SCSI command private data.
static void scsicmd_free (struct refcnt *refcnt)
 Free SCSI command.
static void scsicmd_close (struct scsi_command *scsicmd, int rc)
 Close SCSI command.
static int scsicmd_command (struct scsi_command *scsicmd)
 Construct and issue SCSI command.
static void scsicmd_done (struct scsi_command *scsicmd, int rc)
 Handle SCSI command completion.
static void scsicmd_response (struct scsi_command *scsicmd, struct scsi_rsp *response)
 Handle SCSI response.
static void scsicmd_read_cmd (struct scsi_command *scsicmd, struct scsi_cmd *command)
 Construct SCSI READ command.
static void scsicmd_write_cmd (struct scsi_command *scsicmd, struct scsi_cmd *command)
 Construct SCSI WRITE command.
static void scsicmd_read_capacity_cmd (struct scsi_command *scsicmd, struct scsi_cmd *command)
 Construct SCSI READ CAPACITY command.
static void scsicmd_read_capacity_done (struct scsi_command *scsicmd, int rc)
 Handle SCSI READ CAPACITY command completion.
static void scsicmd_test_unit_ready_cmd (struct scsi_command *scsicmd __unused, struct scsi_cmd *command)
 Construct SCSI TEST UNIT READY command.
static int scsidev_command (struct scsi_device *scsidev, struct interface *block, struct scsi_command_type *type, uint64_t lba, unsigned int count, userptr_t buffer, size_t len)
 Create SCSI command.
static int scsidev_read (struct scsi_device *scsidev, struct interface *block, uint64_t lba, unsigned int count, userptr_t buffer, size_t len)
 Issue SCSI block read.
static int scsidev_write (struct scsi_device *scsidev, struct interface *block, uint64_t lba, unsigned int count, userptr_t buffer, size_t len)
 Issue SCSI block write.
static int scsidev_read_capacity (struct scsi_device *scsidev, struct interface *block)
 Read SCSI device capacity.
static int scsidev_test_unit_ready (struct scsi_device *scsidev, struct interface *block)
 Test to see if SCSI device is ready.
static size_t scsidev_window (struct scsi_device *scsidev)
 Check SCSI device flow-control window.
static void scsidev_close (struct scsi_device *scsidev, int rc)
 Close SCSI device.
static void scsidev_ready (struct scsi_device *scsidev, int rc)
 Handle SCSI TEST UNIT READY response.
static void scsidev_step (struct scsi_device *scsidev)
 SCSI TEST UNIT READY process.
int scsi_open (struct interface *block, struct interface *scsi, struct scsi_lun *lun)
 Open SCSI device.

Variables

static struct scsi_command_type scsicmd_read
 SCSI READ command type.
static struct scsi_command_type scsicmd_write
 SCSI WRITE command type.
static struct scsi_command_type scsicmd_read_capacity
 SCSI READ CAPACITY command type.
static struct scsi_command_type scsicmd_test_unit_ready
 SCSI TEST UNIT READY command type.
static struct interface_operation scsicmd_block_op []
 SCSI command block interface operations.
static struct interface_descriptor scsicmd_block_desc
 SCSI command block interface descriptor.
static struct interface_operation scsicmd_scsi_op []
 SCSI command SCSI interface operations.
static struct interface_descriptor scsicmd_scsi_desc
 SCSI command SCSI interface descriptor.
static struct interface_operation scsidev_block_op []
 SCSI device block interface operations.
static struct interface_descriptor scsidev_block_desc
 SCSI device block interface descriptor.
static struct interface_operation scsidev_ready_op []
 SCSI device TEST UNIT READY interface operations.
static struct interface_descriptor scsidev_ready_desc
 SCSI device TEST UNIT READY interface descriptor.
static struct interface_operation scsidev_scsi_op []
 SCSI device SCSI interface operations.
static struct interface_descriptor scsidev_scsi_desc
 SCSI device SCSI interface descriptor.
static struct process_descriptor scsidev_process_desc
 SCSI device process descriptor.

Detailed Description

SCSI block device.

Definition in file scsi.c.


Define Documentation

#define SCSI_READY_MAX_RETRIES   10

Maximum number of TEST UNIT READY retries.

Definition at line 44 of file scsi.c.

Referenced by scsidev_ready().

Definition at line 47 of file scsi.c.

#define EINFO_EIO_NO_SENSE   __einfo_uniqify ( EINFO_EIO, 0x00, "No sense" )

Definition at line 48 of file scsi.c.

Definition at line 50 of file scsi.c.

#define EINFO_EIO_RECOVERED_ERROR   __einfo_uniqify ( EINFO_EIO, 0x01, "Recovered error" )

Definition at line 51 of file scsi.c.

Definition at line 53 of file scsi.c.

#define EINFO_EIO_NOT_READY   __einfo_uniqify ( EINFO_EIO, 0x02, "Not ready" )

Definition at line 54 of file scsi.c.

Definition at line 56 of file scsi.c.

#define EINFO_EIO_MEDIUM_ERROR   __einfo_uniqify ( EINFO_EIO, 0x03, "Medium error" )

Definition at line 57 of file scsi.c.

Definition at line 59 of file scsi.c.

#define EINFO_EIO_HARDWARE_ERROR   __einfo_uniqify ( EINFO_EIO, 0x04, "Hardware error" )

Definition at line 60 of file scsi.c.

Definition at line 62 of file scsi.c.

#define EINFO_EIO_ILLEGAL_REQUEST   __einfo_uniqify ( EINFO_EIO, 0x05, "Illegal request" )

Definition at line 63 of file scsi.c.

Definition at line 65 of file scsi.c.

#define EINFO_EIO_UNIT_ATTENTION   __einfo_uniqify ( EINFO_EIO, 0x06, "Unit attention" )

Definition at line 66 of file scsi.c.

Definition at line 68 of file scsi.c.

#define EINFO_EIO_DATA_PROTECT   __einfo_uniqify ( EINFO_EIO, 0x07, "Data protect" )

Definition at line 69 of file scsi.c.

Definition at line 71 of file scsi.c.

#define EINFO_EIO_BLANK_CHECK   __einfo_uniqify ( EINFO_EIO, 0x08, "Blank check" )

Definition at line 72 of file scsi.c.

Definition at line 74 of file scsi.c.

#define EINFO_EIO_VENDOR_SPECIFIC   __einfo_uniqify ( EINFO_EIO, 0x09, "Vendor specific" )

Definition at line 75 of file scsi.c.

Definition at line 77 of file scsi.c.

#define EINFO_EIO_COPY_ABORTED   __einfo_uniqify ( EINFO_EIO, 0x0a, "Copy aborted" )

Definition at line 78 of file scsi.c.

Definition at line 80 of file scsi.c.

#define EINFO_EIO_ABORTED_COMMAND   __einfo_uniqify ( EINFO_EIO, 0x0b, "Aborted command" )

Definition at line 81 of file scsi.c.

Definition at line 83 of file scsi.c.

#define EINFO_EIO_RESERVED   __einfo_uniqify ( EINFO_EIO, 0x0c, "Reserved" )

Definition at line 84 of file scsi.c.

Definition at line 86 of file scsi.c.

#define EINFO_EIO_VOLUME_OVERFLOW   __einfo_uniqify ( EINFO_EIO, 0x0d, "Volume overflow" )

Definition at line 87 of file scsi.c.

Definition at line 89 of file scsi.c.

#define EINFO_EIO_MISCOMPARE   __einfo_uniqify ( EINFO_EIO, 0x0e, "Miscompare" )

Definition at line 90 of file scsi.c.

Definition at line 92 of file scsi.c.

#define EINFO_EIO_COMPLETED   __einfo_uniqify ( EINFO_EIO, 0x0f, "Completed" )

Definition at line 93 of file scsi.c.

#define EIO_SENSE (   key)

Enumeration Type Documentation

SCSI device flags.

Enumerator:
SCSIDEV_UNIT_TESTED 

TEST UNIT READY has been issued.

SCSIDEV_UNIT_READY 

TEST UNIT READY has completed successfully.

Definition at line 254 of file scsi.c.

                       {
        /** TEST UNIT READY has been issued */
        SCSIDEV_UNIT_TESTED = 0x0001,
        /** TEST UNIT READY has completed successfully */
        SCSIDEV_UNIT_READY = 0x0002,
};

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
int scsi_parse_lun ( const char *  lun_string,
struct scsi_lun lun 
)

Parse SCSI LUN.

Parameters:
lun_stringLUN string representation
lunLUN to fill in
Return values:
rcReturn status code

Definition at line 117 of file scsi.c.

References EINVAL, htons, memset(), strtoul(), and scsi_lun::u16.

Referenced by fcp_parse_uri(), ib_srp_parse_lun(), and iscsi_parse_root_path().

                                                                    {
        char *p;
        int i;

        memset ( lun, 0, sizeof ( *lun ) );
        if ( lun_string ) {
                p = ( char * ) lun_string;
                for ( i = 0 ; i < 4 ; i++ ) {
                        lun->u16[i] = htons ( strtoul ( p, &p, 16 ) );
                        if ( *p == '\0' )
                                break;
                        if ( *p != '-' )
                                return -EINVAL;
                        p++;
                }
                if ( *p )
                        return -EINVAL;
        }

        return 0;
}
void scsi_parse_sense ( const void *  data,
size_t  len,
struct scsi_sns_descriptor sense 
)

Parse SCSI sense data.

Parameters:
dataRaw sense data
lenLength of raw sense data
senseDescriptor-format sense data to fill in

Definition at line 146 of file scsi.c.

References scsi_sns_fixed::additional, scsi_sns_descriptor::additional, scsi_sns::code, data, scsi_sns::desc, scsi_sns::fixed, memcpy(), memset(), and SCSI_SENSE_FIXED.

Referenced by fcpcmd_recv_rsp(), iscsi_rx_scsi_response(), and srp_rsp().

                                                            {
        const union scsi_sns *sns = data;

        /* Avoid returning uninitialised data */
        memset ( sense, 0, sizeof ( *sense ) );

        /* Copy, assuming descriptor-format data */
        if ( len < sizeof ( sns->desc ) )
                return;
        memcpy ( sense, &sns->desc, sizeof ( *sense ) );

        /* Convert fixed-format to descriptor-format, if applicable */
        if ( len < sizeof ( sns->fixed ) )
                return;
        if ( ! SCSI_SENSE_FIXED ( sns->code ) )
                return;
        sense->additional = sns->fixed.additional;
}
int scsi_command ( struct interface control,
struct interface data,
struct scsi_cmd command 
)

Issue SCSI command.

Parameters:
controlSCSI control interface
dataSCSI data interface
commandSCSI command
Return values:
tagCommand tag, or negative error

Definition at line 181 of file scsi.c.

References dest, EOPNOTSUPP, intf_get_dest_op, intf_object(), intf_put(), op, and scsi_command_TYPE.

                                              {
        struct interface *dest;
        scsi_command_TYPE ( void * ) *op =
                intf_get_dest_op ( control, scsi_command, &dest );
        void *object = intf_object ( dest );
        int tap;

        if ( op ) {
                tap = op ( object, data, command );
        } else {
                /* Default is to fail to issue the command */
                tap = -EOPNOTSUPP;
        }

        intf_put ( dest );
        return tap;
}
void scsi_response ( struct interface intf,
struct scsi_rsp response 
)

Report SCSI response.

Parameters:
interfaceSCSI command interface
responseSCSI response

Definition at line 206 of file scsi.c.

References dest, intf_get_dest_op, intf_object(), intf_put(), op, scsi_response(), and scsi_response_TYPE.

Referenced by fcpcmd_recv_rsp(), iscsi_scsi_done(), scsi_response(), and srp_rsp().

                                                                         {
        struct interface *dest;
        scsi_response_TYPE ( void * ) *op =
                intf_get_dest_op ( intf, scsi_response, &dest );
        void *object = intf_object ( dest );

        if ( op ) {
                op ( object, response );
        } else {
                /* Default is to ignore the response */
        }

        intf_put ( dest );
}
static struct scsi_device* scsidev_get ( struct scsi_device scsidev) [static, read]

Get reference to SCSI device.

Parameters:
scsidevSCSI device
Return values:
scsidevSCSI device

Definition at line 322 of file scsi.c.

References ref_get, and scsi_command::scsidev.

Referenced by scsidev_command().

                                            {
        ref_get ( &scsidev->refcnt );
        return scsidev;
}
static void scsidev_put ( struct scsi_device scsidev) [inline, static]

Drop reference to SCSI device.

Parameters:
scsidevSCSI device

Definition at line 333 of file scsi.c.

References ref_put.

Referenced by scsicmd_free().

                                            {
        ref_put ( &scsidev->refcnt );
}
static struct scsi_command* scsicmd_get ( struct scsi_command scsicmd) [static, read]

Get reference to SCSI command.

Parameters:
scsicmdSCSI command
Return values:
scsicmdSCSI command

Definition at line 344 of file scsi.c.

References ref_get.

                                             {
        ref_get ( &scsicmd->refcnt );
        return scsicmd;
}
static void scsicmd_put ( struct scsi_command scsicmd) [inline, static]

Drop reference to SCSI command.

Parameters:
scsicmdSCSI command

Definition at line 355 of file scsi.c.

References ref_put.

Referenced by scsicmd_close().

                                             {
        ref_put ( &scsicmd->refcnt );
}
static void* scsicmd_priv ( struct scsi_command scsicmd) [inline, static]

Get SCSI command private data.

Parameters:
scsicmdSCSI command
Return values:
privPrivate data

Definition at line 366 of file scsi.c.

Referenced by scsicmd_read_capacity_cmd(), and scsicmd_read_capacity_done().

                                              {
        return scsicmd->priv;
}
static void scsicmd_free ( struct refcnt refcnt) [static]

Free SCSI command.

Parameters:
refcntReference count

Definition at line 375 of file scsi.c.

References container_of, free, scsi_command::scsidev, and scsidev_put().

Referenced by scsidev_command().

                                                   {
        struct scsi_command *scsicmd =
                container_of ( refcnt, struct scsi_command, refcnt );

        /* Drop reference to SCSI device */
        scsidev_put ( scsicmd->scsidev );

        /* Free command */
        free ( scsicmd );
}
static void scsicmd_close ( struct scsi_command scsicmd,
int  rc 
) [static]

Close SCSI command.

Parameters:
scsicmdSCSI command
rcReason for close

Definition at line 392 of file scsi.c.

References scsi_command::block, DBGC, intfs_shutdown(), scsi_command::list, list_del, NULL, scsi_command::scsi, scsicmd_put(), scsi_command::scsidev, strerror(), and scsi_command::tag.

Referenced by scsicmd_read_capacity_done(), scsidev_close(), and scsidev_command().

                                                                   {
        struct scsi_device *scsidev = scsicmd->scsidev;

        if ( rc != 0 ) {
                DBGC ( scsidev, "SCSI %p tag %08x closed: %s\n",
                       scsidev, scsicmd->tag, strerror ( rc ) );
        }

        /* Remove from list of commands */
        list_del ( &scsicmd->list );

        /* Shut down interfaces */
        intfs_shutdown ( rc, &scsicmd->scsi, &scsicmd->block, NULL );

        /* Drop list's reference */
        scsicmd_put ( scsicmd );
}
static int scsicmd_command ( struct scsi_command scsicmd) [static]

Construct and issue SCSI command.

Return values:
rcReturn status code

Definition at line 415 of file scsi.c.

References scsi_cmd::cdb, scsi_command_type::cmd, DBGC, DBGC2, scsi_device::lun, scsi_cmd::lun, memcpy(), memset(), scsi_command_type::name, rc, scsi_device::scsi, scsi_command::scsi, SCSI_CDB_DATA, SCSI_CDB_FORMAT, scsi_command::scsidev, strerror(), tag, scsi_command::tag, and scsi_command::type.

Referenced by scsicmd_read_capacity_done(), and scsidev_command().

                                                            {
        struct scsi_device *scsidev = scsicmd->scsidev;
        struct scsi_cmd command;
        int tag;
        int rc;

        /* Construct command */
        memset ( &command, 0, sizeof ( command ) );
        memcpy ( &command.lun, &scsidev->lun, sizeof ( command.lun ) );
        scsicmd->type->cmd ( scsicmd, &command );

        /* Issue command */
        if ( ( tag = scsi_command ( &scsidev->scsi, &scsicmd->scsi,
                                    &command ) ) < 0 ) {
                rc = tag;
                DBGC ( scsidev, "SCSI %p could not issue command: %s\n",
                       scsidev, strerror ( rc ) );
                return rc;
        }

        /* Record tag */
        if ( scsicmd->tag ) {
                DBGC ( scsidev, "SCSI %p tag %08x is now tag %08x\n",
                       scsidev, scsicmd->tag, tag );
        }
        scsicmd->tag = tag;
        DBGC2 ( scsidev, "SCSI %p tag %08x %s " SCSI_CDB_FORMAT "\n",
                scsidev, scsicmd->tag, scsicmd->type->name,
                SCSI_CDB_DATA ( command.cdb ) );

        return 0;
}
static void scsicmd_done ( struct scsi_command scsicmd,
int  rc 
) [static]

Handle SCSI command completion.

Parameters:
scsicmdSCSI command
rcReason for close

Definition at line 454 of file scsi.c.

References scsi_command_type::done, intf_restart(), scsi_command::scsi, and scsi_command::type.

Referenced by scsicmd_response().

                                                                  {

        /* Restart SCSI interface */
        intf_restart ( &scsicmd->scsi, rc );

        /* Hand over to the command completion handler */
        scsicmd->type->done ( scsicmd, rc );
}
static void scsicmd_response ( struct scsi_command scsicmd,
struct scsi_rsp response 
) [static]

Handle SCSI response.

Parameters:
scsicmdSCSI command
responseSCSI response

Definition at line 469 of file scsi.c.

References scsi_sns_descriptor::additional, scsi_sns_descriptor::code, DBGC, EIO_SENSE, scsi_sns_descriptor::key, ntohs, scsi_rsp::overrun, rc, SCSI_SENSE_CODE_MASK, SCSI_SENSE_KEY_MASK, scsicmd_done(), scsi_command::scsidev, scsi_rsp::sense, scsi_rsp::status, and scsi_command::tag.

                                                           {
        struct scsi_device *scsidev = scsicmd->scsidev;
        size_t overrun;
        size_t underrun;
        int rc;

        if ( response->status == 0 ) {
                scsicmd_done ( scsicmd, 0 );
        } else {
                DBGC ( scsidev, "SCSI %p tag %08x status %02x",
                       scsidev, scsicmd->tag, response->status );
                if ( response->overrun > 0 ) {
                        overrun = response->overrun;
                        DBGC ( scsidev, " overrun +%zd", overrun );
                } else if ( response->overrun < 0 ) {
                        underrun = -(response->overrun);
                        DBGC ( scsidev, " underrun -%zd", underrun );
                }
                DBGC ( scsidev, " sense %02x key %02x additional %04x\n",
                       ( response->sense.code & SCSI_SENSE_CODE_MASK ),
                       ( response->sense.key & SCSI_SENSE_KEY_MASK ),
                       ntohs ( response->sense.additional ) );

                /* Construct error number from sense data */
                rc = -EIO_SENSE ( response->sense.key & SCSI_SENSE_KEY_MASK );
                scsicmd_done ( scsicmd, rc );
        }
}
static void scsicmd_read_cmd ( struct scsi_command scsicmd,
struct scsi_cmd command 
) [static]

Construct SCSI READ command.

Parameters:
scsicmdSCSI command
commandSCSI command IU

Definition at line 505 of file scsi.c.

References scsi_command::buffer, scsi_cmd::cdb, scsi_command::count, cpu_to_be16, cpu_to_be32, cpu_to_be64, scsi_cmd::data_in, scsi_cmd::data_in_len, scsi_cdb_read_10::lba, scsi_cdb_read_16::lba, scsi_command::lba, scsi_cdb_read_10::len, scsi_cdb_read_16::len, scsi_command::len, scsi_cdb_read_10::opcode, scsi_cdb_read_16::opcode, scsi_cdb::read10, scsi_cdb::read16, SCSI_MAX_BLOCK_10, SCSI_OPCODE_READ_10, and SCSI_OPCODE_READ_16.

                                                          {

        if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) {
                /* Use READ (16) */
                command->cdb.read16.opcode = SCSI_OPCODE_READ_16;
                command->cdb.read16.lba = cpu_to_be64 ( scsicmd->lba );
                command->cdb.read16.len = cpu_to_be32 ( scsicmd->count );
        } else {
                /* Use READ (10) */
                command->cdb.read10.opcode = SCSI_OPCODE_READ_10;
                command->cdb.read10.lba = cpu_to_be32 ( scsicmd->lba );
                command->cdb.read10.len = cpu_to_be16 ( scsicmd->count );
        }
        command->data_in = scsicmd->buffer;
        command->data_in_len = scsicmd->len;
}
static void scsicmd_write_cmd ( struct scsi_command scsicmd,
struct scsi_cmd command 
) [static]

Construct SCSI WRITE command.

Parameters:
scsicmdSCSI command
commandSCSI command IU

Definition at line 536 of file scsi.c.

References scsi_command::buffer, scsi_cmd::cdb, scsi_command::count, cpu_to_be16, cpu_to_be32, cpu_to_be64, scsi_cmd::data_out, scsi_cmd::data_out_len, scsi_cdb_write_10::lba, scsi_cdb_write_16::lba, scsi_command::lba, scsi_cdb_write_10::len, scsi_cdb_write_16::len, scsi_command::len, scsi_cdb_write_10::opcode, scsi_cdb_write_16::opcode, SCSI_MAX_BLOCK_10, SCSI_OPCODE_WRITE_10, SCSI_OPCODE_WRITE_16, scsi_cdb::write10, and scsi_cdb::write16.

                                                           {

        if ( ( scsicmd->lba + scsicmd->count ) > SCSI_MAX_BLOCK_10 ) {
                /* Use WRITE (16) */
                command->cdb.write16.opcode = SCSI_OPCODE_WRITE_16;
                command->cdb.write16.lba = cpu_to_be64 ( scsicmd->lba );
                command->cdb.write16.len = cpu_to_be32 ( scsicmd->count );
        } else {
                /* Use WRITE (10) */
                command->cdb.write10.opcode = SCSI_OPCODE_WRITE_10;
                command->cdb.write10.lba = cpu_to_be32 ( scsicmd->lba );
                command->cdb.write10.len = cpu_to_be16 ( scsicmd->count );
        }
        command->data_out = scsicmd->buffer;
        command->data_out_len = scsicmd->len;
}
static void scsicmd_read_capacity_cmd ( struct scsi_command scsicmd,
struct scsi_cmd command 
) [static]

Construct SCSI READ CAPACITY command.

Parameters:
scsicmdSCSI command
commandSCSI command IU

Definition at line 580 of file scsi.c.

References scsi_read_capacity_private::capacity, scsi_read_capacity_private::capacity10, scsi_read_capacity_private::capacity16, scsi_cmd::cdb, cpu_to_be32, scsi_cmd::data_in, scsi_cmd::data_in_len, scsi_cdb_read_capacity_16::len, scsi_cdb_read_capacity_10::opcode, scsi_cdb_read_capacity_16::opcode, priv, scsi_cdb::readcap10, scsi_cdb::readcap16, SCSI_OPCODE_READ_CAPACITY_10, SCSI_OPCODE_SERVICE_ACTION_IN, SCSI_SERVICE_ACTION_READ_CAPACITY_16, scsicmd_priv(), scsi_cdb_read_capacity_16::service_action, scsi_read_capacity_private::use16, and virt_to_user().

                                                                   {
        struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd );
        struct scsi_cdb_read_capacity_16 *readcap16 = &command->cdb.readcap16;
        struct scsi_cdb_read_capacity_10 *readcap10 = &command->cdb.readcap10;
        struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16;
        struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10;

        if ( priv->use16 ) {
                /* Use READ CAPACITY (16) */
                readcap16->opcode = SCSI_OPCODE_SERVICE_ACTION_IN;
                readcap16->service_action =
                        SCSI_SERVICE_ACTION_READ_CAPACITY_16;
                readcap16->len = cpu_to_be32 ( sizeof ( *capacity16 ) );
                command->data_in = virt_to_user ( capacity16 );
                command->data_in_len = sizeof ( *capacity16 );
        } else {
                /* Use READ CAPACITY (10) */
                readcap10->opcode = SCSI_OPCODE_READ_CAPACITY_10;
                command->data_in = virt_to_user ( capacity10 );
                command->data_in_len = sizeof ( *capacity10 );
        }
}
static void scsicmd_read_capacity_done ( struct scsi_command scsicmd,
int  rc 
) [static]

Handle SCSI READ CAPACITY command completion.

Parameters:
scsicmdSCSI command
rcReason for completion

Definition at line 610 of file scsi.c.

References be32_to_cpu, be64_to_cpu, block_device_capacity::blksize, scsi_capacity_10::blksize, scsi_capacity_16::blksize, scsi_command::block, block_capacity(), block_device_capacity::blocks, scsi_read_capacity_private::capacity, scsi_read_capacity_private::capacity10, scsi_read_capacity_private::capacity16, scsi_capacity_10::lba, scsi_capacity_16::lba, block_device_capacity::max_count, priv, scsicmd_close(), scsicmd_command(), scsicmd_priv(), and scsi_read_capacity_private::use16.

                                                  {
        struct scsi_read_capacity_private *priv = scsicmd_priv ( scsicmd );
        struct scsi_capacity_16 *capacity16 = &priv->capacity.capacity16;
        struct scsi_capacity_10 *capacity10 = &priv->capacity.capacity10;
        struct block_device_capacity capacity;

        /* Close if command failed */
        if ( rc != 0 ) {
                scsicmd_close ( scsicmd, rc );
                return;
        }

        /* Extract capacity */
        if ( priv->use16 ) {
                capacity.blocks = ( be64_to_cpu ( capacity16->lba ) + 1 );
                capacity.blksize = be32_to_cpu ( capacity16->blksize );
        } else {
                capacity.blocks = ( be32_to_cpu ( capacity10->lba ) + 1 );
                capacity.blksize = be32_to_cpu ( capacity10->blksize );

                /* If capacity range was exceeded (i.e. capacity.lba
                 * was 0xffffffff, meaning that blockdev->blocks is
                 * now zero), use READ CAPACITY (16) instead.  READ
                 * CAPACITY (16) is not mandatory, so we can't just
                 * use it straight off.
                 */
                if ( capacity.blocks == 0 ) {
                        priv->use16 = 1;
                        if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 ) {
                                scsicmd_close ( scsicmd, rc );
                                return;
                        }
                        return;
                }
        }
        capacity.max_count = -1U;

        /* Return capacity to caller */
        block_capacity ( &scsicmd->block, &capacity );

        /* Close command */
        scsicmd_close ( scsicmd, 0 );
}
static void scsicmd_test_unit_ready_cmd ( struct scsi_command *scsicmd  __unused,
struct scsi_cmd command 
) [static]

Construct SCSI TEST UNIT READY command.

Parameters:
scsicmdSCSI command
commandSCSI command IU

Definition at line 669 of file scsi.c.

References scsi_cmd::cdb, scsi_cdb_test_unit_ready::opcode, SCSI_OPCODE_TEST_UNIT_READY, and scsi_cdb::testready.

                                                                     {
        struct scsi_cdb_test_unit_ready *testready = &command->cdb.testready;

        testready->opcode = SCSI_OPCODE_TEST_UNIT_READY;
}
static int scsidev_command ( struct scsi_device scsidev,
struct interface block,
struct scsi_command_type type,
uint64_t  lba,
unsigned int  count,
userptr_t  buffer,
size_t  len 
) [static]

Create SCSI command.

Parameters:
scsidevSCSI device
blockBlock data interface
typeSCSI command type
lbaStarting logical block address
countNumber of blocks to transfer
bufferData buffer
lenLength of data buffer
Return values:
rcReturn status code

Definition at line 716 of file scsi.c.

References scsi_command::block, scsi_command::buffer, buffer, scsi_device::cmds, count, scsi_command::count, ENOMEM, intf_init(), intf_plug_plug(), lba, scsi_command::lba, scsi_command::len, len, scsi_command::list, list_add, scsi_command_type::priv_len, rc, ref_init, ref_put, scsi_command::refcnt, scsi_command::scsi, scsicmd_close(), scsicmd_command(), scsicmd_free(), scsi_command::scsidev, scsidev_get(), scsi_command::type, type, and zalloc().

Referenced by scsidev_read(), scsidev_read_capacity(), scsidev_test_unit_ready(), and scsidev_write().

                                                            {
        struct scsi_command *scsicmd;
        int rc;

        /* Allocate and initialise structure */
        scsicmd = zalloc ( sizeof ( *scsicmd ) + type->priv_len );
        if ( ! scsicmd ) {
                rc = -ENOMEM;
                goto err_zalloc;
        }
        ref_init ( &scsicmd->refcnt, scsicmd_free );
        intf_init ( &scsicmd->block, &scsicmd_block_desc, &scsicmd->refcnt );
        intf_init ( &scsicmd->scsi, &scsicmd_scsi_desc,
                    &scsicmd->refcnt );
        scsicmd->scsidev = scsidev_get ( scsidev );
        list_add ( &scsicmd->list, &scsidev->cmds );
        scsicmd->type = type;
        scsicmd->lba = lba;
        scsicmd->count = count;
        scsicmd->buffer = buffer;
        scsicmd->len = len;

        /* Issue SCSI command */
        if ( ( rc = scsicmd_command ( scsicmd ) ) != 0 )
                goto err_command;

        /* Attach to parent interface, transfer reference to list, and return */
        intf_plug_plug ( &scsicmd->block, block );
        return 0;

 err_command:
        scsicmd_close ( scsicmd, rc );
        ref_put ( &scsicmd->refcnt );
 err_zalloc:
        return rc;
}
static int scsidev_read ( struct scsi_device scsidev,
struct interface block,
uint64_t  lba,
unsigned int  count,
userptr_t  buffer,
size_t  len 
) [static]

Issue SCSI block read.

Parameters:
scsidevSCSI device
blockBlock data interface
lbaStarting logical block address
countNumber of blocks to transfer
bufferData buffer
lenLength of data buffer
Return values:
rcReturn status code

Definition at line 769 of file scsi.c.

References scsidev_command().

                                                         {
        return scsidev_command ( scsidev, block, &scsicmd_read,
                                 lba, count, buffer, len );
}
static int scsidev_write ( struct scsi_device scsidev,
struct interface block,
uint64_t  lba,
unsigned int  count,
userptr_t  buffer,
size_t  len 
) [static]

Issue SCSI block write.

Parameters:
scsidevSCSI device
blockBlock data interface
lbaStarting logical block address
countNumber of blocks to transfer
bufferData buffer
lenLength of data buffer
Return values:
rcReturn status code

Definition at line 788 of file scsi.c.

References scsidev_command().

                                                          {
        return scsidev_command ( scsidev, block, &scsicmd_write,
                                 lba, count, buffer, len );
}
static int scsidev_read_capacity ( struct scsi_device scsidev,
struct interface block 
) [static]

Read SCSI device capacity.

Parameters:
scsidevSCSI device
blockBlock data interface
Return values:
rcReturn status code

Definition at line 803 of file scsi.c.

References scsidev_command(), and UNULL.

                                                             {
        return scsidev_command ( scsidev, block, &scsicmd_read_capacity,
                                 0, 0, UNULL, 0 );
}
static int scsidev_test_unit_ready ( struct scsi_device scsidev,
struct interface block 
) [static]

Test to see if SCSI device is ready.

Parameters:
scsidevSCSI device
blockBlock data interface
Return values:
rcReturn status code

Definition at line 816 of file scsi.c.

References scsidev_command(), and UNULL.

Referenced by scsidev_step().

                                                               {
        return scsidev_command ( scsidev, block, &scsicmd_test_unit_ready,
                                 0, 0, UNULL, 0 );
}
static size_t scsidev_window ( struct scsi_device scsidev) [static]

Check SCSI device flow-control window.

Parameters:
scsidevSCSI device
Return values:
lenLength of window

Definition at line 828 of file scsi.c.

References scsi_device::flags, scsi_device::scsi, SCSIDEV_UNIT_READY, and xfer_window().

                                                             {

        /* Refuse commands until unit is confirmed ready */
        if ( ! ( scsidev->flags & SCSIDEV_UNIT_READY ) )
                return 0;

        return xfer_window ( &scsidev->scsi );
}
static void scsidev_close ( struct scsi_device scsidev,
int  rc 
) [static]

Close SCSI device.

Parameters:
scsidevSCSI device
rcReason for close

Definition at line 843 of file scsi.c.

References scsi_device::block, scsi_device::cmds, intfs_shutdown(), scsi_command::list, list_for_each_entry_safe, NULL, scsi_device::process, process_del(), scsi_device::ready, scsi_device::scsi, and scsicmd_close().

Referenced by scsidev_ready(), and scsidev_step().

                                                                  {
        struct scsi_command *scsicmd;
        struct scsi_command *tmp;

        /* Stop process */
        process_del ( &scsidev->process );

        /* Shut down interfaces */
        intfs_shutdown ( rc, &scsidev->block, &scsidev->scsi, &scsidev->ready,
                         NULL );

        /* Shut down any remaining commands */
        list_for_each_entry_safe ( scsicmd, tmp, &scsidev->cmds, list )
                scsicmd_close ( scsicmd, rc );
}
static void scsidev_ready ( struct scsi_device scsidev,
int  rc 
) [static]

Handle SCSI TEST UNIT READY response.

Parameters:
scsidevSCSI device
rcReason for close

Definition at line 880 of file scsi.c.

References scsi_device::block, DBGC, scsi_device::flags, intf_restart(), scsi_device::process, process_add(), scsi_device::ready, scsi_device::retries, SCSI_READY_MAX_RETRIES, scsidev_close(), SCSIDEV_UNIT_READY, SCSIDEV_UNIT_TESTED, strerror(), and xfer_window_changed().

                                                                  {

        /* Shut down interface */
        intf_restart ( &scsidev->ready, rc );

        /* Mark device as ready, if applicable */
        if ( rc == 0 ) {
                DBGC ( scsidev, "SCSI %p unit is ready\n", scsidev );
                scsidev->flags |= SCSIDEV_UNIT_READY;
                xfer_window_changed ( &scsidev->block );
                return;
        }
        DBGC ( scsidev, "SCSI %p not ready: %s\n", scsidev, strerror ( rc ) );

        /* SCSI targets have an annoying habit of returning occasional
         * pointless "error" messages such as "power-on occurred", so
         * we have to be prepared to retry commands.
         *
         * For most commands, we rely on the caller (e.g. the generic
         * SAN device layer) to retry commands as needed.  However, a
         * TEST UNIT READY failure is used as an indication that the
         * whole SCSI device is unavailable and should be closed.  We
         * must therefore perform this retry loop within the SCSI
         * layer.
         */
        if ( scsidev->retries++ < SCSI_READY_MAX_RETRIES ) {
                DBGC ( scsidev, "SCSI %p retrying (retry %d)\n",
                       scsidev, scsidev->retries );
                scsidev->flags &= ~SCSIDEV_UNIT_TESTED;
                process_add ( &scsidev->process );
                return;
        }

        /* Close device */
        DBGC ( scsidev, "SCSI %p never became ready: %s\n",
               scsidev, strerror ( rc ) );
        scsidev_close ( scsidev, rc );
}
static void scsidev_step ( struct scsi_device scsidev) [static]

SCSI TEST UNIT READY process.

Parameters:
scsidevSCSI device

Definition at line 933 of file scsi.c.

References DBGC, scsi_device::flags, rc, scsi_device::ready, scsi_device::scsi, scsidev_close(), scsidev_test_unit_ready(), SCSIDEV_UNIT_TESTED, and xfer_window().

                                                         {
        int rc;

        /* Do nothing if we have already issued TEST UNIT READY */
        if ( scsidev->flags & SCSIDEV_UNIT_TESTED )
                return;

        /* Wait until underlying SCSI device is ready */
        if ( xfer_window ( &scsidev->scsi ) == 0 )
                return;

        DBGC ( scsidev, "SCSI %p waiting for unit to become ready\n",
               scsidev );

        /* Mark TEST UNIT READY as sent */
        scsidev->flags |= SCSIDEV_UNIT_TESTED;

        /* Issue TEST UNIT READY command */
        if ( ( rc = scsidev_test_unit_ready ( scsidev, &scsidev->ready )) !=0){
                scsidev_close ( scsidev, rc );
                return;
        }
}
int scsi_open ( struct interface block,
struct interface scsi,
struct scsi_lun lun 
)

Open SCSI device.

Parameters:
blockBlock control interface
scsiSCSI control interface
lunSCSI LUN
Return values:
rcReturn status code

Definition at line 980 of file scsi.c.

References scsi_device::block, scsi_device::cmds, DBGC, ENOMEM, INIT_LIST_HEAD, intf_init(), intf_plug_plug(), scsi_device::lun, memcpy(), NULL, scsi_device::process, process_init(), scsi_device::ready, ref_init, ref_put, scsi_device::refcnt, scsi_device::scsi, SCSI_LUN_DATA, SCSI_LUN_FORMAT, and zalloc().

Referenced by fcpdev_open(), iscsi_open(), and srp_open().

                                       {
        struct scsi_device *scsidev;

        /* Allocate and initialise structure */
        scsidev = zalloc ( sizeof ( *scsidev ) );
        if ( ! scsidev )
                return -ENOMEM;
        ref_init ( &scsidev->refcnt, NULL );
        intf_init ( &scsidev->block, &scsidev_block_desc, &scsidev->refcnt );
        intf_init ( &scsidev->scsi, &scsidev_scsi_desc, &scsidev->refcnt );
        intf_init ( &scsidev->ready, &scsidev_ready_desc, &scsidev->refcnt );
        process_init ( &scsidev->process, &scsidev_process_desc,
                       &scsidev->refcnt );
        INIT_LIST_HEAD ( &scsidev->cmds );
        memcpy ( &scsidev->lun, lun, sizeof ( scsidev->lun ) );
        DBGC ( scsidev, "SCSI %p created for LUN " SCSI_LUN_FORMAT "\n",
               scsidev, SCSI_LUN_DATA ( scsidev->lun ) );

        /* Attach to SCSI and parent interfaces, mortalise self, and return */
        intf_plug_plug ( &scsidev->scsi, scsi );
        intf_plug_plug ( &scsidev->block, block );
        ref_put ( &scsidev->refcnt );
        return 0;
}

Variable Documentation

Initial value:
 {
        .name = "READ",
        .cmd = scsicmd_read_cmd,
        .done = scsicmd_close,
}

SCSI READ command type.

Definition at line 524 of file scsi.c.

Initial value:
 {
        .name = "WRITE",
        .cmd = scsicmd_write_cmd,
        .done = scsicmd_close,
}

SCSI WRITE command type.

Definition at line 555 of file scsi.c.

Initial value:
 {
        .name = "READ CAPACITY",
        .priv_len = sizeof ( struct scsi_read_capacity_private ),
        .cmd = scsicmd_read_capacity_cmd,
        .done = scsicmd_read_capacity_done,
}

SCSI READ CAPACITY command type.

Definition at line 656 of file scsi.c.

Initial value:
 {
        .name = "TEST UNIT READY",
        .cmd = scsicmd_test_unit_ready_cmd,
        .done = scsicmd_close,
}

SCSI TEST UNIT READY command type.

Definition at line 677 of file scsi.c.

Initial value:

SCSI command block interface operations.

Definition at line 684 of file scsi.c.

Initial value:

SCSI command block interface descriptor.

Definition at line 689 of file scsi.c.

Initial value:

SCSI command SCSI interface operations.

Definition at line 694 of file scsi.c.

Initial value:

SCSI command SCSI interface descriptor.

Definition at line 700 of file scsi.c.

Initial value:

SCSI device block interface operations.

Definition at line 860 of file scsi.c.

Initial value:

SCSI device block interface descriptor.

Definition at line 870 of file scsi.c.

Initial value:

SCSI device TEST UNIT READY interface operations.

Definition at line 920 of file scsi.c.

Initial value:

SCSI device TEST UNIT READY interface descriptor.

Definition at line 925 of file scsi.c.

Initial value:

SCSI device SCSI interface operations.

Definition at line 958 of file scsi.c.

Initial value:

SCSI device SCSI interface descriptor.

Definition at line 964 of file scsi.c.

Initial value:

SCSI device process descriptor.

Definition at line 969 of file scsi.c.