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
 	struct aoe_device *aoedev
37
 	struct aoe_device *aoedev
38
 		= container_of ( ata, struct aoe_device, ata );
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
 extern void aoe_open ( struct aoe_session *aoe );
110
 extern void aoe_open ( struct aoe_session *aoe );
111
 extern void aoe_close ( struct aoe_session *aoe );
111
 extern void aoe_close ( struct aoe_session *aoe );
112
 extern int aoe_issue ( struct aoe_session *aoe, struct ata_command *command );
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
 /** An AoE device */
116
 /** An AoE device */
115
 struct aoe_device {
117
 struct aoe_device {

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

117
 /** Master ("device 0") flag in the ATA device register */
117
 /** Master ("device 0") flag in the ATA device register */
118
 #define ATA_DEV_MASTER 0x00
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
 /** "Read sectors" command */
123
 /** "Read sectors" command */
121
 #define ATA_CMD_READ 0x20
124
 #define ATA_CMD_READ 0x20
122
 
125
 

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

84
 	aoecmd->cmd_stat = command->cb.cmd_stat;
84
 	aoecmd->cmd_stat = command->cb.cmd_stat;
85
 	aoecmd->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
85
 	aoecmd->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
86
 	if ( ! command->cb.lba48 )
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
 	/* Fill data payload */
89
 	/* Fill data payload */
90
 	copy_from_user ( pkb_put ( pkb, command->data_out_len ),
90
 	copy_from_user ( pkb_put ( pkb, command->data_out_len ),
244
  * Issue ATA command via an open AoE session
244
  * Issue ATA command via an open AoE session
245
  *
245
  *
246
  * @v aoe		AoE session
246
  * @v aoe		AoE session
247
- * @v command		AoE command
247
+ * @v command		ATA command
248
  * @ret rc		Return status code
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
 int aoe_issue ( struct aoe_session *aoe, struct ata_command *command ) {
253
 int aoe_issue ( struct aoe_session *aoe, struct ata_command *command ) {
251
 	aoe->command = command;
254
 	aoe->command = command;
259
 
262
 
260
 	return ( ( aoe->status & AOE_STATUS_ERR_MASK ) ? -EIO : 0 );
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