diff options
-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 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 | ||
2786 | static void audio_rebuffer(void) | 2787 | static 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 | ||
806 | bool 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 |
25 | static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS]; | 27 | static 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 |
55 | void unregister_ata_idle_func(ata_idle_notify func) | 57 | void 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 | ||
69 | bool call_ata_idle_notifys(void) | 72 | bool 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 | ||
88 | void ata_idle_notify_init(void) | 93 | void 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)]; | |||
239 | static const char ata_thread_name[] = "ata"; | 239 | static const char ata_thread_name[] = "ata"; |
240 | static struct event_queue ata_queue; | 240 | static struct event_queue ata_queue; |
241 | static bool initialized = false; | 241 | static bool initialized = false; |
242 | static bool delayed_write = false; | ||
243 | static unsigned char delayed_sector[SECTOR_SIZE]; | ||
244 | static int delayed_sector_num; | ||
245 | 242 | ||
246 | static long last_user_activity = -1; | 243 | static long last_user_activity = -1; |
247 | long last_disk_activity = -1; | 244 | long 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) */ | ||
1241 | extern 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 */ | ||
1249 | extern 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 | |||
1260 | static int check_registers(void) | 1228 | static 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 |
99 | static bool initialized = false; | 99 | static bool initialized = false; |
100 | static bool new_mmc_circuit; | 100 | static bool new_mmc_circuit; |
101 | static bool delayed_write = false; | ||
102 | static unsigned char delayed_sector[SECTOR_SIZE]; | ||
103 | static int delayed_sector_num; | ||
104 | 101 | ||
105 | static enum { | 102 | static 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 */ | ||
972 | extern 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 */ | ||
980 | extern 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 | |||
990 | void ata_spindown(int seconds) | 959 | void 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); | |||
46 | extern int ata_init(void); | 46 | extern int ata_init(void); |
47 | extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); | 47 | extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); |
48 | extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); | 48 | extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); |
49 | extern void ata_delayed_write(unsigned long sector, const void* buf); | ||
50 | extern void ata_flush(void); | ||
51 | extern void ata_spin(void); | 49 | extern void ata_spin(void); |
52 | #if CONFIG_LED == LED_REAL | 50 | #if CONFIG_LED == LED_REAL |
53 | extern void ata_set_led_enabled(bool enabled); | 51 | 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 @@ | |||
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 |
28 | typedef bool (*ata_idle_notify)(void); | 42 | typedef bool (*ata_idle_notify)(void); |
29 | 43 | ||
30 | extern bool register_ata_idle_func(ata_idle_notify function); | 44 | extern bool register_ata_idle_func(ata_idle_notify function); |
31 | #if USING_ATA_CALLBACK | 45 | #if USING_ATA_CALLBACK |
32 | extern void ata_idle_notify_init(void); | 46 | extern void ata_idle_notify_init(void); |
33 | extern void unregister_ata_idle_func(ata_idle_notify function); | 47 | extern void unregister_ata_idle_func(ata_idle_notify function, bool run); |
34 | extern bool call_ata_idle_notifys(void); | 48 | extern 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); |