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
|