Browse Source

Use separate data-in and data-out buffers.

Increase code simplicity at the expense of around 64 bytes.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
6f998cecb3
2 changed files with 67 additions and 69 deletions
  1. 30
    40
      src/drivers/block/ata.c
  2. 37
    29
      src/include/gpxe/ata.h

+ 30
- 40
src/drivers/block/ata.c View File

@@ -51,55 +51,32 @@ ata_command ( struct ata_device *ata, struct ata_command *command ) {
51 51
 }
52 52
 
53 53
 /**
54
- * Read block from / write block to ATA device
54
+ * Read block from ATA device
55 55
  *
56
- * @v write		Write flag (ATA_FL_WRITE or 0)
57 56
  * @v blockdev		Block device
58 57
  * @v block		LBA block number
59 58
  * @v count		Block count
60 59
  * @v buffer		Data buffer
61 60
  * @ret rc		Return status code
62 61
  */
63
-static __attribute__ (( regparm ( 1 ) )) int
64
-ata_rw ( int write, struct block_device *blockdev, uint64_t block,
65
-	 unsigned long count, userptr_t buffer ) {
62
+static int ata_read ( struct block_device *blockdev, uint64_t block,
63
+		      unsigned long count, userptr_t buffer ) {
66 64
 	struct ata_device *ata = block_to_ata ( blockdev );
67 65
 	struct ata_command command;
68
-	int lba48 = ( ata->flags & ATA_FL_LBA48 );
69 66
 
70 67
 	memset ( &command, 0, sizeof ( command ) );
71 68
 	command.cb.lba.native = block;
72 69
 	command.cb.count.native = count;
73
-	command.cb.device = ( ata->flags | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
74
-	command.cb.flags = ( ata->flags | write );
75
-	command.cb.cmd_stat = ( write ? ATA_CMD_WRITE : ATA_CMD_READ );
76
-	if ( lba48 ) {
77
-		command.cb.cmd_stat |= ATA_CMD_EXT;
78
-	} else {
70
+	command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
71
+	command.cb.lba48 = ata->lba48;
72
+	if ( ! ata->lba48 )
79 73
 		command.cb.device |= command.cb.lba.bytes.low_prev;
80
-	}
81
-	command.data = buffer;
82
-	command.data_len = ( count * blockdev->blksize );
74
+	command.cb.cmd_stat = ( ata->lba48 ? ATA_CMD_READ_EXT : ATA_CMD_READ );
75
+	command.data_in = buffer;
76
+	command.data_in_len = ( count * blockdev->blksize );
83 77
 	return ata_command ( ata, &command );
84 78
 }
85 79
 
86
-/**
87
- * Read block from ATA device
88
- *
89
- * @v blockdev		Block device
90
- * @v block		LBA block number
91
- * @v count		Block count
92
- * @v buffer		Data buffer
93
- * @ret rc		Return status code
94
- */
95
-static int ata_read ( struct block_device *blockdev, uint64_t block,
96
-		      unsigned long count, userptr_t buffer ) {
97
-	/* Pass through to ata_rw().  Since ata_rw is regparm(1), this
98
-	 * is extremely efficient; just a mov and a jmp.
99
-	 */
100
-	return ata_rw ( 0, blockdev, block, count, buffer );
101
-}
102
-
103 80
 /**
104 81
  * Write block to ATA device
105 82
  *
@@ -111,10 +88,21 @@ static int ata_read ( struct block_device *blockdev, uint64_t block,
111 88
  */
112 89
 static int ata_write ( struct block_device *blockdev, uint64_t block,
113 90
 		       unsigned long count, userptr_t buffer ) {
114
-	/* Pass through to ata_rw().  Since ata_rw is regparm(1), this
115
-	 * is extremely efficient; just a mov and a jmp.
116
-	 */
117
-	return ata_rw ( ATA_FL_WRITE, blockdev, block, count, buffer );
91
+	struct ata_device *ata = block_to_ata ( blockdev );
92
+	struct ata_command command;
93
+	
94
+	memset ( &command, 0, sizeof ( command ) );
95
+	command.cb.lba.native = block;
96
+	command.cb.count.native = count;
97
+	command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
98
+	command.cb.lba48 = ata->lba48;
99
+	if ( ! ata->lba48 )
100
+		command.cb.device |= command.cb.lba.bytes.low_prev;
101
+	command.cb.cmd_stat = ( ata->lba48 ?
102
+				ATA_CMD_WRITE_EXT : ATA_CMD_WRITE );
103
+	command.data_out = buffer;
104
+	command.data_out_len = ( count * blockdev->blksize );
105
+	return ata_command ( ata, &command );
118 106
 }
119 107
 
120 108
 /**
@@ -131,17 +119,19 @@ static int ata_identify ( struct block_device *blockdev ) {
131 119
 
132 120
 	/* Issue IDENTIFY */
133 121
 	memset ( &command, 0, sizeof ( command ) );
134
-	command.cb.device = ( ata->flags | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
122
+	command.cb.count.native = 1; /* n/a according to spec, but at least
123
+				      * AoE vblade devices require it. */
124
+	command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
135 125
 	command.cb.cmd_stat = ATA_CMD_IDENTIFY;
136
-	command.data = virt_to_user ( &identity );
137
-	command.data_len = sizeof ( identity );
126
+	command.data_in = virt_to_user ( &identity );
127
+	command.data_in_len = sizeof ( identity );
138 128
 	if ( ( rc = ata_command ( ata, &command ) ) != 0 )
139 129
 		return rc;
140 130
 
141 131
 	/* Fill in block device parameters */
142 132
 	blockdev->blksize = ATA_SECTOR_SIZE;
143 133
 	if ( identity.supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
144
-		ata->flags |= ATA_FL_LBA48;
134
+		ata->lba48 = 1;
145 135
 		blockdev->blocks = le64_to_cpu ( identity.lba48_sectors );
146 136
 	} else {
147 137
 		blockdev->blocks = le32_to_cpu ( identity.lba_sectors );

+ 37
- 29
src/include/gpxe/ata.h View File

@@ -56,9 +56,9 @@ union ata_lba {
56 56
 		uint8_t low_prev;
57 57
 		uint8_t mid_prev;
58 58
 		uint8_t high_prev;
59
-		uint8_t pad[2];
59
+		uint16_t pad;
60 60
 #elif __BYTE_ORDER == __BIG_ENDIAN
61
-		uint8_t pad[2];
61
+		uint16_t pad;
62 62
 		uint8_t high_prev;
63 63
 		uint8_t mid_prev;
64 64
 		uint8_t low_prev;
@@ -101,52 +101,55 @@ struct ata_cb {
101 101
 	uint8_t device;
102 102
 	/** Command/status register */
103 103
 	uint8_t cmd_stat;
104
-	/** Flags
105
-	 *
106
-	 * This field does not correspond to any ATA register.
107
-	 */
108
-	uint8_t flags;
104
+	/** LBA48 addressing flag */
105
+	int lba48;
109 106
 };
110 107
 
111
-/** LBA48 extended addressing */
112
-#define ATA_FL_LBA48 0x40
113
-
114
-/** Device 1 ("slave") */
115
-#define ATA_FL_SLAVE 0x10
116
-
117
-/** Write command */
118
-#define ATA_FL_WRITE 0x01
119
-
120 108
 /** Obsolete bits in the ATA device register */
121 109
 #define ATA_DEV_OBSOLETE 0xa0
122 110
 
123 111
 /** LBA flag in the ATA device register */
124 112
 #define ATA_DEV_LBA 0x40
125 113
 
114
+/** Slave ("device 1") flag in the ATA device register */
115
+#define ATA_DEV_SLAVE 0x10
116
+
117
+/** Master ("device 0") flag in the ATA device register */
118
+#define ATA_DEV_MASTER 0x00
119
+
126 120
 /** "Read sectors" command */
127 121
 #define ATA_CMD_READ 0x20
128 122
 
123
+/** "Read sectors (ext)" command */
124
+#define ATA_CMD_READ_EXT 0x24
125
+
129 126
 /** "Write sectors" command */
130 127
 #define ATA_CMD_WRITE 0x30
131 128
 
129
+/** "Write sectors (ext)" command */
130
+#define ATA_CMD_WRITE_EXT 0x34
131
+
132 132
 /** "Identify" command */
133 133
 #define ATA_CMD_IDENTIFY 0xec
134 134
 
135
-/** "Extended (LBA48)" command modifier
136
- *
137
- * This doesn't apply to all ATA commands, but it does for @c
138
- * ATA_CMD_READ and @c ATA_CMD_WRITE.
139
- */
140
-#define ATA_CMD_EXT 0x04
141
-
142 135
 /** An ATA command */
143 136
 struct ata_command {
144 137
 	/** ATA command block */
145 138
 	struct ata_cb cb;
146
-	/** Data buffer */
147
-	userptr_t data;
148
-	/** Data buffer length */
149
-	size_t data_len;
139
+	/** Data-out buffer (may be NULL) */
140
+	userptr_t data_out;
141
+	/** Data-out buffer length
142
+	 *
143
+	 * Must be zero if @c data_out is NULL
144
+	 */
145
+	size_t data_out_len;
146
+	/** Data-in buffer (may be NULL) */
147
+	userptr_t data_in;
148
+	/** Data-in buffer length
149
+	 *
150
+	 * Must be zero if @c data_in is NULL
151
+	 */
152
+	size_t data_in_len;
150 153
 };
151 154
 
152 155
 /**
@@ -175,8 +178,13 @@ struct ata_identity {
175 178
 struct ata_device {
176 179
 	/** Block device interface */
177 180
 	struct block_device blockdev;
178
-	/** Flags */
179
-	int flags;
181
+	/** Device number
182
+	 *
183
+	 * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
184
+	 */
185
+	int device;
186
+	/** LBA48 extended addressing */
187
+	int lba48;
180 188
 	/**
181 189
 	 * Issue ATA command
182 190
 	 *

Loading…
Cancel
Save