scsi.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <stddef.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <byteswap.h>
00025 #include <errno.h>
00026 #include <gpxe/blockdev.h>
00027 #include <gpxe/process.h>
00028 #include <gpxe/scsi.h>
00029 
00030 /** @file
00031  *
00032  * SCSI block device
00033  *
00034  */
00035 
00036 /** Maximum number of dummy "read capacity (10)" operations
00037  *
00038  * These are issued at connection setup to draw out various useless
00039  * power-on messages.
00040  */
00041 #define SCSI_MAX_DUMMY_READ_CAP 10
00042 
00043 static inline __attribute__ (( always_inline )) struct scsi_device *
00044 block_to_scsi ( struct block_device *blockdev ) {
00045         return container_of ( blockdev, struct scsi_device, blockdev );
00046 }
00047 
00048 /**
00049  * Handle SCSI command with no backing device
00050  *
00051  * @v scsi              SCSI device
00052  * @v command           SCSI command
00053  * @ret rc              Return status code
00054  */
00055 int scsi_detached_command ( struct scsi_device *scsi __unused,
00056                             struct scsi_command *command __unused ) {
00057         return -ENODEV;
00058 }
00059 
00060 /**
00061  * Issue SCSI command
00062  *
00063  * @v scsi              SCSI device
00064  * @v command           SCSI command
00065  * @ret rc              Return status code
00066  */
00067 static int scsi_command ( struct scsi_device *scsi,
00068                           struct scsi_command *command ) {
00069         int rc;
00070 
00071         DBGC2 ( scsi, "SCSI %p " SCSI_CDB_FORMAT "\n",
00072                 scsi, SCSI_CDB_DATA ( command->cdb ) );
00073 
00074         /* Clear sense response code before issuing command */
00075         command->sense_response = 0;
00076 
00077         /* Flag command as in-progress */
00078         command->rc = -EINPROGRESS;
00079 
00080         /* Issue SCSI command */
00081         if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) {
00082                 /* Something went wrong with the issuing mechanism */
00083                 DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " err %s\n",
00084                        scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) );
00085                 return rc;
00086         }
00087 
00088         /* Wait for command to complete */
00089         while ( command->rc == -EINPROGRESS )
00090                 step();
00091         if ( ( rc = command->rc ) != 0 ) {
00092                 /* Something went wrong with the command execution */
00093                 DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " err %s\n",
00094                        scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) );
00095                 return rc;
00096         }
00097 
00098         /* Check for SCSI errors */
00099         if ( command->status != 0 ) {
00100                 DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " status %02x sense "
00101                        "%02x\n", scsi, SCSI_CDB_DATA ( command->cdb ),
00102                        command->status, command->sense_response );
00103                 return -EIO;
00104         }
00105 
00106         return 0;
00107 }
00108 
00109 /**
00110  * Read block from SCSI device using READ (10)
00111  *
00112  * @v blockdev          Block device
00113  * @v block             LBA block number
00114  * @v count             Block count
00115  * @v buffer            Data buffer
00116  * @ret rc              Return status code
00117  */
00118 static int scsi_read_10 ( struct block_device *blockdev, uint64_t block,
00119                           unsigned long count, userptr_t buffer ) {
00120         struct scsi_device *scsi = block_to_scsi ( blockdev );
00121         struct scsi_command command;
00122         struct scsi_cdb_read_10 *cdb = &command.cdb.read10;
00123 
00124         /* Issue READ (10) */
00125         memset ( &command, 0, sizeof ( command ) );
00126         cdb->opcode = SCSI_OPCODE_READ_10;
00127         cdb->lba = cpu_to_be32 ( block );
00128         cdb->len = cpu_to_be16 ( count );
00129         command.data_in = buffer;
00130         command.data_in_len = ( count * blockdev->blksize );
00131         return scsi_command ( scsi, &command );
00132 }
00133 
00134 /**
00135  * Read block from SCSI device using READ (16)
00136  *
00137  * @v blockdev          Block device
00138  * @v block             LBA block number
00139  * @v count             Block count
00140  * @v buffer            Data buffer
00141  * @ret rc              Return status code
00142  */
00143 static int scsi_read_16 ( struct block_device *blockdev, uint64_t block,
00144                           unsigned long count, userptr_t buffer ) {
00145         struct scsi_device *scsi = block_to_scsi ( blockdev );
00146         struct scsi_command command;
00147         struct scsi_cdb_read_16 *cdb = &command.cdb.read16;
00148 
00149         /* Issue READ (16) */
00150         memset ( &command, 0, sizeof ( command ) );
00151         cdb->opcode = SCSI_OPCODE_READ_16;
00152         cdb->lba = cpu_to_be64 ( block );
00153         cdb->len = cpu_to_be32 ( count );
00154         command.data_in = buffer;
00155         command.data_in_len = ( count * blockdev->blksize );
00156         return scsi_command ( scsi, &command );
00157 }
00158 
00159 /**
00160  * Write block to SCSI device using WRITE (10)
00161  *
00162  * @v blockdev          Block device
00163  * @v block             LBA block number
00164  * @v count             Block count
00165  * @v buffer            Data buffer
00166  * @ret rc              Return status code
00167  */
00168 static int scsi_write_10 ( struct block_device *blockdev, uint64_t block,
00169                            unsigned long count, userptr_t buffer ) {
00170         struct scsi_device *scsi = block_to_scsi ( blockdev );
00171         struct scsi_command command;
00172         struct scsi_cdb_write_10 *cdb = &command.cdb.write10;
00173 
00174         /* Issue WRITE (10) */
00175         memset ( &command, 0, sizeof ( command ) );
00176         cdb->opcode = SCSI_OPCODE_WRITE_10;
00177         cdb->lba = cpu_to_be32 ( block );
00178         cdb->len = cpu_to_be16 ( count );
00179         command.data_out = buffer;
00180         command.data_out_len = ( count * blockdev->blksize );
00181         return scsi_command ( scsi, &command );
00182 }
00183 
00184 /**
00185  * Write block to SCSI device using WRITE (16)
00186  *
00187  * @v blockdev          Block device
00188  * @v block             LBA block number
00189  * @v count             Block count
00190  * @v buffer            Data buffer
00191  * @ret rc              Return status code
00192  */
00193 static int scsi_write_16 ( struct block_device *blockdev, uint64_t block,
00194                            unsigned long count, userptr_t buffer ) {
00195         struct scsi_device *scsi = block_to_scsi ( blockdev );
00196         struct scsi_command command;
00197         struct scsi_cdb_write_16 *cdb = &command.cdb.write16;
00198 
00199         /* Issue WRITE (16) */
00200         memset ( &command, 0, sizeof ( command ) );
00201         cdb->opcode = SCSI_OPCODE_WRITE_16;
00202         cdb->lba = cpu_to_be64 ( block );
00203         cdb->len = cpu_to_be32 ( count );
00204         command.data_out = buffer;
00205         command.data_out_len = ( count * blockdev->blksize );
00206         return scsi_command ( scsi, &command );
00207 }
00208 
00209 /**
00210  * Read capacity of SCSI device via READ CAPACITY (10)
00211  *
00212  * @v blockdev          Block device
00213  * @ret rc              Return status code
00214  */
00215 static int scsi_read_capacity_10 ( struct block_device *blockdev ) {
00216         struct scsi_device *scsi = block_to_scsi ( blockdev );
00217         struct scsi_command command;
00218         struct scsi_cdb_read_capacity_10 *cdb = &command.cdb.readcap10;
00219         struct scsi_capacity_10 capacity;
00220         int rc;
00221 
00222         /* Issue READ CAPACITY (10) */
00223         memset ( &command, 0, sizeof ( command ) );
00224         cdb->opcode = SCSI_OPCODE_READ_CAPACITY_10;
00225         command.data_in = virt_to_user ( &capacity );
00226         command.data_in_len = sizeof ( capacity );
00227 
00228         if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
00229                 return rc;
00230 
00231         /* Fill in block device fields */
00232         blockdev->blksize = be32_to_cpu ( capacity.blksize );
00233         blockdev->blocks = ( be32_to_cpu ( capacity.lba ) + 1 );
00234 
00235         return 0;
00236 }
00237 
00238 /**
00239  * Read capacity of SCSI device via READ CAPACITY (16)
00240  *
00241  * @v blockdev          Block device
00242  * @ret rc              Return status code
00243  */
00244 static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
00245         struct scsi_device *scsi = block_to_scsi ( blockdev );
00246         struct scsi_command command;
00247         struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
00248         struct scsi_capacity_16 capacity;
00249         int rc;
00250 
00251         /* Issue READ CAPACITY (16) */
00252         memset ( &command, 0, sizeof ( command ) );
00253         cdb->opcode = SCSI_OPCODE_SERVICE_ACTION_IN;
00254         cdb->service_action = SCSI_SERVICE_ACTION_READ_CAPACITY_16;
00255         cdb->len = cpu_to_be32 ( sizeof ( capacity ) );
00256         command.data_in = virt_to_user ( &capacity );
00257         command.data_in_len = sizeof ( capacity );
00258 
00259         if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
00260                 return rc;
00261 
00262         /* Fill in block device fields */
00263         blockdev->blksize = be32_to_cpu ( capacity.blksize );
00264         blockdev->blocks = ( be64_to_cpu ( capacity.lba ) + 1 );
00265         return 0;
00266 }
00267 
00268 static struct block_device_operations scsi_operations_16 = {
00269         .read   = scsi_read_16,
00270         .write  = scsi_write_16,
00271 };
00272 
00273 static struct block_device_operations scsi_operations_10 = {
00274         .read   = scsi_read_10,
00275         .write  = scsi_write_10,
00276 };
00277 
00278 /**
00279  * Initialise SCSI device
00280  *
00281  * @v scsi              SCSI device
00282  * @ret rc              Return status code
00283  *
00284  * Initialises a SCSI device.  The scsi_device::command and
00285  * scsi_device::lun fields must already be filled in.  This function
00286  * will configure scsi_device::blockdev, including issuing a READ
00287  * CAPACITY call to determine the block size and total device size.
00288  */
00289 int init_scsidev ( struct scsi_device *scsi ) {
00290         unsigned int i;
00291         int rc;
00292 
00293         /* Issue some theoretically extraneous READ CAPACITY (10)
00294          * commands, solely in order to draw out the "CHECK CONDITION
00295          * (power-on occurred)", "CHECK CONDITION (reported LUNs data
00296          * has changed)" etc. that some dumb targets insist on sending
00297          * as an error at start of day.  The precise command that we
00298          * use is unimportant; we just need to provide the target with
00299          * an opportunity to send its responses.
00300          */
00301         for ( i = 0 ; i < SCSI_MAX_DUMMY_READ_CAP ; i++ ) {
00302                 if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) == 0 )
00303                         break;
00304                 DBGC ( scsi, "SCSI %p ignoring start-of-day error (#%d)\n",
00305                        scsi, ( i + 1 ) );
00306         }
00307 
00308         /* Try READ CAPACITY (10), which is a mandatory command, first. */
00309         scsi->blockdev.op = &scsi_operations_10;
00310         if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) != 0 ) {
00311                 DBGC ( scsi, "SCSI %p could not READ CAPACITY (10): %s\n",
00312                        scsi, strerror ( rc ) );
00313                 return rc;
00314         }
00315 
00316         /* If capacity range was exceeded (i.e. capacity.lba was
00317          * 0xffffffff, meaning that blockdev->blocks is now zero), use
00318          * READ CAPACITY (16) instead.  READ CAPACITY (16) is not
00319          * mandatory, so we can't just use it straight off.
00320          */
00321         if ( scsi->blockdev.blocks == 0 ) {
00322                 scsi->blockdev.op = &scsi_operations_16;
00323                 if ( ( rc = scsi_read_capacity_16 ( &scsi->blockdev ) ) != 0 ){
00324                         DBGC ( scsi, "SCSI %p could not READ CAPACITY (16): "
00325                                "%s\n", scsi, strerror ( rc ) );
00326                         return rc;
00327                 }
00328         }
00329 
00330         DBGC ( scsi, "SCSI %p using READ/WRITE (%d) commands\n", scsi,
00331                ( ( scsi->blockdev.op == &scsi_operations_10 ) ? 10 : 16 ) );
00332         DBGC ( scsi, "SCSI %p capacity is %ld MB (%#llx blocks)\n", scsi,
00333                ( ( unsigned long ) ( scsi->blockdev.blocks >> 11 ) ),
00334                scsi->blockdev.blocks );
00335 
00336         return 0;
00337 }
00338 
00339 /**
00340  * Parse SCSI LUN
00341  *
00342  * @v lun_string        LUN string representation
00343  * @v lun               LUN to fill in
00344  * @ret rc              Return status code
00345  */
00346 int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) {
00347         char *p;
00348         int i;
00349 
00350         memset ( lun, 0, sizeof ( *lun ) );
00351         if ( lun_string ) {
00352                 p = ( char * ) lun_string;
00353                 for ( i = 0 ; i < 4 ; i++ ) {
00354                         lun->u16[i] = htons ( strtoul ( p, &p, 16 ) );
00355                         if ( *p == '\0' )
00356                                 break;
00357                         if ( *p != '-' )
00358                                 return -EINVAL;
00359                         p++;
00360                 }
00361                 if ( *p )
00362                         return -EINVAL;
00363         }
00364 
00365         return 0;
00366 }

Generated on Tue Apr 6 20:00:52 2010 for gPXE by  doxygen 1.5.7.1