summaryrefslogtreecommitdiffstats
path: root/firmware/drivers/ata.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/ata.c')
-rw-r--r--firmware/drivers/ata.c84
1 files changed, 37 insertions, 47 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 7d306084e4..d2e1ad4a22 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -164,8 +164,8 @@ static inline bool ata_power_off_timed_out(void)
static ICODE_ATTR int wait_for_bsy(void)
{
long timeout = current_tick + HZ*30;
-
- do
+
+ do
{
if (!(ATA_IN8(ATA_STATUS) & STATUS_BSY))
return 1;
@@ -184,8 +184,8 @@ static ICODE_ATTR int wait_for_rdy(void)
return 0;
timeout = current_tick + HZ*10;
-
- do
+
+ do
{
if (ATA_IN8(ATA_ALT_STATUS) & STATUS_RDY)
return 1;
@@ -220,6 +220,15 @@ static int ata_perform_wakeup(int state)
static int ata_perform_sleep(void)
{
+ /* Don't issue the sleep command if the device
+ doesn't support (mandatory!) ATA power management commands!
+
+ The FC1307A ATA->SD chipset (used by the common iFlash adapters)
+ is the only known offender, and will eat your data if told to sleep.
+ */
+ if (!(identify_info[82] & (1 << 3)))
+ return 0;
+
ATA_OUT8(ATA_SELECT, ata_device);
if(!wait_for_rdy()) {
@@ -250,15 +259,15 @@ static ICODE_ATTR int wait_for_end_of_transfer(void)
{
if (!wait_for_bsy())
return 0;
- return (ATA_IN8(ATA_ALT_STATUS) &
+ return (ATA_IN8(ATA_ALT_STATUS) &
(STATUS_BSY|STATUS_RDY|STATUS_DF|STATUS_DRQ|STATUS_ERR))
== STATUS_RDY;
-}
+}
#if (CONFIG_LED == LED_REAL)
/* Conditionally block LED access for the ATA driver, so the LED can be
* (mis)used for other purposes */
-static void ata_led(bool on)
+static void ata_led(bool on)
{
ata_led_on = on;
if (ata_led_enabled)
@@ -591,7 +600,7 @@ static int cache_sector(unsigned long sector)
{
int rc;
- sector &= ~(phys_sector_mult - 1);
+ sector &= ~(phys_sector_mult - 1);
/* round down to physical sector boundary */
/* check whether the sector is already cached */
@@ -602,7 +611,7 @@ static int cache_sector(unsigned long sector)
sector_cache.inuse = false;
rc = ata_transfer_sectors(sector, phys_sector_mult, sector_cache.data, false);
if (!rc)
- {
+ {
sector_cache.sectornum = sector;
sector_cache.inuse = true;
}
@@ -627,19 +636,19 @@ int ata_read_sectors(IF_MD(int drive,)
(void)drive; /* unused for now */
#endif
mutex_lock(&ata_mtx);
-
+
offset = start & (phys_sector_mult - 1);
-
+
if (offset) /* first partial sector */
{
int partcount = MIN(incount, phys_sector_mult - offset);
-
+
rc = cache_sector(start);
if (rc)
{
rc = rc * 10 - 1;
goto error;
- }
+ }
memcpy(inbuf, sector_cache.data + offset * SECTOR_SIZE,
partcount * SECTOR_SIZE);
@@ -651,7 +660,7 @@ int ata_read_sectors(IF_MD(int drive,)
{
offset = incount & (phys_sector_mult - 1);
incount -= offset;
-
+
if (incount)
{
rc = ata_transfer_sectors(start, incount, inbuf, false);
@@ -693,9 +702,9 @@ int ata_write_sectors(IF_MD(int drive,)
(void)drive; /* unused for now */
#endif
mutex_lock(&ata_mtx);
-
+
offset = start & (phys_sector_mult - 1);
-
+
if (offset) /* first partial sector */
{
int partcount = MIN(count, phys_sector_mult - offset);
@@ -705,7 +714,7 @@ int ata_write_sectors(IF_MD(int drive,)
{
rc = rc * 10 - 1;
goto error;
- }
+ }
memcpy(sector_cache.data + offset * SECTOR_SIZE, buf,
partcount * SECTOR_SIZE);
rc = flush_current_sector();
@@ -713,7 +722,7 @@ int ata_write_sectors(IF_MD(int drive,)
{
rc = rc * 10 - 2;
goto error;
- }
+ }
start += partcount;
buf += partcount * SECTOR_SIZE;
count -= partcount;
@@ -722,7 +731,7 @@ int ata_write_sectors(IF_MD(int drive,)
{
offset = count & (phys_sector_mult - 1);
count -= offset;
-
+
if (count)
{
rc = ata_transfer_sectors(start, count, (void*)buf, true);
@@ -742,7 +751,7 @@ int ata_write_sectors(IF_MD(int drive,)
rc = rc * 10 - 4;
goto error;
}
- memcpy(sector_cache.data, buf, offset * SECTOR_SIZE);
+ memcpy(sector_cache.data, buf, offset * SECTOR_SIZE);
rc = flush_current_sector();
if (rc)
{
@@ -809,30 +818,11 @@ void ata_spindown(int seconds)
bool ata_disk_is_active(void)
{
- /* "active" here means "spinning / not sleeping"
- we normally leave active state by putting the device to
- sleep (using ATA powersave commands) which flushes all writes
- and puts the device into an inactive/quiescent state.
-
- Unfortuantely the CF->SD chipset used by the common iFlash
- adapters does not support ATA powersave, which makes the
- "active/not" distinction irrelevant, so insead we just mirror
- the sd/mmc/flash storage drivers and claim that we're always
- inactive.
- */
- if (!(identify_info[82] & (1 << 3)))
- return false;
-
return ata_state >= ATA_SPINUP;
}
void ata_sleepnow(void)
{
- /* Don't enter sleep if the device doesn't support
- power management. See comment in ata_disk_is_active() */
- if (!(identify_info[82] & (1 << 3)))
- return;
-
if (ata_state >= ATA_SPINUP) {
mutex_lock(&ata_mtx);
if (ata_state == ATA_ON) {
@@ -954,7 +944,7 @@ static int perform_soft_reset(void)
int ata_soft_reset(void)
{
int ret = -6;
-
+
mutex_lock(&ata_mtx);
if (ata_state > ATA_OFF) {
@@ -969,7 +959,7 @@ int ata_soft_reset(void)
static int ata_power_on(void)
{
int rc;
-
+
ide_power_enable(true);
sleep(HZ/4); /* allow voltage to build up */
@@ -1100,7 +1090,7 @@ static int set_features(void)
}
else
features[4].id_word = 88;
-
+
features[4].id_bit = dma_mode & 7;
features[4].parameter = dma_mode;
#endif /* HAVE_ATA_DMA */
@@ -1172,7 +1162,7 @@ static int STORAGE_INIT_ATTR init_and_check(bool hard_reset)
rc = check_registers();
if (rc)
return -30 + rc;
-
+
return 0;
}
@@ -1243,7 +1233,7 @@ int STORAGE_INIT_ATTR ata_init(void)
{ /* (needs BigLBA addressing) */
if (identify_info[102] || identify_info[103])
panicf("Unsupported disk size: >= 2^32 sectors");
-
+
total_sectors = identify_info[100] | (identify_info[101] << 16);
lba48 = true; /* use BigLBA */
}
@@ -1282,7 +1272,7 @@ int STORAGE_INIT_ATTR ata_init(void)
if (rc == 0)
phys_sector_mult = 1;
}
-
+
if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE))
panicf("Unsupported physical sector size: %d",
phys_sector_mult * SECTOR_SIZE);
@@ -1301,7 +1291,7 @@ error:
}
#if (CONFIG_LED == LED_REAL)
-void ata_set_led_enabled(bool enabled)
+void ata_set_led_enabled(bool enabled)
{
ata_led_enabled = enabled;
if (ata_led_enabled)
@@ -1372,7 +1362,7 @@ int ata_num_drives(int first_drive)
{
/* We don't care which logical drive number(s) we have been assigned */
(void)first_drive;
-
+
return 1;
}
#endif