diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2006-11-08 01:55:26 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2006-11-08 01:55:26 +0000 |
commit | f184152c0501a80e95ad871927d766fdee50281b (patch) | |
tree | ecfa4b6cdf24065b32467d6d7274a2659c3ec9b0 /firmware | |
parent | 5dd07759248fec1407f6b3d4d1fb177554e45a13 (diff) | |
download | rockbox-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.c | 16 | ||||
-rw-r--r-- | firmware/drivers/ata.c | 65 | ||||
-rw-r--r-- | firmware/drivers/ata_mmc.c | 31 | ||||
-rw-r--r-- | firmware/export/ata.h | 2 | ||||
-rw-r--r-- | firmware/export/ata_idle_notify.h | 24 | ||||
-rw-r--r-- | firmware/powermgmt.c | 1 |
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); |