Browse Source

READ CAPACITY (16) turns out to be an optional command (even though

READ(16) is mandatory); we must use READ CAPACITY (10) first and then
use READ CAPACITY (16) if the READ CAPACITY (10) returns "out of range".
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
402ba15c64
2 changed files with 84 additions and 2 deletions
  1. 57
    2
      src/drivers/block/scsi.c
  2. 27
    0
      src/include/gpxe/scsi.h

+ 57
- 2
src/drivers/block/scsi.c View File

96
 }
96
 }
97
 
97
 
98
 /**
98
 /**
99
- * Read capacity of SCSI device
99
+ * Read capacity of SCSI device via READ CAPACITY (10)
100
  *
100
  *
101
  * @v blockdev		Block device
101
  * @v blockdev		Block device
102
  * @ret rc		Return status code
102
  * @ret rc		Return status code
103
  */
103
  */
104
-static int scsi_read_capacity ( struct block_device *blockdev ) {
104
+static int scsi_read_capacity_10 ( struct block_device *blockdev ) {
105
+	struct scsi_device *scsi = block_to_scsi ( blockdev );
106
+	struct scsi_command command;
107
+	struct scsi_cdb_read_capacity_10 *cdb = &command.cdb.readcap10;
108
+	struct scsi_capacity_10 capacity;
109
+	int rc;
110
+
111
+	/* Issue READ CAPACITY (10) */
112
+	memset ( &command, 0, sizeof ( command ) );
113
+	cdb->opcode = SCSI_OPCODE_READ_CAPACITY_10;
114
+	command.data_in = virt_to_user ( &capacity );
115
+	command.data_in_len = sizeof ( capacity );
116
+
117
+	if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
118
+		return rc;
119
+
120
+	/* Fill in block device fields */
121
+	blockdev->blksize = be32_to_cpu ( capacity.blksize );
122
+	blockdev->blocks = ( be32_to_cpu ( capacity.lba ) + 1 );
123
+
124
+	return 0;
125
+}
126
+
127
+/**
128
+ * Read capacity of SCSI device via READ CAPACITY (16)
129
+ *
130
+ * @v blockdev		Block device
131
+ * @ret rc		Return status code
132
+ */
133
+static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
105
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
134
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
106
 	struct scsi_command command;
135
 	struct scsi_command command;
107
 	struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
136
 	struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
125
 	return 0;
154
 	return 0;
126
 }
155
 }
127
 
156
 
157
+/**
158
+ * Read capacity of SCSI device
159
+ *
160
+ * @v blockdev		Block device
161
+ * @ret rc		Return status code
162
+ */
163
+static int scsi_read_capacity ( struct block_device *blockdev ) {
164
+	int rc;
165
+
166
+	/* Try READ CAPACITY (10), which is a mandatory command, first. */
167
+	if ( ( rc = scsi_read_capacity_10 ( blockdev ) ) != 0 )
168
+		return rc;
169
+
170
+	/* If capacity range was exceeded (i.e. capacity.lba was
171
+	 * 0xffffffff, meaning that blockdev->blocks is now zero), use
172
+	 * READ CAPACITY (16) instead.  READ CAPACITY (16) is not
173
+	 * mandatory, so we can't just use it straight off.
174
+	 */
175
+	if ( blockdev->blocks == 0 ) {
176
+		if ( ( rc = scsi_read_capacity_16 ( blockdev ) ) != 0 )
177
+			return rc;
178
+	}
179
+
180
+	return 0;
181
+}
182
+
128
 /**
183
 /**
129
  * Initialise SCSI device
184
  * Initialise SCSI device
130
  *
185
  *

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

12
 
12
 
13
 #define SCSI_OPCODE_READ_16		0x88	/**< READ (16) */
13
 #define SCSI_OPCODE_READ_16		0x88	/**< READ (16) */
14
 #define SCSI_OPCODE_WRITE_16		0x8a	/**< WRITE (16) */
14
 #define SCSI_OPCODE_WRITE_16		0x8a	/**< WRITE (16) */
15
+#define SCSI_OPCODE_READ_CAPACITY_10	0x25	/**< READ CAPACITY (10) */
15
 #define SCSI_OPCODE_SERVICE_ACTION_IN	0x9e	/**< SERVICE ACTION IN */
16
 #define SCSI_OPCODE_SERVICE_ACTION_IN	0x9e	/**< SERVICE ACTION IN */
16
 #define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
17
 #define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
17
 
18
 
77
 	uint8_t control;
78
 	uint8_t control;
78
 } __attribute__ (( packed ));
79
 } __attribute__ (( packed ));
79
 
80
 
81
+/** A SCSI "READ CAPACITY (10)" CDB */
82
+struct scsi_cdb_read_capacity_10 {
83
+	/** Opcode (0x25) */
84
+	uint8_t opcode;
85
+	/** Reserved */
86
+	uint8_t reserved_a;
87
+	/** Logical block address
88
+	 *
89
+	 * Applicable only if the PMI bit is set.
90
+	 */
91
+	uint32_t lba;
92
+	/** Reserved */
93
+	uint8_t reserved_b[3];
94
+	/** Control byte */
95
+	uint8_t control;	
96
+} __attribute__ (( packed ));
97
+
98
+/** SCSI "READ CAPACITY (10)" parameter data */
99
+struct scsi_capacity_10 {
100
+	/** Maximum logical block number */
101
+	uint32_t lba;
102
+	/** Block length in bytes */
103
+	uint32_t blksize;
104
+} __attribute__ (( packed ));
105
+
80
 /** A SCSI "READ CAPACITY (16)" CDB */
106
 /** A SCSI "READ CAPACITY (16)" CDB */
81
 struct scsi_cdb_read_capacity_16 {
107
 struct scsi_cdb_read_capacity_16 {
82
 	/** Opcode (0x9e) */
108
 	/** Opcode (0x9e) */
113
 union scsi_cdb {
139
 union scsi_cdb {
114
 	struct scsi_cdb_read_16 read16;
140
 	struct scsi_cdb_read_16 read16;
115
 	struct scsi_cdb_write_16 write16;
141
 	struct scsi_cdb_write_16 write16;
142
+	struct scsi_cdb_read_capacity_10 readcap10;
116
 	struct scsi_cdb_read_capacity_16 readcap16;
143
 	struct scsi_cdb_read_capacity_16 readcap16;
117
 	char bytes[16];
144
 	char bytes[16];
118
 };
145
 };

Loading…
Cancel
Save