summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-09-24 14:23:18 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-09-24 14:23:18 +0000
commit70747f9bf38fd659be227b575e8d28faeeec6300 (patch)
treeb0c5ee44d8c894fae406b37f5b2bb9a9c419afa1 /firmware
parent2d8aef9ab7e747baa1a3e984ebb1855d9aabf6ff (diff)
downloadrockbox-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')
-rw-r--r--firmware/drivers/ata.c98
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 @@
#define Q_SLEEP 0
+#define READ_TIMEOUT 5*HZ
+
static struct mutex ata_mtx;
char ata_device; /* device 0 (master) or 1 (slave) */
int ata_io_address; /* 0x300 or 0x200, only valid on recorder */
@@ -166,6 +168,7 @@ int ata_read_sectors(unsigned long start,
void* buf)
{
int ret = 0;
+ int timeout;
last_disk_activity = current_tick;
@@ -196,62 +199,67 @@ int ata_read_sectors(unsigned long start,
led(true);
- if ( count == 256 )
- ATA_NSECTOR = 0; /* 0 means 256 sectors */
- else
- ATA_NSECTOR = (unsigned char)count;
-
- ATA_SECTOR = start & 0xff;
- ATA_LCYL = (start >> 8) & 0xff;
- ATA_HCYL = (start >> 16) & 0xff;
- ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | ata_device;
- ATA_COMMAND = CMD_READ_MULTIPLE;
-
- while (count) {
- int j;
- int sectors;
- int wordcount;
+ timeout = current_tick + READ_TIMEOUT;
+ while (TIME_BEFORE(current_tick, timeout)) {
- if (!wait_for_start_of_transfer())
- {
- led(false);
- mutex_unlock(&ata_mtx);
- return -1;
- }
+ if ( count == 256 )
+ ATA_NSECTOR = 0; /* 0 means 256 sectors */
+ else
+ ATA_NSECTOR = (unsigned char)count;
+
+ ATA_SECTOR = start & 0xff;
+ ATA_LCYL = (start >> 8) & 0xff;
+ ATA_HCYL = (start >> 16) & 0xff;
+ ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | ata_device;
+ ATA_COMMAND = CMD_READ_MULTIPLE;
+
+ while (count) {
+ int j;
+ int sectors;
+ int wordcount;
+
+ if (!wait_for_start_of_transfer()) {
+ ret = -4;
+ continue;
+ }
- /* if destination address is odd, use byte copying,
- otherwise use word copying */
+ /* if destination address is odd, use byte copying,
+ otherwise use word copying */
- if (count >= multisectors )
- sectors = multisectors;
- else
- sectors = count;
+ if (count >= multisectors )
+ sectors = multisectors;
+ else
+ sectors = count;
- wordcount = sectors * SECTOR_SIZE / 2;
+ wordcount = sectors * SECTOR_SIZE / 2;
- if ( (unsigned int)buf & 1 ) {
- for (j=0; j < wordcount; j++) {
- unsigned short tmp = SWAB16(ATA_DATA);
- ((unsigned char*)buf)[j*2] = tmp >> 8;
- ((unsigned char*)buf)[j*2+1] = tmp & 0xff;
+ if ( (unsigned int)buf & 1 ) {
+ for (j=0; j < wordcount; j++) {
+ unsigned short tmp = SWAB16(ATA_DATA);
+ ((unsigned char*)buf)[j*2] = tmp >> 8;
+ ((unsigned char*)buf)[j*2+1] = tmp & 0xff;
+ }
+ }
+ else {
+ for (j=0; j < wordcount; j++)
+ ((unsigned short*)buf)[j] = SWAB16(ATA_DATA);
}
- }
- else {
- for (j=0; j < wordcount; j++)
- ((unsigned short*)buf)[j] = SWAB16(ATA_DATA);
- }
#ifdef USE_INTERRUPT
- /* reading the status register clears the interrupt */
- j = ATA_STATUS;
+ /* reading the status register clears the interrupt */
+ j = ATA_STATUS;
#endif
- buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */
- count -= sectors;
- }
+ buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */
+ count -= sectors;
+ }
- if(!wait_for_end_of_transfer())
- ret = -3;
+ if(!wait_for_end_of_transfer()) {
+ ret = -3;
+ continue;
+ }
+ break;
+ }
led(false);
mutex_unlock(&ata_mtx);