From 11968a429a36e9981b9cc30fcd8af8e9a6e77d2b Mon Sep 17 00:00:00 2001 From: Björn Stenberg Date: Tue, 16 Jul 2002 14:07:47 +0000 Subject: Removed use of internal harddisk standby timer and instead added software sleep timer. This gives lower power use and slightly faster boot, plus a more fine-grained timeout setting (1s steps instead of 5s). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1372 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/ata.c | 95 ++++++++++++++++++++++++++++++++------------------ firmware/drivers/ata.h | 2 +- 2 files changed, 63 insertions(+), 34 deletions(-) (limited to 'firmware') diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 963929deb7..3fdc93669e 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c @@ -19,11 +19,13 @@ #include #include "ata.h" #include "kernel.h" +#include "thread.h" #include "led.h" #include "sh7034.h" #include "system.h" #include "debug.h" #include "panic.h" +#include "usb.h" #define SECTOR_SIZE 512 #define ATA_DATA (*((volatile unsigned short*)0x06104100)) @@ -61,6 +63,8 @@ #define CMD_SLEEP 0xE6 #define CMD_SECURITY_FREEZE_LOCK 0xF5 +#define Q_SLEEP 0 + static struct mutex ata_mtx; char ata_device; /* device 0 (master) or 1 (slave) */ int ata_io_address; /* 0x300 or 0x200, only valid on recorder */ @@ -68,6 +72,12 @@ static volatile unsigned char* ata_control; bool old_recorder = false; static bool sleeping = false; +static int sleep_timer = 0; +static int sleep_timeout = 5*HZ; +static char ata_stack[DEFAULT_STACK_SIZE]; +static char ata_thread_name[] = "ata"; +static struct event_queue ata_queue; +static bool initialized = false; static int wait_for_bsy(void) { @@ -121,7 +131,8 @@ int ata_read_sectors(unsigned long start, } mutex_lock(&ata_mtx); - + sleep_timer = sleep_timeout; + if (!wait_for_rdy()) { mutex_unlock(&ata_mtx); @@ -179,6 +190,7 @@ int ata_write_sectors(unsigned long start, } mutex_lock(&ata_mtx); + sleep_timer = sleep_timeout; if (!wait_for_rdy()) { @@ -254,58 +266,70 @@ static int freeze_lock(void) return 0; } -int ata_spindown(int time) +void ata_spindown(int seconds) +{ + sleep_timeout = seconds * HZ; +} + +static int ata_perform_sleep(void) { int ret = 0; mutex_lock(&ata_mtx); - if(!wait_for_rdy()) - { + if(!wait_for_rdy()) { mutex_unlock(&ata_mtx); return -1; } - if ( time == -1 ) { - ATA_COMMAND = CMD_STANDBY_IMMEDIATE; - } - else { - if (time > 255) - { - mutex_unlock(&ata_mtx); - return -1; - } - ATA_NSECTOR = time & 0xff; - ATA_COMMAND = CMD_STANDBY; - } + ATA_SELECT = ata_device; + ATA_COMMAND = CMD_SLEEP; if (!wait_for_rdy()) ret = -1; + sleeping = true; + sleep_timer = 0; mutex_unlock(&ata_mtx); return ret; } int ata_sleep(void) { - int ret = 0; + queue_post(&ata_queue, Q_SLEEP, NULL); + return 0; +} - mutex_lock(&ata_mtx); +static void ata_thread(void) +{ + struct event ev; - if(!wait_for_rdy()) { - mutex_unlock(&ata_mtx); - return -1; + while (1) { + queue_wait(&ata_queue, &ev); + switch ( ev.id ) { + case SYS_USB_CONNECTED: + /* Tell the USB thread that we are safe */ + DEBUGF("backlight_thread got SYS_USB_CONNECTED\n"); + usb_acknowledge(SYS_USB_CONNECTED_ACK); + + /* Wait until the USB cable is extracted again */ + usb_wait_for_disconnect(&ata_queue); + break; + + case Q_SLEEP: + ata_perform_sleep(); + break; + } } +} - ATA_SELECT = ata_device; - ATA_COMMAND = CMD_SLEEP; - - if (!wait_for_rdy()) - ret = -1; - - sleeping = true; - mutex_unlock(&ata_mtx); - return ret; +static void ata_tick(void) +{ + if (sleep_timer) { + sleep_timer--; + if (!sleep_timer) + queue_post(&ata_queue, 0, NULL); + } } int ata_hard_reset(void) @@ -433,7 +457,7 @@ void ata_enable(bool on) int ata_init(void) { mutex_init(&ata_mtx); - + led(false); ata_enable(true); @@ -450,8 +474,13 @@ int ata_init(void) if (freeze_lock()) return -4; - if (ata_spindown(1)) - return -5; + if ( !initialized ) { + queue_init(&ata_queue); + create_thread(ata_thread, ata_stack, + sizeof(ata_stack), ata_thread_name); + tick_add_task(ata_tick); + initialized = true; + } ATA_SELECT = SELECT_LBA; ATA_CONTROL = CONTROL_nIEN; diff --git a/firmware/drivers/ata.h b/firmware/drivers/ata.h index 23dd1fac58..77c4c2b7bf 100644 --- a/firmware/drivers/ata.h +++ b/firmware/drivers/ata.h @@ -33,7 +33,7 @@ 255 21 min 15 s */ extern void ata_enable(bool on); -extern int ata_spindown(int time); +extern void ata_spindown(int seconds); extern int ata_sleep(void); extern int ata_hard_reset(void); extern int ata_soft_reset(void); -- cgit v1.2.3