summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/ata.c75
1 files changed, 65 insertions, 10 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 10efecc342..29d2851875 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -28,6 +28,16 @@
28#include "usb.h" 28#include "usb.h"
29#include "power.h" 29#include "power.h"
30 30
31/* Define one of USE_STANDBY, USE_SLEEP or USE_POWEROFF */
32#define USE_STANDBY
33
34/* We can only use power off on the recorder */
35#if !defined(ARCHOS_RECORDER) && defined(USE_POWEROFF)
36#undef USE_POWEROFF
37#define USE_STANDBY
38#endif
39
40
31#define SECTOR_SIZE 512 41#define SECTOR_SIZE 512
32#define ATA_DATA (*((volatile unsigned short*)0x06104100)) 42#define ATA_DATA (*((volatile unsigned short*)0x06104100))
33#define ATA_ERROR (*((volatile unsigned char*)0x06100101)) 43#define ATA_ERROR (*((volatile unsigned char*)0x06100101))
@@ -80,6 +90,10 @@ static char ata_thread_name[] = "ata";
80static struct event_queue ata_queue; 90static struct event_queue ata_queue;
81static bool initialized = false; 91static bool initialized = false;
82 92
93#ifdef USE_POWEROFF
94static int ata_power_on(void);
95#endif
96
83static int wait_for_bsy(void) __attribute__ ((section (".icode"))); 97static int wait_for_bsy(void) __attribute__ ((section (".icode")));
84static int wait_for_bsy(void) 98static int wait_for_bsy(void)
85{ 99{
@@ -131,12 +145,19 @@ int ata_read_sectors(unsigned long start,
131 int i; 145 int i;
132 int ret = 0; 146 int ret = 0;
133 147
148#ifndef USE_STANDBY
134 if ( sleeping ) { 149 if ( sleeping ) {
150#ifdef USE_POWEROFF
151 if (ata_power_on()) {
152 return -1;
153 }
154#else
135 if (ata_soft_reset()) { 155 if (ata_soft_reset()) {
136 return -1; 156 return -1;
137 } 157 }
158#endif
138 } 159 }
139 160#endif
140 mutex_lock(&ata_mtx); 161 mutex_lock(&ata_mtx);
141 sleep_timer = sleep_timeout; 162 sleep_timer = sleep_timeout;
142 163
@@ -188,12 +209,17 @@ int ata_write_sectors(unsigned long start,
188{ 209{
189 int i; 210 int i;
190 211
191 if ( sleeping ) { 212#ifndef USE_STANDBY
213#ifdef USE_POWEROFF
214 if (ata_power_on()) {
215 return -1;
216 }
217#else
192 if (ata_soft_reset()) { 218 if (ata_soft_reset()) {
193 return -1; 219 return -1;
194 } 220 }
195 } 221#endif
196 222#endif
197 mutex_lock(&ata_mtx); 223 mutex_lock(&ata_mtx);
198 sleep_timer = sleep_timeout; 224 sleep_timer = sleep_timeout;
199 225
@@ -291,11 +317,15 @@ static int ata_perform_sleep(void)
291 return -1; 317 return -1;
292 } 318 }
293 319
294#ifdef ATA_POWER_OFF 320#ifdef USE_POWEROFF
295 ide_power_enable(false); 321 ide_power_enable(false);
296#else 322#else
297 ATA_SELECT = ata_device; 323 ATA_SELECT = ata_device;
324#ifdef USE_SLEEP
325 ATA_COMMAND = CMD_SLEEP;
326#else
298 ATA_COMMAND = CMD_STANDBY; 327 ATA_COMMAND = CMD_STANDBY;
328#endif
299 329
300 if (!wait_for_rdy()) 330 if (!wait_for_rdy())
301 ret = -1; 331 ret = -1;
@@ -373,17 +403,13 @@ int ata_soft_reset(void)
373 403
374 mutex_lock(&ata_mtx); 404 mutex_lock(&ata_mtx);
375 405
376#ifdef ATA_POWER_OFF
377 ide_power_enable(true);
378 sleep(HZ);
379#else
380 ATA_SELECT = SELECT_LBA | ata_device; 406 ATA_SELECT = SELECT_LBA | ata_device;
381 ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST; 407 ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST;
382 sleep(HZ/20000); /* >= 5us */ 408 sleep(HZ/20000); /* >= 5us */
383 409
384 ATA_CONTROL = CONTROL_nIEN; 410 ATA_CONTROL = CONTROL_nIEN;
385 sleep(HZ/400); /* >2ms */ 411 sleep(HZ/400); /* >2ms */
386#endif 412
387 /* This little sucker can take up to 30 seconds */ 413 /* This little sucker can take up to 30 seconds */
388 retry_count = 8; 414 retry_count = 8;
389 do 415 do
@@ -399,6 +425,35 @@ int ata_soft_reset(void)
399 return ret; 425 return ret;
400} 426}
401 427
428#ifdef USE_POWEROFF
429static int ata_power_on(void)
430{
431 int ret;
432 int retry_count;
433
434 mutex_lock(&ata_mtx);
435
436 ide_power_enable(true);
437 sleep(HZ/2);
438
439 ATA_CONTROL = CONTROL_nIEN;
440
441 /* This little sucker can take up to 30 seconds */
442 retry_count = 8;
443 do
444 {
445 ret = wait_for_rdy();
446 } while(!ret && retry_count--);
447
448 /* Massage the return code so it is 0 on success and -1 on failure */
449 ret = ret?0:-1;
450
451 sleeping = false;
452 mutex_unlock(&ata_mtx);
453 return ret;
454}
455#endif
456
402static int master_slave_detect(void) 457static int master_slave_detect(void)
403{ 458{
404 /* master? */ 459 /* master? */