summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2003-03-14 16:06:09 +0000
committerBjörn Stenberg <bjorn@haxx.se>2003-03-14 16:06:09 +0000
commitbb6e51aa0df865009680518ef04334f064fb6509 (patch)
treeeb00545dbbc528eb3878c8811fe5db340f50150d /firmware
parent67c1a0c63cc1cb0e9f405d6d763b5f642bd998ad (diff)
downloadrockbox-bb6e51aa0df865009680518ef04334f064fb6509.tar.gz
rockbox-bb6e51aa0df865009680518ef04334f064fb6509.zip
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')
-rw-r--r--firmware/drivers/ata.c27
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;