summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
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;