summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2006-11-08 01:55:26 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2006-11-08 01:55:26 +0000
commitf184152c0501a80e95ad871927d766fdee50281b (patch)
treeecfa4b6cdf24065b32467d6d7274a2659c3ec9b0 /firmware
parent5dd07759248fec1407f6b3d4d1fb177554e45a13 (diff)
downloadrockbox-f184152c0501a80e95ad871927d766fdee50281b.tar.gz
rockbox-f184152c0501a80e95ad871927d766fdee50281b.zip
* changes to ata.c - idle callbacks are called after 2 sec of real idle,
and shutdown and usb (it makes sense here). ata_sleep doesnt get broken by callbacks. * allow ata_sleep() at the end of buffering again * config block uses ata_idle instead of delayed sector when saving * remove delayed sector code from ata_mmc.c (idle callbacks are not yet implemented for ata_mmc.c tho) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11461 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/ata_idle_notify.c16
-rw-r--r--firmware/drivers/ata.c65
-rw-r--r--firmware/drivers/ata_mmc.c31
-rw-r--r--firmware/export/ata.h2
-rw-r--r--firmware/export/ata_idle_notify.h24
-rw-r--r--firmware/powermgmt.c1
6 files changed, 48 insertions, 91 deletions
diff --git a/firmware/ata_idle_notify.c b/firmware/ata_idle_notify.c
index a0a56e958b..c51c3800ce 100644
--- a/firmware/ata_idle_notify.c
+++ b/firmware/ata_idle_notify.c
@@ -18,8 +18,10 @@
****************************************************************************/
#include <stdbool.h>
#include "system.h"
+#include "ata.h"
#include "ata_idle_notify.h"
#include "logf.h"
+#include "string.h"
#if USING_ATA_CALLBACK
static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS];
@@ -52,7 +54,7 @@ bool register_ata_idle_func(ata_idle_notify function)
}
#if USING_ATA_CALLBACK
-void unregister_ata_idle_func(ata_idle_notify func)
+void unregister_ata_idle_func(ata_idle_notify func, bool run)
{
int i;
for (i=0; i<MAX_ATA_CALLBACKS; i++)
@@ -61,12 +63,13 @@ void unregister_ata_idle_func(ata_idle_notify func)
{
ata_idle_notify_funcs[i] = NULL;
ata_callback_count--;
+ if (run) func();
}
}
return;
}
-bool call_ata_idle_notifys(void)
+bool call_ata_idle_notifys(bool sleep_after)
{
int i;
ata_idle_notify function;
@@ -82,15 +85,14 @@ bool call_ata_idle_notifys(void)
function();
}
}
+ if (sleep_after)
+ ata_sleep();
return true;
}
void ata_idle_notify_init(void)
{
- int i;
- for (i=0; i<MAX_ATA_CALLBACKS; i++)
- {
- ata_idle_notify_funcs[i] = NULL;
- }
+ ata_callback_count = 0;
+ memset(ata_idle_notify_funcs, 0, sizeof(ata_idle_notify_funcs));
}
#endif
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 0a03fd2a25..9e20bfb87d 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -239,9 +239,6 @@ static long ata_stack[DEFAULT_STACK_SIZE/sizeof(long)];
static const char ata_thread_name[] = "ata";
static struct event_queue ata_queue;
static bool initialized = false;
-static bool delayed_write = false;
-static unsigned char delayed_sector[SECTOR_SIZE];
-static int delayed_sector_num;
static long last_user_activity = -1;
long last_disk_activity = -1;
@@ -804,10 +801,6 @@ int ata_read_sectors(IF_MV2(int drive,)
mutex_unlock(&ata_mtx);
- /* only flush if reading went ok */
- if ( (ret == 0) && delayed_write )
- ata_flush();
-
return ret;
}
@@ -1229,34 +1222,9 @@ int ata_write_sectors(IF_MV2(int drive,)
mutex_unlock(&ata_mtx);
- /* only flush if writing went ok */
- if ( (ret == 0) && delayed_write )
- ata_flush();
-
return ret;
}
-/* schedule a single sector write, executed with the the next spinup
- (volume 0 only, used for config sector) */
-extern void ata_delayed_write(unsigned long sector, const void* buf)
-{
- memcpy(delayed_sector, buf, SECTOR_SIZE);
- delayed_sector_num = sector;
- delayed_write = true;
-}
-
-/* write the delayed sector to volume 0 */
-extern void ata_flush(void)
-{
- if ( delayed_write ) {
- DEBUGF("ata_flush()\n");
- delayed_write = false;
- ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector);
- }
-}
-
-
-
static int check_registers(void)
{
#if (CONFIG_CPU == PP5002)
@@ -1364,28 +1332,31 @@ static void ata_thread(void)
{
static long last_sleep = 0;
struct event ev;
- static long last_callback_run = 0;
+ static long last_seen_mtx_unlock = 0;
while (1) {
while ( queue_empty( &ata_queue ) ) {
if (!spinup && !sleeping)
{
+ if (!ata_mtx.locked)
+ {
+ if (!last_seen_mtx_unlock)
+ last_seen_mtx_unlock = current_tick;
+ if (TIME_AFTER(current_tick, last_seen_mtx_unlock+(HZ*2)))
+ {
+ call_ata_idle_notifys(false);
+ last_seen_mtx_unlock = 0;
+ }
+ }
if ( sleep_timeout &&
TIME_AFTER( current_tick,
last_user_activity + sleep_timeout ) &&
TIME_AFTER( current_tick,
last_disk_activity + sleep_timeout ) )
{
- if (!call_ata_idle_notifys())
- {
- ata_perform_sleep();
- last_sleep = current_tick;
- }
- }
- else if (TIME_AFTER(current_tick, last_callback_run+(HZ*5)))
- {
- last_callback_run = current_tick;
- call_ata_idle_notifys();
+ call_ata_idle_notifys(false);
+ ata_perform_sleep();
+ last_sleep = current_tick;
}
}
#ifdef HAVE_ATA_POWER_OFF
@@ -1403,8 +1374,10 @@ static void ata_thread(void)
}
queue_wait(&ata_queue, &ev);
switch ( ev.id ) {
-#ifndef USB_NONE
+ case SYS_POWEROFF:
case SYS_USB_CONNECTED:
+ call_ata_idle_notifys(false);
+#ifndef USB_NONE
if (poweroff) {
mutex_lock(&ata_mtx);
ata_led(true);
@@ -1419,11 +1392,13 @@ static void ata_thread(void)
/* Wait until the USB cable is extracted again */
usb_wait_for_disconnect(&ata_queue);
- break;
#endif
+ break;
case Q_SLEEP:
+ call_ata_idle_notifys(true);
last_disk_activity = current_tick - sleep_timeout + (HZ/2);
break;
+
}
}
}
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index 6303ca2851..64a7ba4bfd 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -98,9 +98,6 @@ static bool mmc_monitor_enabled = true;
#endif
static bool initialized = false;
static bool new_mmc_circuit;
-static bool delayed_write = false;
-static unsigned char delayed_sector[SECTOR_SIZE];
-static int delayed_sector_num;
static enum {
MMC_UNKNOWN,
@@ -805,10 +802,6 @@ int ata_read_sectors(IF_MV2(int drive,)
deselect_card();
- /* only flush if reading went ok */
- if ( (rc == 0) && delayed_write )
- ata_flush();
-
return rc;
}
@@ -960,33 +953,9 @@ int ata_write_sectors(IF_MV2(int drive,)
deselect_card();
- /* only flush if writing went ok */
- if ( (rc == 0) && delayed_write )
- ata_flush();
-
return rc;
}
-/* While there is no spinup, the delayed write is still here to avoid
- wearing the flash unnecessarily */
-extern void ata_delayed_write(unsigned long sector, const void* buf)
-{
- memcpy(delayed_sector, buf, SECTOR_SIZE);
- delayed_sector_num = sector;
- delayed_write = true;
-}
-
-/* write the delayed sector to volume 0 */
-extern void ata_flush(void)
-{
- if ( delayed_write )
- {
- DEBUGF("ata_flush()\n");
- delayed_write = false;
- ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector);
- }
-}
-
void ata_spindown(int seconds)
{
(void)seconds;
diff --git a/firmware/export/ata.h b/firmware/export/ata.h
index 83124c6bfa..c2ba974544 100644
--- a/firmware/export/ata.h
+++ b/firmware/export/ata.h
@@ -46,8 +46,6 @@ extern int ata_soft_reset(void);
extern int ata_init(void);
extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
-extern void ata_delayed_write(unsigned long sector, const void* buf);
-extern void ata_flush(void);
extern void ata_spin(void);
#if CONFIG_LED == LED_REAL
extern void ata_set_led_enabled(bool enabled);
diff --git a/firmware/export/ata_idle_notify.h b/firmware/export/ata_idle_notify.h
index f5f2a25fd9..491a612bdd 100644
--- a/firmware/export/ata_idle_notify.h
+++ b/firmware/export/ata_idle_notify.h
@@ -20,22 +20,36 @@
#define __ATACALLBACK_H__
#include <stdbool.h>
+
+#if 0
+ NOTE: ata_idle_nofity usage notes..
+
+ 1) the callbacks are called in the ata thread, not main/your thread.
+ 2) Asyncronous callbacks (like the buffer refill) should be avoided.
+ If you must use an async callback, remember to check ata_is_active() before
+ accessing the disk, and nonot call any functions between that check and the
+ disk access which may cause a yield (lcd_update() does this!)
+ 3) Do not call cany yielding functions in the callback
+ 4) Do not call ata_sleep in the callbacks
+ 5) Dont Panic!
+#endif
+
#define USING_ATA_CALLBACK !defined(SIMULATOR) \
&& !defined(HAVE_FLASH_DISK) \
&& !defined(HAVE_MMC)
-
+
#define MAX_ATA_CALLBACKS 5
typedef bool (*ata_idle_notify)(void);
extern bool register_ata_idle_func(ata_idle_notify function);
#if USING_ATA_CALLBACK
extern void ata_idle_notify_init(void);
-extern void unregister_ata_idle_func(ata_idle_notify function);
-extern bool call_ata_idle_notifys(void);
+extern void unregister_ata_idle_func(ata_idle_notify function, bool run);
+extern bool call_ata_idle_notifys(bool sleep_after);
#else
-#define unregister_ata_idle_func(f)
+#define unregister_ata_idle_func(f,r)
#define call_ata_idle_notifys()
-#define ata_idle_notify_init()
+#define ata_idle_notify_init(s)
#endif
#endif /* __ATACALLBACK_H__ */
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index f258502c2c..2ca176d072 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -1098,7 +1098,6 @@ void shutdown_hw(void)
#ifdef HAVE_LCD_BITMAP
glyph_cache_save();
#endif
- ata_flush();
ata_spindown(1);
while(ata_disk_is_active())
sleep(HZ/10);