00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00031
00032
00033
00034
00035
00036
00037
00038
00039
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
00050
00051
00052
00053
00054
00055 int scsi_detached_command ( struct scsi_device *scsi __unused,
00056 struct scsi_command *command __unused ) {
00057 return -ENODEV;
00058 }
00059
00060
00061
00062
00063
00064
00065
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
00075 command->sense_response = 0;
00076
00077
00078 command->rc = -EINPROGRESS;
00079
00080
00081 if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) {
00082
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
00089 while ( command->rc == -EINPROGRESS )
00090 step();
00091 if ( ( rc = command->rc ) != 0 ) {
00092
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
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
00111
00112
00113
00114
00115
00116
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
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
00136
00137
00138
00139
00140
00141
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
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
00161
00162
00163
00164
00165
00166
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
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
00186
00187
00188
00189
00190
00191
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
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
00211
00212
00213
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
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
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
00240
00241
00242
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
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
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
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 int init_scsidev ( struct scsi_device *scsi ) {
00290 unsigned int i;
00291 int rc;
00292
00293
00294
00295
00296
00297
00298
00299
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
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
00317
00318
00319
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
00341
00342
00343
00344
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 }