| Index: emcore/trunk/target/ipodclassic/storage_ata.c |
| — | — | @@ -109,6 +109,16 @@ |
| 110 | 110 | ata_error_srst = enable; |
| 111 | 111 | } |
| 112 | 112 | |
| | 113 | +int ata_lock_exclusive(int timeout) |
| | 114 | +{ |
| | 115 | + return mutex_lock(&ata_mutex, timeout); |
| | 116 | +} |
| | 117 | + |
| | 118 | +void ata_unlock_exclusive() |
| | 119 | +{ |
| | 120 | + mutex_unlock(&ata_mutex); |
| | 121 | +} |
| | 122 | + |
| 113 | 123 | static uint16_t ata_read_cbr(uint32_t volatile* reg) |
| 114 | 124 | { |
| 115 | 125 | while (!(ATA_PIO_READY & 2)) yield(); |
| — | — | @@ -1323,7 +1333,10 @@ |
| 1324 | 1334 | |
| 1325 | 1335 | int ata_init(void) |
| 1326 | 1336 | { |
| 1327 | | - mutex_init(&ata_mutex); |
| | 1337 | + // Remove this, as it isn't strictly required and causes a race condition. |
| | 1338 | + // The clickwheel dispatcher can run ata_lock_exclusive before ata_init is run. |
| | 1339 | + // BSS is initialized to zeroes, which are interpreted as an unlocked mutex anyway. |
| | 1340 | + //mutex_init(&ata_mutex); |
| 1328 | 1341 | wakeup_init(&ata_wakeup); |
| 1329 | 1342 | wakeup_init(&mmc_wakeup); |
| 1330 | 1343 | wakeup_init(&mmc_comp_wakeup); |
| Index: emcore/trunk/target/ipodclassic/storage_ata-target.h |
| — | — | @@ -68,6 +68,8 @@ |
| 69 | 69 |
|
| 70 | 70 | extern void ata_set_retries(int retries);
|
| 71 | 71 | extern void ata_srst_after_error(bool enable);
|
| | 72 | +extern int ata_lock_exclusive(int timeout);
|
| | 73 | +extern void ata_unlock_exclusive();
|
| 72 | 74 | extern int ata_soft_reset();
|
| 73 | 75 | extern int ata_hard_reset();
|
| 74 | 76 | extern int ata_read_taskfile(struct ata_raw_cmd_t* cmd);
|
| Index: emcore/trunk/target/ipodnano2g/clickwheel.c |
| — | — | @@ -31,13 +31,15 @@ |
| 32 | 32 |
|
| 33 | 33 |
|
| 34 | 34 | static struct wakeup clickwheel_wakeup IBSS_ATTR;
|
| | 35 | +static struct wakeup clickwheel_init_wakeup INITDATA_ATTR;
|
| 35 | 36 | static volatile uint32_t clickwheel_packet IBSS_ATTR;
|
| 36 | 37 | static struct scheduler_thread clickwheel_thread_handle;
|
| 37 | 38 | static uint32_t clickwheel_stack[0x100] STACK_ATTR;
|
| | 39 | +static bool wheel_initialized IBSS_ATTR;
|
| 38 | 40 | static bool oldtouched IBSS_ATTR;
|
| 39 | 41 | static int oldpos IBSS_ATTR;
|
| 40 | 42 | static int oldbuttons IBSS_ATTR;
|
| 41 | | -static uint32_t lastpacket IBSS_ATTR;
|
| | 43 | +static int lastpacket IBSS_ATTR;
|
| 42 | 44 | static int packets IBSS_ATTR;
|
| 43 | 45 | static int collect IBSS_ATTR;
|
| 44 | 46 | static int lastdiff IBSS_ATTR;
|
| — | — | @@ -124,14 +126,21 @@ |
| 125 | 127 | {
|
| 126 | 128 | if (data & 0x1F0000) oldbuttons = (data >> 16) & 0x1F;
|
| 127 | 129 | DEBUGF("This is an init packet, button state: %02X", oldbuttons);
|
| | 130 | + if (!wheel_initialized)
|
| | 131 | + {
|
| | 132 | + wheel_initialized = true;
|
| | 133 | + wakeup_signal(&clickwheel_init_wakeup);
|
| | 134 | + }
|
| 128 | 135 | }
|
| 129 | 136 | }
|
| 130 | 137 | }
|
| 131 | 138 |
|
| 132 | 139 |
|
| 133 | | -void clickwheel_init()
|
| | 140 | +int clickwheel_init()
|
| 134 | 141 | {
|
| 135 | 142 | wakeup_init(&clickwheel_wakeup);
|
| | 143 | + wakeup_init(&clickwheel_init_wakeup);
|
| | 144 | + wheel_initialized = false;
|
| 136 | 145 | oldtouched = false;
|
| 137 | 146 | oldbuttons = 0;
|
| 138 | 147 | lastpacket = 0;
|
| — | — | @@ -154,6 +163,9 @@ |
| 155 | 164 | thread_create(&clickwheel_thread_handle, "Clickwheel dispatcher", clickwheel_thread,
|
| 156 | 165 | clickwheel_stack, sizeof(clickwheel_stack), OS_THREAD, 200, true,
|
| 157 | 166 | NULL, NULL, NULL, NULL);
|
| | 167 | + wakeup_wait(&clickwheel_init_wakeup, 100000);
|
| | 168 | + if (!wheel_initialized) RET_ERR(0);
|
| | 169 | + return 0;
|
| 158 | 170 | }
|
| 159 | 171 |
|
| 160 | 172 | void INT_WHEEL(void) ICODE_ATTR;
|
| Index: emcore/trunk/target/ipodnano3g/targetinit.c |
| — | — | @@ -37,6 +37,18 @@ |
| 38 | 38 | int i;
|
| 39 | 39 |
|
| 40 | 40 | clickwheel_init();
|
| | 41 | + int buttons = clickwheel_get_state() & 0x1f;
|
| | 42 | + if (buttons == 0x11)
|
| | 43 | + {
|
| | 44 | + cputs(CONSOLE_BOOT, "MENU+SELECT is being pressed.\n"
|
| | 45 | + "Continue pressing these buttons to enter DFU mode.\n");
|
| | 46 | + while (buttons == 0x11)
|
| | 47 | + {
|
| | 48 | + sleep(100000);
|
| | 49 | + buttons = clickwheel_get_state() & 0x1f;
|
| | 50 | + }
|
| | 51 | + cputs(CONSOLE_BOOT, "MENU+SELECT was released. Continuing normal boot.\n");
|
| | 52 | + }
|
| 41 | 53 |
|
| 42 | 54 | uint8_t* nor = (uint8_t*)memalign(0x10, 0x1000);
|
| 43 | 55 | uint32_t* norword = (uint32_t*)nor;
|
| Index: emcore/trunk/target/ipodnano3g/clickwheel.c |
| — | — | @@ -28,16 +28,23 @@ |
| 29 | 29 | #include "timer.h"
|
| 30 | 30 | #include "s5l8702.h"
|
| 31 | 31 | #include "contextswitch.h"
|
| | 32 | +#ifdef TARGET_ipodclassic
|
| | 33 | +#include "fat.h"
|
| | 34 | +#include "storage_ata.h"
|
| | 35 | +#include "../ipodclassic/storage_ata-target.h"
|
| | 36 | +#endif
|
| 32 | 37 |
|
| 33 | 38 |
|
| 34 | 39 | static struct wakeup clickwheel_wakeup IBSS_ATTR;
|
| | 40 | +static struct wakeup clickwheel_init_wakeup INITDATA_ATTR;
|
| 35 | 41 | static volatile uint32_t clickwheel_packet IBSS_ATTR;
|
| 36 | 42 | static struct scheduler_thread clickwheel_thread_handle;
|
| 37 | 43 | static uint32_t clickwheel_stack[0x100] STACK_ATTR;
|
| | 44 | +static bool wheel_initialized IBSS_ATTR;
|
| 38 | 45 | static bool oldtouched IBSS_ATTR;
|
| 39 | 46 | static int oldpos IBSS_ATTR;
|
| 40 | 47 | static int oldbuttons IBSS_ATTR;
|
| 41 | | -static uint32_t lastpacket IBSS_ATTR;
|
| | 48 | +static int lastpacket IBSS_ATTR;
|
| 42 | 49 | static int packets IBSS_ATTR;
|
| 43 | 50 | static int collect IBSS_ATTR;
|
| 44 | 51 | static int lastdiff IBSS_ATTR;
|
| — | — | @@ -55,14 +62,15 @@ |
| 56 | 63 | uint32_t data = clickwheel_packet;
|
| 57 | 64 | leave_critical_section(mode);
|
| 58 | 65 | DEBUGF("Acquired clickwheel packet: %08X", data);
|
| | 66 | + int newbuttons = (data >> 8) & 0x1f;
|
| 59 | 67 | if ((data & 0x800000FF) == 0x8000001A)
|
| 60 | 68 | {
|
| 61 | | - int newbuttons = (data >> 8) & 0x1f;
|
| 62 | 69 | int newpos = (data >> 16) & 0xff;
|
| 63 | 70 | bool newtouched = (data & 0x40000000) ? true : false;
|
| 64 | 71 |
|
| 65 | 72 | DEBUGF("This is a change packet, button state: %02X, position: %02d, touched: %d",
|
| 66 | 73 | newbuttons, newpos, newtouched);
|
| | 74 | +
|
| 67 | 75 | int buttonschanged = oldbuttons ^ newbuttons;
|
| 68 | 76 | DEBUGF("Changed buttons: %02X", buttonschanged);
|
| 69 | 77 | for (i = 0; i < 5; i++)
|
| — | — | @@ -115,7 +123,6 @@ |
| 116 | 124 | lastdiff = 0;
|
| 117 | 125 | }
|
| 118 | 126 |
|
| 119 | | - oldbuttons = newbuttons;
|
| 120 | 127 | oldpos = newpos;
|
| 121 | 128 | oldtouched = newtouched;
|
| 122 | 129 | lastpacket = USEC_TIMER;
|
| — | — | @@ -122,16 +129,36 @@ |
| 123 | 130 | }
|
| 124 | 131 | else if ((data & 0x8000FFFF) == 0x8000023A)
|
| 125 | 132 | {
|
| 126 | | - if (data & 0x1F0000) oldbuttons = (data >> 16) & 0x1F;
|
| 127 | | - DEBUGF("This is an init packet, button state: %02X", oldbuttons);
|
| | 133 | + if (data & 0x1F0000) newbuttons = (data >> 16) & 0x1F;
|
| | 134 | + DEBUGF("This is an init packet, button state: %02X", newbuttons);
|
| | 135 | + if (!wheel_initialized)
|
| | 136 | + {
|
| | 137 | + wheel_initialized = true;
|
| | 138 | + wakeup_signal(&clickwheel_init_wakeup);
|
| | 139 | + }
|
| 128 | 140 | }
|
| | 141 | +
|
| | 142 | + #ifdef TARGET_ipodclassic
|
| | 143 | + if (newbuttons == 0x11 && oldbuttons != 0x11)
|
| | 144 | + {
|
| | 145 | + ata_lock_exclusive(TIMEOUT_BLOCK);
|
| | 146 | + flush_fat(true);
|
| | 147 | + ata_sleepnow();
|
| | 148 | + }
|
| | 149 | + else if (newbuttons != 0x11 && oldbuttons == 0x11)
|
| | 150 | + ata_unlock_exclusive();
|
| | 151 | +#endif
|
| | 152 | +
|
| | 153 | + oldbuttons = newbuttons;
|
| 129 | 154 | }
|
| 130 | 155 | }
|
| 131 | 156 |
|
| 132 | 157 |
|
| 133 | | -void clickwheel_init()
|
| | 158 | +int clickwheel_init()
|
| 134 | 159 | {
|
| 135 | 160 | wakeup_init(&clickwheel_wakeup);
|
| | 161 | + wakeup_init(&clickwheel_init_wakeup);
|
| | 162 | + wheel_initialized = false;
|
| 136 | 163 | oldtouched = false;
|
| 137 | 164 | oldbuttons = 0;
|
| 138 | 165 | lastpacket = 0;
|
| — | — | @@ -150,6 +177,9 @@ |
| 151 | 178 | thread_create(&clickwheel_thread_handle, "Clickwheel dispatcher", clickwheel_thread,
|
| 152 | 179 | clickwheel_stack, sizeof(clickwheel_stack), OS_THREAD, 200, true,
|
| 153 | 180 | NULL, NULL, NULL, NULL);
|
| | 181 | + wakeup_wait(&clickwheel_init_wakeup, 100000);
|
| | 182 | + if (!wheel_initialized) RET_ERR(0);
|
| | 183 | + return 0;
|
| 154 | 184 | }
|
| 155 | 185 |
|
| 156 | 186 | void INT_WHEEL(void) ICODE_ATTR;
|
| Index: emcore/trunk/clickwheel.h |
| — | — | @@ -28,7 +28,7 @@ |
| 29 | 29 | #include "global.h"
|
| 30 | 30 |
|
| 31 | 31 |
|
| 32 | | -void clickwheel_init(void) INITCODE_ATTR;
|
| | 32 | +int clickwheel_init(void) INITCODE_ATTR;
|
| 33 | 33 | uint32_t clickwheel_get_state(void);
|
| 34 | 34 |
|
| 35 | 35 |
|
| Index: emcore/trunk/fat.c |
| — | — | @@ -182,7 +182,6 @@ |
| 183 | 183 | static bool flush_fat_disabled = false;
|
| 184 | 184 |
|
| 185 | 185 | static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
|
| 186 | | -static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb));
|
| 187 | 186 | static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb));
|
| 188 | 187 | static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,)
|
| 189 | 188 | long secnum, bool dirty);
|
| — | — | @@ -487,10 +486,11 @@ |
| 488 | 487 | #else
|
| 489 | 488 | (void)volume;
|
| 490 | 489 | #endif
|
| | 490 | + if (!initialized) return;
|
| 491 | 491 |
|
| 492 | 492 | if(flush)
|
| 493 | 493 | {
|
| 494 | | - rc = flush_fat(IF_MV(fat_bpb)); /* the clean way, while still alive */
|
| | 494 | + rc = flush_fat(IF_MV2(fat_bpb,) true); /* the clean way, while still alive */
|
| 495 | 495 | }
|
| 496 | 496 | else
|
| 497 | 497 | { /* volume is not accessible any more, e.g. MMC removed */
|
| — | — | @@ -1024,12 +1024,12 @@ |
| 1025 | 1025 | return 0;
|
| 1026 | 1026 | }
|
| 1027 | 1027 |
|
| 1028 | | -static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb))
|
| | 1028 | +int flush_fat(IF_MV2(struct bpb* fat_bpb,) bool force)
|
| 1029 | 1029 | {
|
| 1030 | 1030 | int i;
|
| 1031 | 1031 | int rc;
|
| 1032 | 1032 | unsigned char *sec;
|
| 1033 | | - if (flush_fat_disabled)
|
| | 1033 | + if (flush_fat_disabled && !force)
|
| 1034 | 1034 | {
|
| 1035 | 1035 | DEBUGF("flush_fat() skipped");
|
| 1036 | 1036 | return 0;
|
| — | — | @@ -1780,7 +1780,7 @@ |
| 1781 | 1781 | /* Set the firstcluster field in the direntry */
|
| 1782 | 1782 | update_short_entry(&newdir, 0, FAT_ATTR_DIRECTORY);
|
| 1783 | 1783 |
|
| 1784 | | - rc = flush_fat(IF_MV(fat_bpb));
|
| | 1784 | + rc = flush_fat(IF_MV2(fat_bpb,) false);
|
| 1785 | 1785 | if (rc < 0)
|
| 1786 | 1786 | return rc * 10 - 5;
|
| 1787 | 1787 |
|
| — | — | @@ -1830,7 +1830,7 @@ |
| 1831 | 1831 | return rc * 10 - 1;
|
| 1832 | 1832 | }
|
| 1833 | 1833 |
|
| 1834 | | - flush_fat(IF_MV(fat_bpb));
|
| | 1834 | + flush_fat(IF_MV2(fat_bpb,) false);
|
| 1835 | 1835 |
|
| 1836 | 1836 | #ifdef TEST_FAT
|
| 1837 | 1837 | if ( file->firstcluster ) {
|
| — | — | @@ -1968,7 +1968,7 @@ |
| 1969 | 1969 | file->firstcluster = 0;
|
| 1970 | 1970 | file->dircluster = 0;
|
| 1971 | 1971 |
|
| 1972 | | - rc = flush_fat(IF_MV(fat_bpb));
|
| | 1972 | + rc = flush_fat(IF_MV2(fat_bpb,) false);
|
| 1973 | 1973 | if (rc < 0)
|
| 1974 | 1974 | return rc * 10 - 2;
|
| 1975 | 1975 |
|
| — | — | @@ -2017,7 +2017,7 @@ |
| 2018 | 2018 | if (rc < 0)
|
| 2019 | 2019 | return rc * 10 - 4;
|
| 2020 | 2020 |
|
| 2021 | | - rc = flush_fat(IF_MV(fat_bpb));
|
| | 2021 | + rc = flush_fat(IF_MV2(fat_bpb,) false);
|
| 2022 | 2022 | if (rc < 0)
|
| 2023 | 2023 | return rc * 10 - 5;
|
| 2024 | 2024 |
|
| — | — | @@ -2575,5 +2575,5 @@ |
| 2576 | 2576 | void fat_enable_flushing(bool state)
|
| 2577 | 2577 | {
|
| 2578 | 2578 | flush_fat_disabled = !state;
|
| 2579 | | - if (state) flush_fat();
|
| | 2579 | + if (state) flush_fat(true);
|
| 2580 | 2580 | }
|
| Index: emcore/trunk/fat.h |
| — | — | @@ -142,6 +142,7 @@ |
| 143 | 143 | extern bool fat_ismounted(int volume);
|
| 144 | 144 | extern void* fat_get_sector_buffer(void);
|
| 145 | 145 | extern void fat_release_sector_buffer(void);
|
| | 146 | +extern int flush_fat(IF_MV2(struct bpb* fat_bpb,) bool force);
|
| 146 | 147 |
|
| 147 | 148 |
|
| 148 | 149 | #endif
|