Browse Source

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

based on the device size.
tags/v0.9.3
Michael Brown 17 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,7 +70,7 @@ static int scsi_command ( struct scsi_device *scsi,
70 70
 }
71 71
 
72 72
 /**
73
- * Read block from SCSI device
73
+ * Read block from SCSI device using READ (10)
74 74
  *
75 75
  * @v blockdev		Block device
76 76
  * @v block		LBA block number
@@ -78,8 +78,33 @@ static int scsi_command ( struct scsi_device *scsi,
78 78
  * @v buffer		Data buffer
79 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 108
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
84 109
 	struct scsi_command command;
85 110
 	struct scsi_cdb_read_16 *cdb = &command.cdb.read16;
@@ -95,7 +120,7 @@ static int scsi_read ( struct block_device *blockdev, uint64_t block,
95 120
 }
96 121
 
97 122
 /**
98
- * Write block to SCSI device
123
+ * Write block to SCSI device using WRITE (10)
99 124
  *
100 125
  * @v blockdev		Block device
101 126
  * @v block		LBA block number
@@ -103,8 +128,33 @@ static int scsi_read ( struct block_device *blockdev, uint64_t block,
103 128
  * @v buffer		Data buffer
104 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 158
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
109 159
 	struct scsi_command command;
110 160
 	struct scsi_cdb_write_16 *cdb = &command.cdb.write16;
@@ -179,12 +229,17 @@ static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
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 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 243
 	int rc;
189 244
 
190 245
 	/* Issue a theoretically extraneous READ CAPACITY (10)
@@ -192,10 +247,12 @@ static int scsi_read_capacity ( struct block_device *blockdev ) {
192 247
 	 * (power-on occurred)" that some dumb targets insist on
193 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 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 256
 		return rc;
200 257
 
201 258
 	/* If capacity range was exceeded (i.e. capacity.lba was
@@ -203,28 +260,12 @@ static int scsi_read_capacity ( struct block_device *blockdev ) {
203 260
 	 * READ CAPACITY (16) instead.  READ CAPACITY (16) is not
204 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 267
 			return rc;
209 268
 	}
210 269
 
211 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,7 +16,9 @@
16 16
  * @{
17 17
  */
18 18
 
19
+#define SCSI_OPCODE_READ_10		0x28	/**< READ (10) */
19 20
 #define SCSI_OPCODE_READ_16		0x88	/**< READ (16) */
21
+#define SCSI_OPCODE_WRITE_10		0x2a	/**< WRITE (10) */
20 22
 #define SCSI_OPCODE_WRITE_16		0x8a	/**< WRITE (16) */
21 23
 #define SCSI_OPCODE_READ_CAPACITY_10	0x25	/**< READ CAPACITY (10) */
22 24
 #define SCSI_OPCODE_SERVICE_ACTION_IN	0x9e	/**< SERVICE ACTION IN */
@@ -40,6 +42,28 @@
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 67
 /** A SCSI "READ (16)" CDB */
44 68
 struct scsi_cdb_read_16 {
45 69
 	/** Opcode (0x88) */
@@ -62,6 +86,28 @@ struct scsi_cdb_read_16 {
62 86
 	uint8_t control;
63 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 111
 /** A SCSI "WRITE (16)" CDB */
66 112
 struct scsi_cdb_write_16 {
67 113
 	/** Opcode (0x8a) */
@@ -143,7 +189,9 @@ struct scsi_capacity_16 {
143 189
 
144 190
 /** A SCSI Command Data Block */
145 191
 union scsi_cdb {
192
+	struct scsi_cdb_read_10 read10;
146 193
 	struct scsi_cdb_read_16 read16;
194
+	struct scsi_cdb_write_10 write10;
147 195
 	struct scsi_cdb_write_16 write16;
148 196
 	struct scsi_cdb_read_capacity_10 readcap10;
149 197
 	struct scsi_cdb_read_capacity_16 readcap16;

Loading…
Cancel
Save