summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/ata.c95
1 files changed, 48 insertions, 47 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 58349f69a6..8ca3b75adb 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -29,16 +29,6 @@
29#include "power.h" 29#include "power.h"
30#include "string.h" 30#include "string.h"
31 31
32/* Define one of USE_STANDBY, USE_SLEEP or USE_POWEROFF */
33#define USE_SLEEP
34
35/* We can only use power off on the recorder */
36#if !defined(ARCHOS_RECORDER) && defined(USE_POWEROFF)
37#undef USE_POWEROFF
38#define USE_SLEEP
39#endif
40
41
42#define SECTOR_SIZE 512 32#define SECTOR_SIZE 512
43#define ATA_DATA (*((volatile unsigned short*)0x06104100)) 33#define ATA_DATA (*((volatile unsigned short*)0x06104100))
44#define ATA_ERROR (*((volatile unsigned char*)0x06100101)) 34#define ATA_ERROR (*((volatile unsigned char*)0x06100101))
@@ -92,6 +82,10 @@ static volatile unsigned char* ata_control;
92bool old_recorder = false; 82bool old_recorder = false;
93static bool sleeping = false; 83static bool sleeping = false;
94static int sleep_timeout = 5*HZ; 84static int sleep_timeout = 5*HZ;
85static bool poweroff = false;
86#ifdef ARCHOS_RECORDER
87static int poweroff_timeout = 2*HZ;
88#endif
95static char ata_stack[DEFAULT_STACK_SIZE]; 89static char ata_stack[DEFAULT_STACK_SIZE];
96static char ata_thread_name[] = "ata"; 90static char ata_thread_name[] = "ata";
97static struct event_queue ata_queue; 91static struct event_queue ata_queue;
@@ -106,10 +100,7 @@ long last_disk_activity = -1;
106static int multisectors; /* number of supported multisectors */ 100static int multisectors; /* number of supported multisectors */
107static unsigned short identify_info[SECTOR_SIZE]; 101static unsigned short identify_info[SECTOR_SIZE];
108 102
109#ifdef USE_POWEROFF
110static int ata_power_on(void); 103static int ata_power_on(void);
111#endif
112
113static int perform_soft_reset(void); 104static int perform_soft_reset(void);
114 105
115static int wait_for_bsy(void) __attribute__ ((section (".icode"))); 106static int wait_for_bsy(void) __attribute__ ((section (".icode")));
@@ -177,21 +168,23 @@ int ata_read_sectors(unsigned long start,
177 168
178 mutex_lock(&ata_mtx); 169 mutex_lock(&ata_mtx);
179 170
171 led(true);
172
180 if ( sleeping ) { 173 if ( sleeping ) {
181#ifdef USE_POWEROFF 174 if (poweroff) {
182 if (ata_power_on()) { 175 if (ata_power_on()) {
183 mutex_unlock(&ata_mtx); 176 mutex_unlock(&ata_mtx);
184 return -1; 177 return -1;
178 }
185 } 179 }
186#else 180 else {
187#ifdef USE_SLEEP 181 if (perform_soft_reset()) {
188 if (perform_soft_reset()) { 182 mutex_unlock(&ata_mtx);
189 mutex_unlock(&ata_mtx); 183 return -1;
190 return -1; 184 }
191 } 185 }
192#endif
193#endif
194 sleeping = false; 186 sleeping = false;
187 poweroff = false;
195 } 188 }
196 189
197 if (!wait_for_rdy()) 190 if (!wait_for_rdy())
@@ -200,8 +193,6 @@ int ata_read_sectors(unsigned long start,
200 return -2; 193 return -2;
201 } 194 }
202 195
203 led(true);
204
205 timeout = current_tick + READ_TIMEOUT; 196 timeout = current_tick + READ_TIMEOUT;
206 197
207 retry: 198 retry:
@@ -298,20 +289,20 @@ int ata_write_sectors(unsigned long start,
298 mutex_lock(&ata_mtx); 289 mutex_lock(&ata_mtx);
299 290
300 if ( sleeping ) { 291 if ( sleeping ) {
301#ifdef USE_POWEROFF 292 if (poweroff) {
302 if (ata_power_on()) { 293 if (ata_power_on()) {
303 mutex_unlock(&ata_mtx); 294 mutex_unlock(&ata_mtx);
304 return -1; 295 return -1;
296 }
305 } 297 }
306#else 298 else {
307#ifdef USE_SLEEP 299 if (perform_soft_reset()) {
308 if (perform_soft_reset()) { 300 mutex_unlock(&ata_mtx);
309 mutex_unlock(&ata_mtx); 301 return -1;
310 return -1; 302 }
311 } 303 }
312#endif
313#endif
314 sleeping = false; 304 sleeping = false;
305 poweroff = false;
315 } 306 }
316 307
317 if (!wait_for_rdy()) 308 if (!wait_for_rdy())
@@ -437,22 +428,15 @@ static int ata_perform_sleep(void)
437 return -1; 428 return -1;
438 } 429 }
439 430
440#ifdef USE_POWEROFF
441 ide_power_enable(false);
442#else
443 ATA_SELECT = ata_device; 431 ATA_SELECT = ata_device;
444#ifdef USE_SLEEP
445 ATA_COMMAND = CMD_SLEEP; 432 ATA_COMMAND = CMD_SLEEP;
446#else
447 ATA_COMMAND = CMD_STANDBY_IMMEDIATE;
448#endif
449 433
450 if (!wait_for_rdy()) 434 if (!wait_for_rdy())
451 { 435 {
452 DEBUGF("ata_perform_sleep() - CMD failed\n"); 436 DEBUGF("ata_perform_sleep() - CMD failed\n");
453 ret = -2; 437 ret = -2;
454 } 438 }
455#endif 439
456 sleeping = true; 440 sleeping = true;
457 mutex_unlock(&ata_mtx); 441 mutex_unlock(&ata_mtx);
458 return ret; 442 return ret;
@@ -471,6 +455,7 @@ void ata_spin(void)
471 455
472static void ata_thread(void) 456static void ata_thread(void)
473{ 457{
458 static long last_sleep = 0;
474 struct event ev; 459 struct event ev;
475 460
476 while (1) { 461 while (1) {
@@ -481,12 +466,30 @@ static void ata_thread(void)
481 last_user_activity + sleep_timeout ) && 466 last_user_activity + sleep_timeout ) &&
482 TIME_AFTER( current_tick, 467 TIME_AFTER( current_tick,
483 last_disk_activity + sleep_timeout ) ) 468 last_disk_activity + sleep_timeout ) )
469 {
484 ata_perform_sleep(); 470 ata_perform_sleep();
471 last_sleep = current_tick;
472 }
473
474#ifdef ARCHOS_RECORDER
475 if ( sleeping && poweroff_timeout && !poweroff &&
476 TIME_AFTER( current_tick, last_sleep + poweroff_timeout ))
477 {
478 mutex_lock(&ata_mtx);
479 ide_power_enable(false);
480 mutex_unlock(&ata_mtx);
481 poweroff = true;
482 }
483#endif
484
485 sleep(HZ/4); 485 sleep(HZ/4);
486 } 486 }
487 queue_wait(&ata_queue, &ev); 487 queue_wait(&ata_queue, &ev);
488 switch ( ev.id ) { 488 switch ( ev.id ) {
489 case SYS_USB_CONNECTED: 489 case SYS_USB_CONNECTED:
490 if (poweroff)
491 ata_power_on();
492
490 /* Tell the USB thread that we are safe */ 493 /* Tell the USB thread that we are safe */
491 DEBUGF("ata_thread got SYS_USB_CONNECTED\n"); 494 DEBUGF("ata_thread got SYS_USB_CONNECTED\n");
492 usb_acknowledge(SYS_USB_CONNECTED_ACK); 495 usb_acknowledge(SYS_USB_CONNECTED_ACK);
@@ -562,7 +565,6 @@ int ata_soft_reset(void)
562 return ret; 565 return ret;
563} 566}
564 567
565#ifdef USE_POWEROFF
566static int ata_power_on(void) 568static int ata_power_on(void)
567{ 569{
568 int ret; 570 int ret;
@@ -586,7 +588,6 @@ static int ata_power_on(void)
586 sleeping = false; 588 sleeping = false;
587 return ret; 589 return ret;
588} 590}
589#endif
590 591
591static int master_slave_detect(void) 592static int master_slave_detect(void)
592{ 593{