Browse Source

Handle multi-sector reads by splitting them into subcommands.

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
6541338897
4 changed files with 54 additions and 3 deletions
  1. 1
    1
      src/drivers/ata/aoedev.c
  2. 2
    0
      src/include/gpxe/aoe.h
  3. 3
    0
      src/include/gpxe/ata.h
  4. 48
    2
      src/net/aoe.c

+ 1
- 1
src/drivers/ata/aoedev.c View File

@@ -37,7 +37,7 @@ static int aoe_command ( struct ata_device *ata,
37 37
 	struct aoe_device *aoedev
38 38
 		= container_of ( ata, struct aoe_device, ata );
39 39
 
40
-	return aoe_issue ( &aoedev->aoe, command );
40
+	return aoe_issue_split ( &aoedev->aoe, command );
41 41
 }
42 42
 
43 43
 /**

+ 2
- 0
src/include/gpxe/aoe.h View File

@@ -110,6 +110,8 @@ struct aoe_session {
110 110
 extern void aoe_open ( struct aoe_session *aoe );
111 111
 extern void aoe_close ( struct aoe_session *aoe );
112 112
 extern int aoe_issue ( struct aoe_session *aoe, struct ata_command *command );
113
+extern int aoe_issue_split ( struct aoe_session *aoe,
114
+			     struct ata_command *command );
113 115
 
114 116
 /** An AoE device */
115 117
 struct aoe_device {

+ 3
- 0
src/include/gpxe/ata.h View File

@@ -117,6 +117,9 @@ struct ata_cb {
117 117
 /** Master ("device 0") flag in the ATA device register */
118 118
 #define ATA_DEV_MASTER 0x00
119 119
 
120
+/** Mask of non-LBA portion of device register */
121
+#define ATA_DEV_MASK 0xf0
122
+
120 123
 /** "Read sectors" command */
121 124
 #define ATA_CMD_READ 0x20
122 125
 

+ 48
- 2
src/net/aoe.c View File

@@ -84,7 +84,7 @@ static int aoe_send_command ( struct aoe_session *aoe ) {
84 84
 	aoecmd->cmd_stat = command->cb.cmd_stat;
85 85
 	aoecmd->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
86 86
 	if ( ! command->cb.lba48 )
87
-		aoecmd->lba.bytes[3] |= command->cb.device;
87
+		aoecmd->lba.bytes[3] |= ( command->cb.device & ATA_DEV_MASK );
88 88
 
89 89
 	/* Fill data payload */
90 90
 	copy_from_user ( pkb_put ( pkb, command->data_out_len ),
@@ -244,8 +244,11 @@ void aoe_kick ( struct aoe_session *aoe ) {
244 244
  * Issue ATA command via an open AoE session
245 245
  *
246 246
  * @v aoe		AoE session
247
- * @v command		AoE command
247
+ * @v command		ATA command
248 248
  * @ret rc		Return status code
249
+ *
250
+ * The ATA command must fit within a single AoE frame (i.e. the sector
251
+ * count must not exceed AOE_MAX_COUNT).
249 252
  */
250 253
 int aoe_issue ( struct aoe_session *aoe, struct ata_command *command ) {
251 254
 	aoe->command = command;
@@ -259,3 +262,46 @@ int aoe_issue ( struct aoe_session *aoe, struct ata_command *command ) {
259 262
 
260 263
 	return ( ( aoe->status & AOE_STATUS_ERR_MASK ) ? -EIO : 0 );
261 264
 }
265
+
266
+/**
267
+ * Issue ATA command via an open AoE session
268
+ *
269
+ * @v aoe		AoE session
270
+ * @v command		ATA command
271
+ * @ret rc		Return status code
272
+ *
273
+ * The ATA command will be split into several smaller ATA commands,
274
+ * each with a sector count no larger than AOE_MAX_COUNT.
275
+ */
276
+int aoe_issue_split ( struct aoe_session *aoe, struct ata_command *command ) {
277
+	struct ata_command subcommand;
278
+	unsigned int offset;
279
+	unsigned int count;
280
+	unsigned int data_len;
281
+	unsigned int status = 0;
282
+	int rc = 0;
283
+
284
+	/* Split ATA command into AoE-sized subcommands */
285
+	for ( offset = 0; offset < command->cb.count.native; offset += count ){
286
+		memcpy ( &subcommand, command, sizeof ( subcommand ) );
287
+		count = ( command->cb.count.native - offset );
288
+		if ( count > AOE_MAX_COUNT )
289
+			count = AOE_MAX_COUNT;
290
+		data_len = count * ATA_SECTOR_SIZE;
291
+		if ( subcommand.data_in_len )
292
+			subcommand.data_in_len = data_len;
293
+		if ( subcommand.data_out_len )
294
+			subcommand.data_out_len = data_len;
295
+		aoe->command_offset = ( offset * ATA_SECTOR_SIZE );
296
+		subcommand.cb.lba.native += offset;
297
+		subcommand.cb.count.native = count;
298
+		if ( ( rc = aoe_issue ( aoe, &subcommand ) ) != 0 )
299
+			goto done;
300
+		status |= subcommand.cb.cmd_stat;
301
+	}
302
+	command->cb.cmd_stat = status;
303
+
304
+ done:
305
+	aoe->command_offset = 0;
306
+	return rc;
307
+}

Loading…
Cancel
Save