diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-09-24 14:23:18 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-09-24 14:23:18 +0000 |
commit | 70747f9bf38fd659be227b575e8d28faeeec6300 (patch) | |
tree | b0c5ee44d8c894fae406b37f5b2bb9a9c419afa1 /firmware/drivers/ata.c | |
parent | 2d8aef9ab7e747baa1a3e984ebb1855d9aabf6ff (diff) | |
download | rockbox-70747f9bf38fd659be227b575e8d28faeeec6300.tar.gz rockbox-70747f9bf38fd659be227b575e8d28faeeec6300.zip |
Added read retry.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2397 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/ata.c')
-rw-r--r-- | firmware/drivers/ata.c | 98 |
1 files changed, 53 insertions, 45 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 807d441351..d547692b56 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -81,6 +81,8 @@ | |||
81 | 81 | ||
82 | #define Q_SLEEP 0 | 82 | #define Q_SLEEP 0 |
83 | 83 | ||
84 | #define READ_TIMEOUT 5*HZ | ||
85 | |||
84 | static struct mutex ata_mtx; | 86 | static struct mutex ata_mtx; |
85 | char ata_device; /* device 0 (master) or 1 (slave) */ | 87 | char ata_device; /* device 0 (master) or 1 (slave) */ |
86 | int ata_io_address; /* 0x300 or 0x200, only valid on recorder */ | 88 | int ata_io_address; /* 0x300 or 0x200, only valid on recorder */ |
@@ -166,6 +168,7 @@ int ata_read_sectors(unsigned long start, | |||
166 | void* buf) | 168 | void* buf) |
167 | { | 169 | { |
168 | int ret = 0; | 170 | int ret = 0; |
171 | int timeout; | ||
169 | 172 | ||
170 | last_disk_activity = current_tick; | 173 | last_disk_activity = current_tick; |
171 | 174 | ||
@@ -196,62 +199,67 @@ int ata_read_sectors(unsigned long start, | |||
196 | 199 | ||
197 | led(true); | 200 | led(true); |
198 | 201 | ||
199 | if ( count == 256 ) | 202 | timeout = current_tick + READ_TIMEOUT; |
200 | ATA_NSECTOR = 0; /* 0 means 256 sectors */ | 203 | while (TIME_BEFORE(current_tick, timeout)) { |
201 | else | ||
202 | ATA_NSECTOR = (unsigned char)count; | ||
203 | |||
204 | ATA_SECTOR = start & 0xff; | ||
205 | ATA_LCYL = (start >> 8) & 0xff; | ||
206 | ATA_HCYL = (start >> 16) & 0xff; | ||
207 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | ata_device; | ||
208 | ATA_COMMAND = CMD_READ_MULTIPLE; | ||
209 | |||
210 | while (count) { | ||
211 | int j; | ||
212 | int sectors; | ||
213 | int wordcount; | ||
214 | 204 | ||
215 | if (!wait_for_start_of_transfer()) | 205 | if ( count == 256 ) |
216 | { | 206 | ATA_NSECTOR = 0; /* 0 means 256 sectors */ |
217 | led(false); | 207 | else |
218 | mutex_unlock(&ata_mtx); | 208 | ATA_NSECTOR = (unsigned char)count; |
219 | return -1; | 209 | |
220 | } | 210 | ATA_SECTOR = start & 0xff; |
211 | ATA_LCYL = (start >> 8) & 0xff; | ||
212 | ATA_HCYL = (start >> 16) & 0xff; | ||
213 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | ata_device; | ||
214 | ATA_COMMAND = CMD_READ_MULTIPLE; | ||
215 | |||
216 | while (count) { | ||
217 | int j; | ||
218 | int sectors; | ||
219 | int wordcount; | ||
220 | |||
221 | if (!wait_for_start_of_transfer()) { | ||
222 | ret = -4; | ||
223 | continue; | ||
224 | } | ||
221 | 225 | ||
222 | /* if destination address is odd, use byte copying, | 226 | /* if destination address is odd, use byte copying, |
223 | otherwise use word copying */ | 227 | otherwise use word copying */ |
224 | 228 | ||
225 | if (count >= multisectors ) | 229 | if (count >= multisectors ) |
226 | sectors = multisectors; | 230 | sectors = multisectors; |
227 | else | 231 | else |
228 | sectors = count; | 232 | sectors = count; |
229 | 233 | ||
230 | wordcount = sectors * SECTOR_SIZE / 2; | 234 | wordcount = sectors * SECTOR_SIZE / 2; |
231 | 235 | ||
232 | if ( (unsigned int)buf & 1 ) { | 236 | if ( (unsigned int)buf & 1 ) { |
233 | for (j=0; j < wordcount; j++) { | 237 | for (j=0; j < wordcount; j++) { |
234 | unsigned short tmp = SWAB16(ATA_DATA); | 238 | unsigned short tmp = SWAB16(ATA_DATA); |
235 | ((unsigned char*)buf)[j*2] = tmp >> 8; | 239 | ((unsigned char*)buf)[j*2] = tmp >> 8; |
236 | ((unsigned char*)buf)[j*2+1] = tmp & 0xff; | 240 | ((unsigned char*)buf)[j*2+1] = tmp & 0xff; |
241 | } | ||
242 | } | ||
243 | else { | ||
244 | for (j=0; j < wordcount; j++) | ||
245 | ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); | ||
237 | } | 246 | } |
238 | } | ||
239 | else { | ||
240 | for (j=0; j < wordcount; j++) | ||
241 | ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); | ||
242 | } | ||
243 | 247 | ||
244 | #ifdef USE_INTERRUPT | 248 | #ifdef USE_INTERRUPT |
245 | /* reading the status register clears the interrupt */ | 249 | /* reading the status register clears the interrupt */ |
246 | j = ATA_STATUS; | 250 | j = ATA_STATUS; |
247 | #endif | 251 | #endif |
248 | buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */ | 252 | buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */ |
249 | count -= sectors; | 253 | count -= sectors; |
250 | } | 254 | } |
251 | 255 | ||
252 | if(!wait_for_end_of_transfer()) | 256 | if(!wait_for_end_of_transfer()) { |
253 | ret = -3; | 257 | ret = -3; |
258 | continue; | ||
259 | } | ||
254 | 260 | ||
261 | break; | ||
262 | } | ||
255 | led(false); | 263 | led(false); |
256 | 264 | ||
257 | mutex_unlock(&ata_mtx); | 265 | mutex_unlock(&ata_mtx); |