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 | |
| parent | 5dd07759248fec1407f6b3d4d1fb177554e45a13 (diff) | |
| download | rockbox-f184152c0501a80e95ad871927d766fdee50281b.zip rockbox-f184152c0501a80e95ad871927d766fdee50281b.tar.gz rockbox-f184152c0501a80e95ad871927d766fdee50281b.tar.bz2 rockbox-f184152c0501a80e95ad871927d766fdee50281b.tar.xz | |
* 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
| -rw-r--r-- | apps/playback.c | 1 | ||||
| -rw-r--r-- | apps/settings.c | 8 | ||||
| -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 |
8 files changed, 56 insertions, 92 deletions
diff --git a/apps/playback.c b/apps/playback.c index f4274a8..c0558ed 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -2781,6 +2781,7 @@ static void audio_fill_file_buffer( filling = false; } + ata_sleep(); } static void audio_rebuffer(void) diff --git a/apps/settings.c b/apps/settings.c index ec96cc7..08e6376 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -38,6 +38,7 @@ #include "talk.h" #include "string.h" #include "ata.h" +#include "ata_idle_notify.h" #include "fat.h" #include "power.h" #include "powermgmt.h" @@ -802,6 +803,11 @@ static void init_config_buffer( void ) config_block[3] = CONFIG_BLOCK_VERSION; } +bool flush_config_block_callback(void) +{ + ata_write_sectors(IF_MV2(0,) config_sector, 1, config_block); + return true; +} /* * save the config block buffer to disk or RTC RAM */ @@ -833,7 +839,7 @@ static int save_config_buffer( void ) #endif if (config_sector != 0) - ata_delayed_write( config_sector, config_block); + register_ata_idle_func(flush_config_block_callback); else return -1; diff --git a/firmware/ata_idle_notify.c b/firmware/ata_idle_notify.c index a0a56e9..c51c380 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 0a03fd2..9e20bfb 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 6303ca2..64a7ba4 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 83124c6..c2ba974 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 f5f2a25..491a612 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 f258502..2ca176d 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); |