summaryrefslogtreecommitdiff
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
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
-rw-r--r--apps/playback.c1
-rw-r--r--apps/settings.c8
-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
8 files changed, 56 insertions, 92 deletions
diff --git a/apps/playback.c b/apps/playback.c
index f4274a8f02..c0558ed737 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -2781,6 +2781,7 @@ static void audio_fill_file_buffer(
2781 filling = false; 2781 filling = false;
2782 } 2782 }
2783 2783
2784 ata_sleep();
2784} 2785}
2785 2786
2786static void audio_rebuffer(void) 2787static void audio_rebuffer(void)
diff --git a/apps/settings.c b/apps/settings.c
index ec96cc760b..08e6376694 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -38,6 +38,7 @@
38#include "talk.h" 38#include "talk.h"
39#include "string.h" 39#include "string.h"
40#include "ata.h" 40#include "ata.h"
41#include "ata_idle_notify.h"
41#include "fat.h" 42#include "fat.h"
42#include "power.h" 43#include "power.h"
43#include "powermgmt.h" 44#include "powermgmt.h"
@@ -802,6 +803,11 @@ static void init_config_buffer( void )
802 config_block[3] = CONFIG_BLOCK_VERSION; 803 config_block[3] = CONFIG_BLOCK_VERSION;
803} 804}
804 805
806bool flush_config_block_callback(void)
807{
808 ata_write_sectors(IF_MV2(0,) config_sector, 1, config_block);
809 return true;
810}
805/* 811/*
806 * save the config block buffer to disk or RTC RAM 812 * save the config block buffer to disk or RTC RAM
807 */ 813 */
@@ -833,7 +839,7 @@ static int save_config_buffer( void )
833#endif 839#endif
834 840
835 if (config_sector != 0) 841 if (config_sector != 0)
836 ata_delayed_write( config_sector, config_block); 842 register_ata_idle_func(flush_config_block_callback);
837 else 843 else
838 return -1; 844 return -1;
839 845
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 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19#include <stdbool.h> 19#include <stdbool.h>
20#include "system.h" 20#include "system.h"
21#include "ata.h"
21#include "ata_idle_notify.h" 22#include "ata_idle_notify.h"
22#include "logf.h" 23#include "logf.h"
24#include "string.h"
23 25
24#if USING_ATA_CALLBACK 26#if USING_ATA_CALLBACK
25static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS]; 27static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS];
@@ -52,7 +54,7 @@ bool register_ata_idle_func(ata_idle_notify function)
52} 54}
53 55
54#if USING_ATA_CALLBACK 56#if USING_ATA_CALLBACK
55void unregister_ata_idle_func(ata_idle_notify func) 57void unregister_ata_idle_func(ata_idle_notify func, bool run)
56{ 58{
57 int i; 59 int i;
58 for (i=0; i<MAX_ATA_CALLBACKS; i++) 60 for (i=0; i<MAX_ATA_CALLBACKS; i++)
@@ -61,12 +63,13 @@ void unregister_ata_idle_func(ata_idle_notify func)
61 { 63 {
62 ata_idle_notify_funcs[i] = NULL; 64 ata_idle_notify_funcs[i] = NULL;
63 ata_callback_count--; 65 ata_callback_count--;
66 if (run) func();
64 } 67 }
65 } 68 }
66 return; 69 return;
67} 70}
68 71
69bool call_ata_idle_notifys(void) 72bool call_ata_idle_notifys(bool sleep_after)
70{ 73{
71 int i; 74 int i;
72 ata_idle_notify function; 75 ata_idle_notify function;
@@ -82,15 +85,14 @@ bool call_ata_idle_notifys(void)
82 function(); 85 function();
83 } 86 }
84 } 87 }
88 if (sleep_after)
89 ata_sleep();
85 return true; 90 return true;
86} 91}
87 92
88void ata_idle_notify_init(void) 93void ata_idle_notify_init(void)
89{ 94{
90 int i; 95 ata_callback_count = 0;
91 for (i=0; i<MAX_ATA_CALLBACKS; i++) 96 memset(ata_idle_notify_funcs, 0, sizeof(ata_idle_notify_funcs));
92 {
93 ata_idle_notify_funcs[i] = NULL;
94 }
95} 97}
96#endif 98#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)];
239static const char ata_thread_name[] = "ata"; 239static const char ata_thread_name[] = "ata";
240static struct event_queue ata_queue; 240static struct event_queue ata_queue;
241static bool initialized = false; 241static bool initialized = false;
242static bool delayed_write = false;
243static unsigned char delayed_sector[SECTOR_SIZE];
244static int delayed_sector_num;
245 242
246static long last_user_activity = -1; 243static long last_user_activity = -1;
247long last_disk_activity = -1; 244long last_disk_activity = -1;
@@ -804,10 +801,6 @@ int ata_read_sectors(IF_MV2(int drive,)
804 801
805 mutex_unlock(&ata_mtx); 802 mutex_unlock(&ata_mtx);
806 803
807 /* only flush if reading went ok */
808 if ( (ret == 0) && delayed_write )
809 ata_flush();
810
811 return ret; 804 return ret;
812} 805}
813 806
@@ -1229,34 +1222,9 @@ int ata_write_sectors(IF_MV2(int drive,)
1229 1222
1230 mutex_unlock(&ata_mtx); 1223 mutex_unlock(&ata_mtx);
1231 1224
1232 /* only flush if writing went ok */
1233 if ( (ret == 0) && delayed_write )
1234 ata_flush();
1235
1236 return ret; 1225 return ret;
1237} 1226}
1238 1227
1239/* schedule a single sector write, executed with the the next spinup
1240 (volume 0 only, used for config sector) */
1241extern void ata_delayed_write(unsigned long sector, const void* buf)
1242{
1243 memcpy(delayed_sector, buf, SECTOR_SIZE);
1244 delayed_sector_num = sector;
1245 delayed_write = true;
1246}
1247
1248/* write the delayed sector to volume 0 */
1249extern void ata_flush(void)
1250{
1251 if ( delayed_write ) {
1252 DEBUGF("ata_flush()\n");
1253 delayed_write = false;
1254 ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector);
1255 }
1256}
1257
1258
1259
1260static int check_registers(void) 1228static int check_registers(void)
1261{ 1229{
1262#if (CONFIG_CPU == PP5002) 1230#if (CONFIG_CPU == PP5002)
@@ -1364,28 +1332,31 @@ static void ata_thread(void)
1364{ 1332{
1365 static long last_sleep = 0; 1333 static long last_sleep = 0;
1366 struct event ev; 1334 struct event ev;
1367 static long last_callback_run = 0; 1335 static long last_seen_mtx_unlock = 0;
1368 1336
1369 while (1) { 1337 while (1) {
1370 while ( queue_empty( &ata_queue ) ) { 1338 while ( queue_empty( &ata_queue ) ) {
1371 if (!spinup && !sleeping) 1339 if (!spinup && !sleeping)
1372 { 1340 {
1341 if (!ata_mtx.locked)
1342 {
1343 if (!last_seen_mtx_unlock)
1344 last_seen_mtx_unlock = current_tick;
1345 if (TIME_AFTER(current_tick, last_seen_mtx_unlock+(HZ*2)))
1346 {
1347 call_ata_idle_notifys(false);
1348 last_seen_mtx_unlock = 0;
1349 }
1350 }
1373 if ( sleep_timeout && 1351 if ( sleep_timeout &&
1374 TIME_AFTER( current_tick, 1352 TIME_AFTER( current_tick,
1375 last_user_activity + sleep_timeout ) && 1353 last_user_activity + sleep_timeout ) &&
1376 TIME_AFTER( current_tick, 1354 TIME_AFTER( current_tick,
1377 last_disk_activity + sleep_timeout ) ) 1355 last_disk_activity + sleep_timeout ) )
1378 { 1356 {
1379 if (!call_ata_idle_notifys()) 1357 call_ata_idle_notifys(false);
1380 { 1358 ata_perform_sleep();
1381 ata_perform_sleep(); 1359 last_sleep = current_tick;
1382 last_sleep = current_tick;
1383 }
1384 }
1385 else if (TIME_AFTER(current_tick, last_callback_run+(HZ*5)))
1386 {
1387 last_callback_run = current_tick;
1388 call_ata_idle_notifys();
1389 } 1360 }
1390 } 1361 }
1391#ifdef HAVE_ATA_POWER_OFF 1362#ifdef HAVE_ATA_POWER_OFF
@@ -1403,8 +1374,10 @@ static void ata_thread(void)
1403 } 1374 }
1404 queue_wait(&ata_queue, &ev); 1375 queue_wait(&ata_queue, &ev);
1405 switch ( ev.id ) { 1376 switch ( ev.id ) {
1406#ifndef USB_NONE 1377 case SYS_POWEROFF:
1407 case SYS_USB_CONNECTED: 1378 case SYS_USB_CONNECTED:
1379 call_ata_idle_notifys(false);
1380#ifndef USB_NONE
1408 if (poweroff) { 1381 if (poweroff) {
1409 mutex_lock(&ata_mtx); 1382 mutex_lock(&ata_mtx);
1410 ata_led(true); 1383 ata_led(true);
@@ -1419,11 +1392,13 @@ static void ata_thread(void)
1419 1392
1420 /* Wait until the USB cable is extracted again */ 1393 /* Wait until the USB cable is extracted again */
1421 usb_wait_for_disconnect(&ata_queue); 1394 usb_wait_for_disconnect(&ata_queue);
1422 break;
1423#endif 1395#endif
1396 break;
1424 case Q_SLEEP: 1397 case Q_SLEEP:
1398 call_ata_idle_notifys(true);
1425 last_disk_activity = current_tick - sleep_timeout + (HZ/2); 1399 last_disk_activity = current_tick - sleep_timeout + (HZ/2);
1426 break; 1400 break;
1401
1427 } 1402 }
1428 } 1403 }
1429} 1404}
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;
98#endif 98#endif
99static bool initialized = false; 99static bool initialized = false;
100static bool new_mmc_circuit; 100static bool new_mmc_circuit;
101static bool delayed_write = false;
102static unsigned char delayed_sector[SECTOR_SIZE];
103static int delayed_sector_num;
104 101
105static enum { 102static enum {
106 MMC_UNKNOWN, 103 MMC_UNKNOWN,
@@ -805,10 +802,6 @@ int ata_read_sectors(IF_MV2(int drive,)
805 802
806 deselect_card(); 803 deselect_card();
807 804
808 /* only flush if reading went ok */
809 if ( (rc == 0) && delayed_write )
810 ata_flush();
811
812 return rc; 805 return rc;
813} 806}
814 807
@@ -960,33 +953,9 @@ int ata_write_sectors(IF_MV2(int drive,)
960 953
961 deselect_card(); 954 deselect_card();
962 955
963 /* only flush if writing went ok */
964 if ( (rc == 0) && delayed_write )
965 ata_flush();
966
967 return rc; 956 return rc;
968} 957}
969 958
970/* While there is no spinup, the delayed write is still here to avoid
971 wearing the flash unnecessarily */
972extern void ata_delayed_write(unsigned long sector, const void* buf)
973{
974 memcpy(delayed_sector, buf, SECTOR_SIZE);
975 delayed_sector_num = sector;
976 delayed_write = true;
977}
978
979/* write the delayed sector to volume 0 */
980extern void ata_flush(void)
981{
982 if ( delayed_write )
983 {
984 DEBUGF("ata_flush()\n");
985 delayed_write = false;
986 ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector);
987 }
988}
989
990void ata_spindown(int seconds) 959void ata_spindown(int seconds)
991{ 960{
992 (void)seconds; 961 (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);
46extern int ata_init(void); 46extern int ata_init(void);
47extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); 47extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
48extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); 48extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
49extern void ata_delayed_write(unsigned long sector, const void* buf);
50extern void ata_flush(void);
51extern void ata_spin(void); 49extern void ata_spin(void);
52#if CONFIG_LED == LED_REAL 50#if CONFIG_LED == LED_REAL
53extern void ata_set_led_enabled(bool enabled); 51extern 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 @@
20#define __ATACALLBACK_H__ 20#define __ATACALLBACK_H__
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23
24#if 0
25 NOTE: ata_idle_nofity usage notes..
26
27 1) the callbacks are called in the ata thread, not main/your thread.
28 2) Asyncronous callbacks (like the buffer refill) should be avoided.
29 If you must use an async callback, remember to check ata_is_active() before
30 accessing the disk, and nonot call any functions between that check and the
31 disk access which may cause a yield (lcd_update() does this!)
32 3) Do not call cany yielding functions in the callback
33 4) Do not call ata_sleep in the callbacks
34 5) Dont Panic!
35#endif
36
23#define USING_ATA_CALLBACK !defined(SIMULATOR) \ 37#define USING_ATA_CALLBACK !defined(SIMULATOR) \
24 && !defined(HAVE_FLASH_DISK) \ 38 && !defined(HAVE_FLASH_DISK) \
25 && !defined(HAVE_MMC) 39 && !defined(HAVE_MMC)
26 40
27#define MAX_ATA_CALLBACKS 5 41#define MAX_ATA_CALLBACKS 5
28typedef bool (*ata_idle_notify)(void); 42typedef bool (*ata_idle_notify)(void);
29 43
30extern bool register_ata_idle_func(ata_idle_notify function); 44extern bool register_ata_idle_func(ata_idle_notify function);
31#if USING_ATA_CALLBACK 45#if USING_ATA_CALLBACK
32extern void ata_idle_notify_init(void); 46extern void ata_idle_notify_init(void);
33extern void unregister_ata_idle_func(ata_idle_notify function); 47extern void unregister_ata_idle_func(ata_idle_notify function, bool run);
34extern bool call_ata_idle_notifys(void); 48extern bool call_ata_idle_notifys(bool sleep_after);
35#else 49#else
36#define unregister_ata_idle_func(f) 50#define unregister_ata_idle_func(f,r)
37#define call_ata_idle_notifys() 51#define call_ata_idle_notifys()
38#define ata_idle_notify_init() 52#define ata_idle_notify_init(s)
39#endif 53#endif
40 54
41#endif /* __ATACALLBACK_H__ */ 55#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)
1098#ifdef HAVE_LCD_BITMAP 1098#ifdef HAVE_LCD_BITMAP
1099 glyph_cache_save(); 1099 glyph_cache_save();
1100#endif 1100#endif
1101 ata_flush();
1102 ata_spindown(1); 1101 ata_spindown(1);
1103 while(ata_disk_is_active()) 1102 while(ata_disk_is_active())
1104 sleep(HZ/10); 1103 sleep(HZ/10);