* 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:
Jonathan Gordon 2006-11-08 01:55:26 +00:00
parent 5dd0775924
commit f184152c05
8 changed files with 56 additions and 92 deletions

View file

@ -2781,6 +2781,7 @@ static void audio_fill_file_buffer(
filling = false;
}
ata_sleep();
}
static void audio_rebuffer(void)

View file

@ -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;

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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__ */

View file

@ -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);