* 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
This commit is contained in:
parent
5dd0775924
commit
f184152c05
8 changed files with 56 additions and 92 deletions
|
@ -2781,6 +2781,7 @@ static void audio_fill_file_buffer(
|
|||
filling = false;
|
||||
}
|
||||
|
||||
ata_sleep();
|
||||
}
|
||||
|
||||
static void audio_rebuffer(void)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,30 +1332,33 @@ 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())
|
||||
{
|
||||
call_ata_idle_notifys(false);
|
||||
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();
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_ATA_POWER_OFF
|
||||
if ( !spinup && sleeping && poweroff_timeout && !poweroff &&
|
||||
TIME_AFTER( current_tick, last_sleep + poweroff_timeout ))
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -20,6 +20,20 @@
|
|||
#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)
|
||||
|
@ -30,12 +44,12 @@ 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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue