summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-07-16 14:07:47 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-07-16 14:07:47 +0000
commit11968a429a36e9981b9cc30fcd8af8e9a6e77d2b (patch)
tree6788b1184242d2fcc02e92af1197b80a9268a460
parentaba3d78801f923b72fb9aa6d348e9d6bc449823c (diff)
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
-rw-r--r--firmware/drivers/ata.c95
-rw-r--r--firmware/drivers/ata.h2
2 files changed, 63 insertions, 34 deletions
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 <stdbool.h>
#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);