2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 FILE_LICENCE ( GPL2_OR_LATER
);
26 #include <gpxe/blockdev.h>
27 #include <gpxe/process.h>
28 #include <gpxe/scsi.h>
36 /** Maximum number of dummy "read capacity (10)" operations
38 * These are issued at connection setup to draw out various useless
41 #define SCSI_MAX_DUMMY_READ_CAP 10
43 static inline __attribute__ (( always_inline
)) struct scsi_device
*
44 block_to_scsi ( struct block_device
*blockdev
) {
45 return container_of ( blockdev
, struct scsi_device
, blockdev
);
49 * Handle SCSI command with no backing device
52 * @v command SCSI command
53 * @ret rc Return status code
55 int scsi_detached_command ( struct scsi_device
*scsi __unused
,
56 struct scsi_command
*command __unused
) {
64 * @v command SCSI command
65 * @ret rc Return status code
67 static int scsi_command ( struct scsi_device
*scsi
,
68 struct scsi_command
*command
) {
71 DBGC2 ( scsi
, "SCSI %p " SCSI_CDB_FORMAT
"\n",
72 scsi
, SCSI_CDB_DATA ( command
->cdb
) );
74 /* Clear sense response code before issuing command */
75 command
->sense_response
= 0;
77 /* Flag command as in-progress */
78 command
->rc
= -EINPROGRESS
;
80 /* Issue SCSI command */
81 if ( ( rc
= scsi
->command ( scsi
, command
) ) != 0 ) {
82 /* Something went wrong with the issuing mechanism */
83 DBGC ( scsi
, "SCSI %p " SCSI_CDB_FORMAT
" err %s\n",
84 scsi
, SCSI_CDB_DATA ( command
->cdb
), strerror ( rc
) );
88 /* Wait for command to complete */
89 while ( command
->rc
== -EINPROGRESS
)
91 if ( ( rc
= command
->rc
) != 0 ) {
92 /* Something went wrong with the command execution */
93 DBGC ( scsi
, "SCSI %p " SCSI_CDB_FORMAT
" err %s\n",
94 scsi
, SCSI_CDB_DATA ( command
->cdb
), strerror ( rc
) );
98 /* Check for SCSI errors */
99 if ( command
->status
!= 0 ) {
100 DBGC ( scsi
, "SCSI %p " SCSI_CDB_FORMAT
" status %02x sense "
101 "%02x\n", scsi
, SCSI_CDB_DATA ( command
->cdb
),
102 command
->status
, command
->sense_response
);
110 * Read block from SCSI device using READ (10)
112 * @v blockdev Block device
113 * @v block LBA block number
114 * @v count Block count
115 * @v buffer Data buffer
116 * @ret rc Return status code
118 static int scsi_read_10 ( struct block_device
*blockdev
, uint64_t block
,
119 unsigned long count
, userptr_t buffer
) {
120 struct scsi_device
*scsi
= block_to_scsi ( blockdev
);
121 struct scsi_command command
;
122 struct scsi_cdb_read_10
*cdb
= &command
.cdb
.read10
;
124 /* Issue READ (10) */
125 memset ( &command
, 0, sizeof ( command
) );
126 cdb
->opcode
= SCSI_OPCODE_READ_10
;
127 cdb
->lba
= cpu_to_be32 ( block
);
128 cdb
->len
= cpu_to_be16 ( count
);
129 command
.data_in
= buffer
;
130 command
.data_in_len
= ( count
* blockdev
->blksize
);
131 return scsi_command ( scsi
, &command
);
135 * Read block from SCSI device using READ (16)
137 * @v blockdev Block device
138 * @v block LBA block number
139 * @v count Block count
140 * @v buffer Data buffer
141 * @ret rc Return status code
143 static int scsi_read_16 ( struct block_device
*blockdev
, uint64_t block
,
144 unsigned long count
, userptr_t buffer
) {
145 struct scsi_device
*scsi
= block_to_scsi ( blockdev
);
146 struct scsi_command command
;
147 struct scsi_cdb_read_16
*cdb
= &command
.cdb
.read16
;
149 /* Issue READ (16) */
150 memset ( &command
, 0, sizeof ( command
) );
151 cdb
->opcode
= SCSI_OPCODE_READ_16
;
152 cdb
->lba
= cpu_to_be64 ( block
);
153 cdb
->len
= cpu_to_be32 ( count
);
154 command
.data_in
= buffer
;
155 command
.data_in_len
= ( count
* blockdev
->blksize
);
156 return scsi_command ( scsi
, &command
);
160 * Write block to SCSI device using WRITE (10)
162 * @v blockdev Block device
163 * @v block LBA block number
164 * @v count Block count
165 * @v buffer Data buffer
166 * @ret rc Return status code
168 static int scsi_write_10 ( struct block_device
*blockdev
, uint64_t block
,
169 unsigned long count
, userptr_t buffer
) {
170 struct scsi_device
*scsi
= block_to_scsi ( blockdev
);
171 struct scsi_command command
;
172 struct scsi_cdb_write_10
*cdb
= &command
.cdb
.write10
;
174 /* Issue WRITE (10) */
175 memset ( &command
, 0, sizeof ( command
) );
176 cdb
->opcode
= SCSI_OPCODE_WRITE_10
;
177 cdb
->lba
= cpu_to_be32 ( block
);
178 cdb
->len
= cpu_to_be16 ( count
);
179 command
.data_out
= buffer
;
180 command
.data_out_len
= ( count
* blockdev
->blksize
);
181 return scsi_command ( scsi
, &command
);
185 * Write block to SCSI device using WRITE (16)
187 * @v blockdev Block device
188 * @v block LBA block number
189 * @v count Block count
190 * @v buffer Data buffer
191 * @ret rc Return status code
193 static int scsi_write_16 ( struct block_device
*blockdev
, uint64_t block
,
194 unsigned long count
, userptr_t buffer
) {
195 struct scsi_device
*scsi
= block_to_scsi ( blockdev
);
196 struct scsi_command command
;
197 struct scsi_cdb_write_16
*cdb
= &command
.cdb
.write16
;
199 /* Issue WRITE (16) */
200 memset ( &command
, 0, sizeof ( command
) );
201 cdb
->opcode
= SCSI_OPCODE_WRITE_16
;
202 cdb
->lba
= cpu_to_be64 ( block
);
203 cdb
->len
= cpu_to_be32 ( count
);
204 command
.data_out
= buffer
;
205 command
.data_out_len
= ( count
* blockdev
->blksize
);
206 return scsi_command ( scsi
, &command
);
210 * Read capacity of SCSI device via READ CAPACITY (10)
212 * @v blockdev Block device
213 * @ret rc Return status code
215 static int scsi_read_capacity_10 ( struct block_device
*blockdev
) {
216 struct scsi_device
*scsi
= block_to_scsi ( blockdev
);
217 struct scsi_command command
;
218 struct scsi_cdb_read_capacity_10
*cdb
= &command
.cdb
.readcap10
;
219 struct scsi_capacity_10 capacity
;
222 /* Issue READ CAPACITY (10) */
223 memset ( &command
, 0, sizeof ( command
) );
224 cdb
->opcode
= SCSI_OPCODE_READ_CAPACITY_10
;
225 command
.data_in
= virt_to_user ( &capacity
);
226 command
.data_in_len
= sizeof ( capacity
);
228 if ( ( rc
= scsi_command ( scsi
, &command
) ) != 0 )
231 /* Fill in block device fields */
232 blockdev
->blksize
= be32_to_cpu ( capacity
.blksize
);
233 blockdev
->blocks
= ( be32_to_cpu ( capacity
.lba
) + 1 );
239 * Read capacity of SCSI device via READ CAPACITY (16)
241 * @v blockdev Block device
242 * @ret rc Return status code
244 static int scsi_read_capacity_16 ( struct block_device
*blockdev
) {
245 struct scsi_device
*scsi
= block_to_scsi ( blockdev
);
246 struct scsi_command command
;
247 struct scsi_cdb_read_capacity_16
*cdb
= &command
.cdb
.readcap16
;
248 struct scsi_capacity_16 capacity
;
251 /* Issue READ CAPACITY (16) */
252 memset ( &command
, 0, sizeof ( command
) );
253 cdb
->opcode
= SCSI_OPCODE_SERVICE_ACTION_IN
;
254 cdb
->service_action
= SCSI_SERVICE_ACTION_READ_CAPACITY_16
;
255 cdb
->len
= cpu_to_be32 ( sizeof ( capacity
) );
256 command
.data_in
= virt_to_user ( &capacity
);
257 command
.data_in_len
= sizeof ( capacity
);
259 if ( ( rc
= scsi_command ( scsi
, &command
) ) != 0 )
262 /* Fill in block device fields */
263 blockdev
->blksize
= be32_to_cpu ( capacity
.blksize
);
264 blockdev
->blocks
= ( be64_to_cpu ( capacity
.lba
) + 1 );
268 static struct block_device_operations scsi_operations_16
= {
269 .read
= scsi_read_16
,
270 .write
= scsi_write_16
,
273 static struct block_device_operations scsi_operations_10
= {
274 .read
= scsi_read_10
,
275 .write
= scsi_write_10
,
279 * Initialise SCSI device
281 * @v scsi SCSI device
282 * @ret rc Return status code
284 * Initialises a SCSI device. The scsi_device::command and
285 * scsi_device::lun fields must already be filled in. This function
286 * will configure scsi_device::blockdev, including issuing a READ
287 * CAPACITY call to determine the block size and total device size.
289 int init_scsidev ( struct scsi_device
*scsi
) {
293 /* Issue some theoretically extraneous READ CAPACITY (10)
294 * commands, solely in order to draw out the "CHECK CONDITION
295 * (power-on occurred)", "CHECK CONDITION (reported LUNs data
296 * has changed)" etc. that some dumb targets insist on sending
297 * as an error at start of day. The precise command that we
298 * use is unimportant; we just need to provide the target with
299 * an opportunity to send its responses.
301 for ( i
= 0 ; i
< SCSI_MAX_DUMMY_READ_CAP
; i
++ ) {
302 if ( ( rc
= scsi_read_capacity_10 ( &scsi
->blockdev
) ) == 0 )
304 DBGC ( scsi
, "SCSI %p ignoring start-of-day error (#%d)\n",
308 /* Try READ CAPACITY (10), which is a mandatory command, first. */
309 scsi
->blockdev
.op
= &scsi_operations_10
;
310 if ( ( rc
= scsi_read_capacity_10 ( &scsi
->blockdev
) ) != 0 ) {
311 DBGC ( scsi
, "SCSI %p could not READ CAPACITY (10): %s\n",
312 scsi
, strerror ( rc
) );
316 /* If capacity range was exceeded (i.e. capacity.lba was
317 * 0xffffffff, meaning that blockdev->blocks is now zero), use
318 * READ CAPACITY (16) instead. READ CAPACITY (16) is not
319 * mandatory, so we can't just use it straight off.
321 if ( scsi
->blockdev
.blocks
== 0 ) {
322 scsi
->blockdev
.op
= &scsi_operations_16
;
323 if ( ( rc
= scsi_read_capacity_16 ( &scsi
->blockdev
) ) != 0 ){
324 DBGC ( scsi
, "SCSI %p could not READ CAPACITY (16): "
325 "%s\n", scsi
, strerror ( rc
) );
330 DBGC ( scsi
, "SCSI %p using READ/WRITE (%d) commands\n", scsi
,
331 ( ( scsi
->blockdev
.op
== &scsi_operations_10
) ? 10 : 16 ) );
332 DBGC ( scsi
, "SCSI %p capacity is %ld MB (%#llx blocks)\n", scsi
,
333 ( ( unsigned long ) ( scsi
->blockdev
.blocks
>> 11 ) ),
334 scsi
->blockdev
.blocks
);
342 * @v lun_string LUN string representation
343 * @v lun LUN to fill in
344 * @ret rc Return status code
346 int scsi_parse_lun ( const char *lun_string
, struct scsi_lun
*lun
) {
350 memset ( lun
, 0, sizeof ( *lun
) );
352 p
= ( char * ) lun_string
;
353 for ( i
= 0 ; i
< 4 ; i
++ ) {
354 lun
->u16
[i
] = htons ( strtoul ( p
, &p
, 16 ) );