Browse Source

Automatically select between the "10" and "16" variants of command set,

based on the device size.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
a39b111684
2 changed files with 120 additions and 31 deletions
  1. 72
    31
      src/drivers/block/scsi.c
  2. 48
    0
      src/include/gpxe/scsi.h

+ 72
- 31
src/drivers/block/scsi.c View File

70
 }
70
 }
71
 
71
 
72
 /**
72
 /**
73
- * Read block from SCSI device
73
+ * Read block from SCSI device using READ (10)
74
  *
74
  *
75
  * @v blockdev		Block device
75
  * @v blockdev		Block device
76
  * @v block		LBA block number
76
  * @v block		LBA block number
78
  * @v buffer		Data buffer
78
  * @v buffer		Data buffer
79
  * @ret rc		Return status code
79
  * @ret rc		Return status code
80
  */
80
  */
81
-static int scsi_read ( struct block_device *blockdev, uint64_t block,
82
-		       unsigned long count, userptr_t buffer ) {
81
+static int scsi_read_10 ( struct block_device *blockdev, uint64_t block,
82
+			  unsigned long count, userptr_t buffer ) {
83
+	struct scsi_device *scsi = block_to_scsi ( blockdev );
84
+	struct scsi_command command;
85
+	struct scsi_cdb_read_10 *cdb = &command.cdb.read10;
86
+
87
+	/* Issue READ (10) */
88
+	memset ( &command, 0, sizeof ( command ) );
89
+	cdb->opcode = SCSI_OPCODE_READ_10;
90
+	cdb->lba = cpu_to_be32 ( block );
91
+	cdb->len = cpu_to_be16 ( count );
92
+	command.data_in = buffer;
93
+	command.data_in_len = ( count * blockdev->blksize );
94
+	return scsi_command ( scsi, &command );
95
+}
96
+
97
+/**
98
+ * Read block from SCSI device using READ (16)
99
+ *
100
+ * @v blockdev		Block device
101
+ * @v block		LBA block number
102
+ * @v count		Block count
103
+ * @v buffer		Data buffer
104
+ * @ret rc		Return status code
105
+ */
106
+static int scsi_read_16 ( struct block_device *blockdev, uint64_t block,
107
+			  unsigned long count, userptr_t buffer ) {
83
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
108
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
84
 	struct scsi_command command;
109
 	struct scsi_command command;
85
 	struct scsi_cdb_read_16 *cdb = &command.cdb.read16;
110
 	struct scsi_cdb_read_16 *cdb = &command.cdb.read16;
95
 }
120
 }
96
 
121
 
97
 /**
122
 /**
98
- * Write block to SCSI device
123
+ * Write block to SCSI device using WRITE (10)
99
  *
124
  *
100
  * @v blockdev		Block device
125
  * @v blockdev		Block device
101
  * @v block		LBA block number
126
  * @v block		LBA block number
103
  * @v buffer		Data buffer
128
  * @v buffer		Data buffer
104
  * @ret rc		Return status code
129
  * @ret rc		Return status code
105
  */
130
  */
106
-static int scsi_write ( struct block_device *blockdev, uint64_t block,
107
-		        unsigned long count, userptr_t buffer ) {
131
+static int scsi_write_10 ( struct block_device *blockdev, uint64_t block,
132
+			   unsigned long count, userptr_t buffer ) {
133
+	struct scsi_device *scsi = block_to_scsi ( blockdev );
134
+	struct scsi_command command;
135
+	struct scsi_cdb_write_10 *cdb = &command.cdb.write10;
136
+
137
+	/* Issue WRITE (10) */
138
+	memset ( &command, 0, sizeof ( command ) );
139
+	cdb->opcode = SCSI_OPCODE_WRITE_10;
140
+	cdb->lba = cpu_to_be32 ( block );
141
+	cdb->len = cpu_to_be16 ( count );
142
+	command.data_out = buffer;
143
+	command.data_out_len = ( count * blockdev->blksize );
144
+	return scsi_command ( scsi, &command );
145
+}
146
+
147
+/**
148
+ * Write block to SCSI device using WRITE (16)
149
+ *
150
+ * @v blockdev		Block device
151
+ * @v block		LBA block number
152
+ * @v count		Block count
153
+ * @v buffer		Data buffer
154
+ * @ret rc		Return status code
155
+ */
156
+static int scsi_write_16 ( struct block_device *blockdev, uint64_t block,
157
+			   unsigned long count, userptr_t buffer ) {
108
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
158
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
109
 	struct scsi_command command;
159
 	struct scsi_command command;
110
 	struct scsi_cdb_write_16 *cdb = &command.cdb.write16;
160
 	struct scsi_cdb_write_16 *cdb = &command.cdb.write16;
179
 }
229
 }
180
 
230
 
181
 /**
231
 /**
182
- * Read capacity of SCSI device
232
+ * Initialise SCSI device
183
  *
233
  *
184
- * @v blockdev		Block device
234
+ * @v scsi		SCSI device
185
  * @ret rc		Return status code
235
  * @ret rc		Return status code
236
+ *
237
+ * Initialises a SCSI device.  The scsi_device::command and
238
+ * scsi_device::lun fields must already be filled in.  This function
239
+ * will configure scsi_device::blockdev, including issuing a READ
240
+ * CAPACITY call to determine the block size and total device size.
186
  */
241
  */
187
-static int scsi_read_capacity ( struct block_device *blockdev ) {
242
+int init_scsidev ( struct scsi_device *scsi ) {
188
 	int rc;
243
 	int rc;
189
 
244
 
190
 	/* Issue a theoretically extraneous READ CAPACITY (10)
245
 	/* Issue a theoretically extraneous READ CAPACITY (10)
192
 	 * (power-on occurred)" that some dumb targets insist on
247
 	 * (power-on occurred)" that some dumb targets insist on
193
 	 * sending as an error at start of day.
248
 	 * sending as an error at start of day.
194
 	 */
249
 	 */
195
-	scsi_read_capacity_10 ( blockdev );
250
+	scsi_read_capacity_10 ( &scsi->blockdev );
196
 
251
 
197
 	/* Try READ CAPACITY (10), which is a mandatory command, first. */
252
 	/* Try READ CAPACITY (10), which is a mandatory command, first. */
198
-	if ( ( rc = scsi_read_capacity_10 ( blockdev ) ) != 0 )
253
+	scsi->blockdev.read = scsi_read_10;
254
+	scsi->blockdev.write = scsi_write_10;
255
+	if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) != 0 )
199
 		return rc;
256
 		return rc;
200
 
257
 
201
 	/* If capacity range was exceeded (i.e. capacity.lba was
258
 	/* If capacity range was exceeded (i.e. capacity.lba was
203
 	 * READ CAPACITY (16) instead.  READ CAPACITY (16) is not
260
 	 * READ CAPACITY (16) instead.  READ CAPACITY (16) is not
204
 	 * mandatory, so we can't just use it straight off.
261
 	 * mandatory, so we can't just use it straight off.
205
 	 */
262
 	 */
206
-	if ( blockdev->blocks == 0 ) {
207
-		if ( ( rc = scsi_read_capacity_16 ( blockdev ) ) != 0 )
263
+	if ( scsi->blockdev.blocks == 0 ) {
264
+		scsi->blockdev.read = scsi_read_16;
265
+		scsi->blockdev.write = scsi_write_16;
266
+		if ( ( rc = scsi_read_capacity_16 ( &scsi->blockdev ) ) != 0 )
208
 			return rc;
267
 			return rc;
209
 	}
268
 	}
210
 
269
 
211
 	return 0;
270
 	return 0;
212
 }
271
 }
213
-
214
-/**
215
- * Initialise SCSI device
216
- *
217
- * @v scsi		SCSI device
218
- * @ret rc		Return status code
219
- *
220
- * Initialises a SCSI device.  The scsi_device::command and
221
- * scsi_device::lun fields must already be filled in.  This function
222
- * will configure scsi_device::blockdev, including issuing a READ
223
- * CAPACITY call to determine the block size and total device size.
224
- */
225
-int init_scsidev ( struct scsi_device *scsi ) {
226
-	/** Fill in read and write methods, and get device capacity */
227
-	scsi->blockdev.read = scsi_read;
228
-	scsi->blockdev.write = scsi_write;
229
-	return scsi_read_capacity ( &scsi->blockdev );
230
-}

+ 48
- 0
src/include/gpxe/scsi.h View File

16
  * @{
16
  * @{
17
  */
17
  */
18
 
18
 
19
+#define SCSI_OPCODE_READ_10		0x28	/**< READ (10) */
19
 #define SCSI_OPCODE_READ_16		0x88	/**< READ (16) */
20
 #define SCSI_OPCODE_READ_16		0x88	/**< READ (16) */
21
+#define SCSI_OPCODE_WRITE_10		0x2a	/**< WRITE (10) */
20
 #define SCSI_OPCODE_WRITE_16		0x8a	/**< WRITE (16) */
22
 #define SCSI_OPCODE_WRITE_16		0x8a	/**< WRITE (16) */
21
 #define SCSI_OPCODE_READ_CAPACITY_10	0x25	/**< READ CAPACITY (10) */
23
 #define SCSI_OPCODE_READ_CAPACITY_10	0x25	/**< READ CAPACITY (10) */
22
 #define SCSI_OPCODE_SERVICE_ACTION_IN	0x9e	/**< SERVICE ACTION IN */
24
 #define SCSI_OPCODE_SERVICE_ACTION_IN	0x9e	/**< SERVICE ACTION IN */
40
  * @{
42
  * @{
41
  */
43
  */
42
 
44
 
45
+/** A SCSI "READ (10)" CDB */
46
+struct scsi_cdb_read_10 {
47
+	/** Opcode (0x28) */
48
+	uint8_t opcode;
49
+	/** Flags */
50
+	uint8_t flags;
51
+	/** Start address
52
+	 *
53
+	 * This is a logical block number, in big-endian order.
54
+	 */
55
+	uint32_t lba;
56
+	/** Group number */
57
+	uint8_t group;
58
+	/** Transfer length
59
+	 *
60
+	 * This is a logical block count, in big-endian order.
61
+	 */
62
+	uint16_t len;
63
+	/** Control byte */
64
+	uint8_t control;
65
+} __attribute__ (( packed ));
66
+
43
 /** A SCSI "READ (16)" CDB */
67
 /** A SCSI "READ (16)" CDB */
44
 struct scsi_cdb_read_16 {
68
 struct scsi_cdb_read_16 {
45
 	/** Opcode (0x88) */
69
 	/** Opcode (0x88) */
62
 	uint8_t control;
86
 	uint8_t control;
63
 } __attribute__ (( packed ));
87
 } __attribute__ (( packed ));
64
 
88
 
89
+/** A SCSI "WRITE (10)" CDB */
90
+struct scsi_cdb_write_10 {
91
+	/** Opcode (0x2a) */
92
+	uint8_t opcode;
93
+	/** Flags */
94
+	uint8_t flags;
95
+	/** Start address
96
+	 *
97
+	 * This is a logical block number, in big-endian order.
98
+	 */
99
+	uint32_t lba;
100
+	/** Group number */
101
+	uint8_t group;
102
+	/** Transfer length
103
+	 *
104
+	 * This is a logical block count, in big-endian order.
105
+	 */
106
+	uint16_t len;
107
+	/** Control byte */
108
+	uint8_t control;
109
+} __attribute__ (( packed ));
110
+
65
 /** A SCSI "WRITE (16)" CDB */
111
 /** A SCSI "WRITE (16)" CDB */
66
 struct scsi_cdb_write_16 {
112
 struct scsi_cdb_write_16 {
67
 	/** Opcode (0x8a) */
113
 	/** Opcode (0x8a) */
143
 
189
 
144
 /** A SCSI Command Data Block */
190
 /** A SCSI Command Data Block */
145
 union scsi_cdb {
191
 union scsi_cdb {
192
+	struct scsi_cdb_read_10 read10;
146
 	struct scsi_cdb_read_16 read16;
193
 	struct scsi_cdb_read_16 read16;
194
+	struct scsi_cdb_write_10 write10;
147
 	struct scsi_cdb_write_16 write16;
195
 	struct scsi_cdb_write_16 write16;
148
 	struct scsi_cdb_read_capacity_10 readcap10;
196
 	struct scsi_cdb_read_capacity_10 readcap10;
149
 	struct scsi_cdb_read_capacity_16 readcap16;
197
 	struct scsi_cdb_read_capacity_16 readcap16;

Loading…
Cancel
Save