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 | |
parent | 2d8aef9ab7e747baa1a3e984ebb1855d9aabf6ff (diff) |
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.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 @@ #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); |