Sfoglia il codice sorgente

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 18 anni fa
parent
commit
402ba15c64
2 ha cambiato i file con 84 aggiunte e 2 eliminazioni
  1. 57
    2
      src/drivers/block/scsi.c
  2. 27
    0
      src/include/gpxe/scsi.h

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

@@ -96,12 +96,41 @@ static int scsi_write ( struct block_device *blockdev, uint64_t block,
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 101
  * @v blockdev		Block device
102 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 134
 	struct scsi_device *scsi = block_to_scsi ( blockdev );
106 135
 	struct scsi_command command;
107 136
 	struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
@@ -125,6 +154,32 @@ static int scsi_read_capacity ( struct block_device *blockdev ) {
125 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 184
  * Initialise SCSI device
130 185
  *

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

@@ -12,6 +12,7 @@
12 12
 
13 13
 #define SCSI_OPCODE_READ_16		0x88	/**< READ (16) */
14 14
 #define SCSI_OPCODE_WRITE_16		0x8a	/**< WRITE (16) */
15
+#define SCSI_OPCODE_READ_CAPACITY_10	0x25	/**< READ CAPACITY (10) */
15 16
 #define SCSI_OPCODE_SERVICE_ACTION_IN	0x9e	/**< SERVICE ACTION IN */
16 17
 #define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
17 18
 
@@ -77,6 +78,31 @@ struct scsi_cdb_write_16 {
77 78
 	uint8_t control;
78 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 106
 /** A SCSI "READ CAPACITY (16)" CDB */
81 107
 struct scsi_cdb_read_capacity_16 {
82 108
 	/** Opcode (0x9e) */
@@ -113,6 +139,7 @@ struct scsi_capacity_16 {
113 139
 union scsi_cdb {
114 140
 	struct scsi_cdb_read_16 read16;
115 141
 	struct scsi_cdb_write_16 write16;
142
+	struct scsi_cdb_read_capacity_10 readcap10;
116 143
 	struct scsi_cdb_read_capacity_16 readcap16;
117 144
 	char bytes[16];
118 145
 };

Loading…
Annulla
Salva