diff options
author | Björn Stenberg <bjorn@haxx.se> | 2003-03-14 16:06:09 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2003-03-14 16:06:09 +0000 |
commit | bb6e51aa0df865009680518ef04334f064fb6509 (patch) | |
tree | eb00545dbbc528eb3878c8811fe5db340f50150d /firmware/drivers | |
parent | 67c1a0c63cc1cb0e9f405d6d763b5f642bd998ad (diff) |
Moved read code around a bit to more strictly obey the ATA specification.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3444 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/ata.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 523b080ec8..26602b1342 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c @@ -221,19 +221,13 @@ int ata_read_sectors(unsigned long start, int j; int sectors; int wordcount; + int status; if (!wait_for_start_of_transfer()) { ret = -4; goto retry; } - if ( ATA_ALT_STATUS & (STATUS_ERR | STATUS_DF) ) { - ret = -5; - if (perform_soft_reset()) - break; - goto retry; - } - if (spinup) { ata_spinup_time = current_tick - last_disk_activity; spinup = false; @@ -241,6 +235,9 @@ int ata_read_sectors(unsigned long start, poweroff = false; } + /* read the status register exactly once per loop */ + status = ATA_STATUS; + /* if destination address is odd, use byte copying, otherwise use word copying */ @@ -263,10 +260,18 @@ int ata_read_sectors(unsigned long start, ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); } -#ifdef USE_INTERRUPT - /* reading the status register clears the interrupt */ - j = ATA_STATUS; -#endif + /* + "Device errors encountered during READ MULTIPLE commands are + posted at the beginning of the block or partial block transfer, + but the DRQ bit is still set to one and the data transfer shall + take place, including transfer of corrupted data, if any." + -- ATA specification + */ + if ( status & (STATUS_BSY | STATUS_ERR | STATUS_DF) ) { + ret = -5; + goto retry; + } + buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */ count -= sectors; |