diff options
25 files changed, 1279 insertions, 1574 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index b574117620..373078d8f9 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -20,18 +20,13 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include <stdbool.h> | 21 | #include <stdbool.h> |
22 | #include <inttypes.h> | 22 | #include <inttypes.h> |
23 | #include "ata.h" | ||
24 | #include "kernel.h" | ||
25 | #include "thread.h" | ||
26 | #include "led.h" | 23 | #include "led.h" |
27 | #include "cpu.h" | 24 | #include "cpu.h" |
28 | #include "system.h" | 25 | #include "system.h" |
29 | #include "debug.h" | 26 | #include "debug.h" |
30 | #include "panic.h" | 27 | #include "panic.h" |
31 | #include "usb.h" | ||
32 | #include "power.h" | 28 | #include "power.h" |
33 | #include "string.h" | 29 | #include "string.h" |
34 | #include "ata_idle_notify.h" | ||
35 | #include "ata-driver.h" | 30 | #include "ata-driver.h" |
36 | #include "ata-defines.h" | 31 | #include "ata-defines.h" |
37 | #include "fs_defines.h" | 32 | #include "fs_defines.h" |
@@ -64,24 +59,28 @@ | |||
64 | #define CMD_WRITE_DMA_EXT 0x35 | 59 | #define CMD_WRITE_DMA_EXT 0x35 |
65 | #endif | 60 | #endif |
66 | 61 | ||
67 | /* Should all be < 0x100 (which are reserved for control messages) */ | ||
68 | #define Q_SLEEP 0 | ||
69 | #define Q_CLOSE 1 | ||
70 | |||
71 | #define READWRITE_TIMEOUT 5*HZ | 62 | #define READWRITE_TIMEOUT 5*HZ |
72 | 63 | ||
73 | #ifdef HAVE_ATA_POWER_OFF | 64 | #ifdef HAVE_ATA_POWER_OFF |
74 | #define ATA_POWER_OFF_TIMEOUT 2*HZ | 65 | #define ATA_POWER_OFF_TIMEOUT 2*HZ |
75 | #endif | 66 | #endif |
76 | 67 | ||
77 | #ifdef ATA_DRIVER_CLOSE | ||
78 | static unsigned int ata_thread_id = 0; | ||
79 | #endif | ||
80 | |||
81 | #if defined(HAVE_USBSTACK) | 68 | #if defined(HAVE_USBSTACK) |
82 | #define ALLOW_USB_SPINDOWN | 69 | #define ATA_ACTIVE_IN_USB 1 |
70 | #else | ||
71 | #define ATA_ACTIVE_IN_USB 0 | ||
83 | #endif | 72 | #endif |
84 | 73 | ||
74 | enum { | ||
75 | ATA_BOOT = -1, | ||
76 | ATA_OFF, | ||
77 | ATA_SLEEPING, | ||
78 | ATA_SPINUP, | ||
79 | ATA_ON, | ||
80 | }; | ||
81 | |||
82 | static int ata_state = ATA_BOOT; | ||
83 | |||
85 | static struct mutex ata_mtx SHAREDBSS_ATTR; | 84 | static struct mutex ata_mtx SHAREDBSS_ATTR; |
86 | static int ata_device; /* device 0 (master) or 1 (slave) */ | 85 | static int ata_device; /* device 0 (master) or 1 (slave) */ |
87 | 86 | ||
@@ -90,22 +89,16 @@ static int spinup_time = 0; | |||
90 | static bool ata_led_enabled = true; | 89 | static bool ata_led_enabled = true; |
91 | static bool ata_led_on = false; | 90 | static bool ata_led_on = false; |
92 | #endif | 91 | #endif |
93 | static bool spinup = false; | 92 | |
94 | static bool sleeping = true; | ||
95 | #ifdef HAVE_ATA_POWER_OFF | ||
96 | static bool poweroff = false; | ||
97 | #endif | ||
98 | static long sleep_timeout = 5*HZ; | 93 | static long sleep_timeout = 5*HZ; |
99 | #ifdef HAVE_LBA48 | 94 | #ifdef HAVE_LBA48 |
100 | static bool lba48 = false; /* set for 48 bit addressing */ | 95 | static bool lba48 = false; /* set for 48 bit addressing */ |
101 | #endif | 96 | #endif |
102 | static long ata_stack[(DEFAULT_STACK_SIZE*3)/sizeof(long)]; | ||
103 | static const char ata_thread_name[] = "ata"; | ||
104 | static struct event_queue ata_queue SHAREDBSS_ATTR; | ||
105 | static bool initialized = false; | ||
106 | 97 | ||
107 | static long last_user_activity = -1; | ||
108 | static long last_disk_activity = -1; | 98 | static long last_disk_activity = -1; |
99 | #ifdef HAVE_ATA_POWER_OFF | ||
100 | static long power_off_tick; | ||
101 | #endif | ||
109 | 102 | ||
110 | static unsigned long total_sectors; | 103 | static unsigned long total_sectors; |
111 | static int multisectors; /* number of supported multisectors */ | 104 | static int multisectors; /* number of supported multisectors */ |
@@ -135,6 +128,38 @@ static int perform_soft_reset(void); | |||
135 | static int set_multiple_mode(int sectors); | 128 | static int set_multiple_mode(int sectors); |
136 | static int set_features(void); | 129 | static int set_features(void); |
137 | 130 | ||
131 | static inline void keep_ata_active(void) | ||
132 | { | ||
133 | last_disk_activity = current_tick; | ||
134 | } | ||
135 | |||
136 | static inline void schedule_ata_sleep(long from_now) | ||
137 | { | ||
138 | last_disk_activity = current_tick - sleep_timeout + from_now; | ||
139 | } | ||
140 | |||
141 | static inline bool ata_sleep_timed_out(void) | ||
142 | { | ||
143 | return sleep_timeout && | ||
144 | TIME_AFTER(current_tick, last_disk_activity + sleep_timeout); | ||
145 | } | ||
146 | |||
147 | static inline void schedule_ata_power_off(void) | ||
148 | { | ||
149 | #ifdef HAVE_ATA_POWER_OFF | ||
150 | power_off_tick = current_tick + ATA_POWER_OFF_TIMEOUT; | ||
151 | #endif | ||
152 | } | ||
153 | |||
154 | static inline bool ata_power_off_timed_out(void) | ||
155 | { | ||
156 | #ifdef HAVE_ATA_POWER_OFF | ||
157 | return TIME_AFTER(current_tick, power_off_tick); | ||
158 | #else | ||
159 | return false; | ||
160 | #endif | ||
161 | } | ||
162 | |||
138 | #ifndef ATA_TARGET_POLLING | 163 | #ifndef ATA_TARGET_POLLING |
139 | static ICODE_ATTR int wait_for_bsy(void) | 164 | static ICODE_ATTR int wait_for_bsy(void) |
140 | { | 165 | { |
@@ -144,7 +169,7 @@ static ICODE_ATTR int wait_for_bsy(void) | |||
144 | { | 169 | { |
145 | if (!(ATA_IN8(ATA_STATUS) & STATUS_BSY)) | 170 | if (!(ATA_IN8(ATA_STATUS) & STATUS_BSY)) |
146 | return 1; | 171 | return 1; |
147 | last_disk_activity = current_tick; | 172 | keep_ata_active(); |
148 | yield(); | 173 | yield(); |
149 | } while (TIME_BEFORE(current_tick, timeout)); | 174 | } while (TIME_BEFORE(current_tick, timeout)); |
150 | 175 | ||
@@ -164,7 +189,7 @@ static ICODE_ATTR int wait_for_rdy(void) | |||
164 | { | 189 | { |
165 | if (ATA_IN8(ATA_ALT_STATUS) & STATUS_RDY) | 190 | if (ATA_IN8(ATA_ALT_STATUS) & STATUS_RDY) |
166 | return 1; | 191 | return 1; |
167 | last_disk_activity = current_tick; | 192 | keep_ata_active(); |
168 | yield(); | 193 | yield(); |
169 | } while (TIME_BEFORE(current_tick, timeout)); | 194 | } while (TIME_BEFORE(current_tick, timeout)); |
170 | 195 | ||
@@ -175,6 +200,44 @@ static ICODE_ATTR int wait_for_rdy(void) | |||
175 | #define wait_for_rdy ata_wait_for_rdy | 200 | #define wait_for_rdy ata_wait_for_rdy |
176 | #endif | 201 | #endif |
177 | 202 | ||
203 | static int ata_perform_wakeup(int state) | ||
204 | { | ||
205 | if (state > ATA_OFF) { | ||
206 | if (perform_soft_reset()) { | ||
207 | return -1; | ||
208 | } | ||
209 | } | ||
210 | #ifdef HAVE_ATA_POWER_OFF | ||
211 | else { | ||
212 | if (ata_power_on()) { | ||
213 | return -2; | ||
214 | } | ||
215 | } | ||
216 | #endif | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int ata_perform_sleep(void) | ||
222 | { | ||
223 | ATA_OUT8(ATA_SELECT, ata_device); | ||
224 | |||
225 | if(!wait_for_rdy()) { | ||
226 | DEBUGF("ata_perform_sleep() - not RDY\n"); | ||
227 | return -1; | ||
228 | } | ||
229 | |||
230 | ATA_OUT8(ATA_COMMAND, CMD_SLEEP); | ||
231 | |||
232 | if (!wait_for_rdy()) | ||
233 | { | ||
234 | DEBUGF("ata_perform_sleep() - CMD failed\n"); | ||
235 | return -2; | ||
236 | } | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
178 | static ICODE_ATTR int wait_for_start_of_transfer(void) | 241 | static ICODE_ATTR int wait_for_start_of_transfer(void) |
179 | { | 242 | { |
180 | if (!wait_for_bsy()) | 243 | if (!wait_for_bsy()) |
@@ -278,42 +341,27 @@ static int ata_transfer_sectors(unsigned long start, | |||
278 | long timeout; | 341 | long timeout; |
279 | int count; | 342 | int count; |
280 | void* buf; | 343 | void* buf; |
281 | long spinup_start; | 344 | long spinup_start = spinup_start; |
282 | #ifdef HAVE_ATA_DMA | 345 | #ifdef HAVE_ATA_DMA |
283 | bool usedma = false; | 346 | bool usedma = false; |
284 | #endif | 347 | #endif |
285 | 348 | ||
286 | #ifndef MAX_PHYS_SECTOR_SIZE | ||
287 | mutex_lock(&ata_mtx); | ||
288 | #endif | ||
289 | |||
290 | if (start + incount > total_sectors) { | 349 | if (start + incount > total_sectors) { |
291 | ret = -1; | 350 | ret = -1; |
292 | goto error; | 351 | goto error; |
293 | } | 352 | } |
294 | 353 | ||
295 | last_disk_activity = current_tick; | 354 | keep_ata_active(); |
296 | spinup_start = current_tick; | ||
297 | 355 | ||
298 | ata_led(true); | 356 | ata_led(true); |
299 | 357 | ||
300 | if ( sleeping ) { | 358 | if (ata_state < ATA_ON) { |
301 | sleeping = false; /* set this now since it'll be on */ | 359 | spinup_start = current_tick; |
302 | spinup = true; | 360 | int state = ata_state; |
303 | #ifdef HAVE_ATA_POWER_OFF | 361 | ata_state = ATA_SPINUP; |
304 | if (poweroff) { | 362 | if (ata_perform_wakeup(state)) { |
305 | if (ata_power_on()) { | 363 | ret = -2; |
306 | ret = -2; | 364 | goto error; |
307 | goto error; | ||
308 | } | ||
309 | } | ||
310 | else | ||
311 | #endif | ||
312 | { | ||
313 | if (perform_soft_reset()) { | ||
314 | ret = -2; | ||
315 | goto error; | ||
316 | } | ||
317 | } | 365 | } |
318 | } | 366 | } |
319 | 367 | ||
@@ -331,7 +379,7 @@ static int ata_transfer_sectors(unsigned long start, | |||
331 | count = incount; | 379 | count = incount; |
332 | while (TIME_BEFORE(current_tick, timeout)) { | 380 | while (TIME_BEFORE(current_tick, timeout)) { |
333 | ret = 0; | 381 | ret = 0; |
334 | last_disk_activity = current_tick; | 382 | keep_ata_active(); |
335 | 383 | ||
336 | #ifdef HAVE_ATA_DMA | 384 | #ifdef HAVE_ATA_DMA |
337 | /* If DMA is supported and parameters are ok for DMA, use it */ | 385 | /* If DMA is supported and parameters are ok for DMA, use it */ |
@@ -395,12 +443,9 @@ static int ata_transfer_sectors(unsigned long start, | |||
395 | goto retry; | 443 | goto retry; |
396 | } | 444 | } |
397 | 445 | ||
398 | if (spinup) { | 446 | if (ata_state == ATA_SPINUP) { |
447 | ata_state = ATA_ON; | ||
399 | spinup_time = current_tick - spinup_start; | 448 | spinup_time = current_tick - spinup_start; |
400 | spinup = false; | ||
401 | #ifdef HAVE_ATA_POWER_OFF | ||
402 | poweroff = false; | ||
403 | #endif | ||
404 | } | 449 | } |
405 | } | 450 | } |
406 | else | 451 | else |
@@ -426,12 +471,9 @@ static int ata_transfer_sectors(unsigned long start, | |||
426 | goto retry; | 471 | goto retry; |
427 | } | 472 | } |
428 | 473 | ||
429 | if (spinup) { | 474 | if (ata_state == ATA_SPINUP) { |
475 | ata_state = ATA_ON; | ||
430 | spinup_time = current_tick - spinup_start; | 476 | spinup_time = current_tick - spinup_start; |
431 | spinup = false; | ||
432 | #ifdef HAVE_ATA_POWER_OFF | ||
433 | poweroff = false; | ||
434 | #endif | ||
435 | } | 477 | } |
436 | 478 | ||
437 | /* read the status register exactly once per loop */ | 479 | /* read the status register exactly once per loop */ |
@@ -470,7 +512,7 @@ static int ata_transfer_sectors(unsigned long start, | |||
470 | buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */ | 512 | buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */ |
471 | count -= sectors; | 513 | count -= sectors; |
472 | 514 | ||
473 | last_disk_activity = current_tick; | 515 | keep_ata_active(); |
474 | } | 516 | } |
475 | } | 517 | } |
476 | 518 | ||
@@ -490,9 +532,11 @@ static int ata_transfer_sectors(unsigned long start, | |||
490 | 532 | ||
491 | error: | 533 | error: |
492 | ata_led(false); | 534 | ata_led(false); |
493 | #ifndef MAX_PHYS_SECTOR_SIZE | 535 | |
494 | mutex_unlock(&ata_mtx); | 536 | if (ret < 0 && ata_state == ATA_SPINUP) { |
495 | #endif | 537 | /* bailed out before updating */ |
538 | ata_state = ATA_ON; | ||
539 | } | ||
496 | 540 | ||
497 | return ret; | 541 | return ret; |
498 | } | 542 | } |
@@ -507,11 +551,12 @@ int ata_read_sectors(IF_MD(int drive,) | |||
507 | (void)drive; /* unused for now */ | 551 | (void)drive; /* unused for now */ |
508 | #endif | 552 | #endif |
509 | 553 | ||
510 | return ata_transfer_sectors(start, incount, inbuf, false); | 554 | mutex_lock(&ata_mtx); |
555 | int rc = ata_transfer_sectors(start, incount, inbuf, false); | ||
556 | mutex_unlock(&ata_mtx); | ||
557 | return rc; | ||
511 | } | 558 | } |
512 | #endif | ||
513 | 559 | ||
514 | #ifndef MAX_PHYS_SECTOR_SIZE | ||
515 | int ata_write_sectors(IF_MD(int drive,) | 560 | int ata_write_sectors(IF_MD(int drive,) |
516 | unsigned long start, | 561 | unsigned long start, |
517 | int count, | 562 | int count, |
@@ -521,9 +566,12 @@ int ata_write_sectors(IF_MD(int drive,) | |||
521 | (void)drive; /* unused for now */ | 566 | (void)drive; /* unused for now */ |
522 | #endif | 567 | #endif |
523 | 568 | ||
524 | return ata_transfer_sectors(start, count, (void*)buf, true); | 569 | mutex_lock(&ata_mtx); |
570 | int rc = ata_transfer_sectors(start, count, (void*)buf, true); | ||
571 | mutex_unlock(&ata_mtx); | ||
572 | return rc; | ||
525 | } | 573 | } |
526 | #endif | 574 | #endif /* ndef MAX_PHYS_SECTOR_SIZE */ |
527 | 575 | ||
528 | #ifdef MAX_PHYS_SECTOR_SIZE | 576 | #ifdef MAX_PHYS_SECTOR_SIZE |
529 | static int cache_sector(unsigned long sector) | 577 | static int cache_sector(unsigned long sector) |
@@ -748,178 +796,26 @@ void ata_spindown(int seconds) | |||
748 | 796 | ||
749 | bool ata_disk_is_active(void) | 797 | bool ata_disk_is_active(void) |
750 | { | 798 | { |
751 | return !sleeping; | 799 | return ata_state >= ATA_SPINUP; |
752 | } | ||
753 | |||
754 | static int ata_perform_sleep(void) | ||
755 | { | ||
756 | /* guard against calls made with checks of these variables outside | ||
757 | the mutex that may not be on the ata thread; status may have changed. */ | ||
758 | if (spinup || sleeping) { | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | ATA_OUT8(ATA_SELECT, ata_device); | ||
763 | |||
764 | if(!wait_for_rdy()) { | ||
765 | DEBUGF("ata_perform_sleep() - not RDY\n"); | ||
766 | return -1; | ||
767 | } | ||
768 | |||
769 | ATA_OUT8(ATA_COMMAND, CMD_SLEEP); | ||
770 | |||
771 | if (!wait_for_rdy()) | ||
772 | { | ||
773 | DEBUGF("ata_perform_sleep() - CMD failed\n"); | ||
774 | return -2; | ||
775 | } | ||
776 | |||
777 | sleeping = true; | ||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | void ata_sleep(void) | ||
782 | { | ||
783 | queue_post(&ata_queue, Q_SLEEP, 0); | ||
784 | } | 800 | } |
785 | 801 | ||
786 | void ata_sleepnow(void) | 802 | void ata_sleepnow(void) |
787 | { | 803 | { |
788 | if (!spinup && !sleeping && initialized) | 804 | if (ata_state >= ATA_SPINUP) { |
789 | { | ||
790 | call_storage_idle_notifys(false); | ||
791 | mutex_lock(&ata_mtx); | 805 | mutex_lock(&ata_mtx); |
792 | ata_perform_sleep(); | 806 | if (ata_state == ATA_ON) { |
807 | if (!ata_perform_sleep()) { | ||
808 | ata_state = ATA_SLEEPING; | ||
809 | schedule_ata_power_off(); | ||
810 | } | ||
811 | } | ||
793 | mutex_unlock(&ata_mtx); | 812 | mutex_unlock(&ata_mtx); |
794 | } | 813 | } |
795 | } | 814 | } |
796 | 815 | ||
797 | void ata_spin(void) | 816 | void ata_spin(void) |
798 | { | 817 | { |
799 | last_user_activity = current_tick; | 818 | keep_ata_active(); |
800 | } | ||
801 | |||
802 | static void ata_thread(void) | ||
803 | { | ||
804 | #ifdef HAVE_ATA_POWER_OFF | ||
805 | static long last_sleep = 0; | ||
806 | #endif | ||
807 | struct queue_event ev; | ||
808 | #ifdef ALLOW_USB_SPINDOWN | ||
809 | static bool usb_mode = false; | ||
810 | #endif | ||
811 | |||
812 | while (1) { | ||
813 | queue_wait_w_tmo(&ata_queue, &ev, HZ/2); | ||
814 | |||
815 | switch ( ev.id ) { | ||
816 | case SYS_TIMEOUT: | ||
817 | if (!spinup && !sleeping) | ||
818 | { | ||
819 | if (TIME_AFTER( current_tick, | ||
820 | last_disk_activity + (HZ*2) ) ) | ||
821 | { | ||
822 | #ifdef ALLOW_USB_SPINDOWN | ||
823 | if(!usb_mode) | ||
824 | #endif | ||
825 | { | ||
826 | call_storage_idle_notifys(false); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | if ( sleep_timeout && | ||
831 | TIME_AFTER( current_tick, | ||
832 | last_user_activity + sleep_timeout ) && | ||
833 | TIME_AFTER( current_tick, | ||
834 | last_disk_activity + sleep_timeout ) ) | ||
835 | { | ||
836 | #ifdef ALLOW_USB_SPINDOWN | ||
837 | if(!usb_mode) | ||
838 | #endif | ||
839 | { | ||
840 | call_storage_idle_notifys(true); | ||
841 | } | ||
842 | mutex_lock(&ata_mtx); | ||
843 | ata_perform_sleep(); | ||
844 | #ifdef HAVE_ATA_POWER_OFF | ||
845 | last_sleep = current_tick; | ||
846 | #endif | ||
847 | mutex_unlock(&ata_mtx); | ||
848 | } | ||
849 | } | ||
850 | |||
851 | #ifdef HAVE_ATA_POWER_OFF | ||
852 | if ( !spinup && sleeping && !poweroff && | ||
853 | TIME_AFTER( current_tick, last_sleep + ATA_POWER_OFF_TIMEOUT )) | ||
854 | { | ||
855 | mutex_lock(&ata_mtx); | ||
856 | ide_power_enable(false); | ||
857 | poweroff = true; | ||
858 | mutex_unlock(&ata_mtx); | ||
859 | } | ||
860 | #endif | ||
861 | break; | ||
862 | |||
863 | #ifndef USB_NONE | ||
864 | case SYS_USB_CONNECTED: | ||
865 | /* Tell the USB thread that we are safe */ | ||
866 | DEBUGF("ata_thread got SYS_USB_CONNECTED\n"); | ||
867 | #ifdef ALLOW_USB_SPINDOWN | ||
868 | usb_mode = true; | ||
869 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
870 | /* There is no need to force ATA power on */ | ||
871 | #else | ||
872 | mutex_lock(&ata_mtx); | ||
873 | if (sleeping) { | ||
874 | ata_led(true); | ||
875 | sleeping = false; /* set this now since it'll be on */ | ||
876 | |||
877 | #ifdef HAVE_ATA_POWER_OFF | ||
878 | if (poweroff) { | ||
879 | ata_power_on(); | ||
880 | poweroff = false; | ||
881 | } | ||
882 | else | ||
883 | #endif | ||
884 | { | ||
885 | perform_soft_reset(); | ||
886 | } | ||
887 | |||
888 | ata_led(false); | ||
889 | } | ||
890 | mutex_unlock(&ata_mtx); | ||
891 | |||
892 | /* Wait until the USB cable is extracted again */ | ||
893 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
894 | usb_wait_for_disconnect(&ata_queue); | ||
895 | #endif | ||
896 | break; | ||
897 | |||
898 | #ifdef ALLOW_USB_SPINDOWN | ||
899 | case SYS_USB_DISCONNECTED: | ||
900 | /* Tell the USB thread that we are ready again */ | ||
901 | DEBUGF("ata_thread got SYS_USB_DISCONNECTED\n"); | ||
902 | usb_mode = false; | ||
903 | break; | ||
904 | #endif | ||
905 | #endif /* USB_NONE */ | ||
906 | |||
907 | case Q_SLEEP: | ||
908 | #ifdef ALLOW_USB_SPINDOWN | ||
909 | if(!usb_mode) | ||
910 | #endif | ||
911 | { | ||
912 | call_storage_idle_notifys(false); | ||
913 | } | ||
914 | last_disk_activity = current_tick - sleep_timeout + (HZ/2); | ||
915 | break; | ||
916 | |||
917 | #ifdef ATA_DRIVER_CLOSE | ||
918 | case Q_CLOSE: | ||
919 | return; | ||
920 | #endif | ||
921 | } | ||
922 | } | ||
923 | } | 819 | } |
924 | 820 | ||
925 | /* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */ | 821 | /* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */ |
@@ -1025,11 +921,13 @@ static int perform_soft_reset(void) | |||
1025 | 921 | ||
1026 | int ata_soft_reset(void) | 922 | int ata_soft_reset(void) |
1027 | { | 923 | { |
1028 | int ret; | 924 | int ret = -6; |
1029 | 925 | ||
1030 | mutex_lock(&ata_mtx); | 926 | mutex_lock(&ata_mtx); |
1031 | 927 | ||
1032 | ret = perform_soft_reset(); | 928 | if (ata_state > ATA_OFF) { |
929 | ret = perform_soft_reset(); | ||
930 | } | ||
1033 | 931 | ||
1034 | mutex_unlock(&ata_mtx); | 932 | mutex_unlock(&ata_mtx); |
1035 | return ret; | 933 | return ret; |
@@ -1068,7 +966,7 @@ static int ata_power_on(void) | |||
1068 | 966 | ||
1069 | return 0; | 967 | return 0; |
1070 | } | 968 | } |
1071 | #endif | 969 | #endif /* HAVE_ATA_POWER_OFF */ |
1072 | 970 | ||
1073 | static int STORAGE_INIT_ATTR master_slave_detect(void) | 971 | static int STORAGE_INIT_ATTR master_slave_detect(void) |
1074 | { | 972 | { |
@@ -1250,9 +1148,8 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1250 | int rc = 0; | 1148 | int rc = 0; |
1251 | bool coldstart; | 1149 | bool coldstart; |
1252 | 1150 | ||
1253 | if ( !initialized ) { | 1151 | if (ata_state == ATA_BOOT) { |
1254 | mutex_init(&ata_mtx); | 1152 | mutex_init(&ata_mtx); |
1255 | queue_init(&ata_queue, true); | ||
1256 | } | 1153 | } |
1257 | 1154 | ||
1258 | mutex_lock(&ata_mtx); | 1155 | mutex_lock(&ata_mtx); |
@@ -1261,16 +1158,13 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1261 | coldstart = ata_is_coldstart(); | 1158 | coldstart = ata_is_coldstart(); |
1262 | ata_led(false); | 1159 | ata_led(false); |
1263 | ata_device_init(); | 1160 | ata_device_init(); |
1264 | sleeping = false; | ||
1265 | ata_enable(true); | 1161 | ata_enable(true); |
1266 | #ifdef MAX_PHYS_SECTOR_SIZE | 1162 | #ifdef MAX_PHYS_SECTOR_SIZE |
1267 | memset(§or_cache, 0, sizeof(sector_cache)); | 1163 | memset(§or_cache, 0, sizeof(sector_cache)); |
1268 | #endif | 1164 | #endif |
1269 | 1165 | ||
1270 | if ( !initialized ) { | 1166 | if (ata_state == ATA_BOOT) { |
1271 | /* First call won't have multiple thread contention - this | 1167 | ata_state = ATA_OFF; |
1272 | * may return at any point without having to unlock */ | ||
1273 | mutex_unlock(&ata_mtx); | ||
1274 | 1168 | ||
1275 | if (!ide_powered()) /* somebody has switched it off */ | 1169 | if (!ide_powered()) /* somebody has switched it off */ |
1276 | { | 1170 | { |
@@ -1290,14 +1184,17 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1290 | { /* failed? -> second try, always with hard reset */ | 1184 | { /* failed? -> second try, always with hard reset */ |
1291 | DEBUGF("ata: init failed, retrying...\n"); | 1185 | DEBUGF("ata: init failed, retrying...\n"); |
1292 | rc = init_and_check(true); | 1186 | rc = init_and_check(true); |
1293 | if (rc) | 1187 | if (rc) { |
1294 | return rc; | 1188 | goto error; |
1189 | } | ||
1295 | } | 1190 | } |
1296 | 1191 | ||
1297 | rc = identify(); | 1192 | rc = identify(); |
1298 | 1193 | ||
1299 | if (rc) | 1194 | if (rc) { |
1300 | return -40 + rc; | 1195 | rc = -40 + rc; |
1196 | goto error; | ||
1197 | } | ||
1301 | 1198 | ||
1302 | multisectors = identify_info[47] & 0xff; | 1199 | multisectors = identify_info[47] & 0xff; |
1303 | if (multisectors == 0) /* Invalid multisector info, try with 16 */ | 1200 | if (multisectors == 0) /* Invalid multisector info, try with 16 */ |
@@ -1317,15 +1214,20 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1317 | total_sectors = identify_info[100] | (identify_info[101] << 16); | 1214 | total_sectors = identify_info[100] | (identify_info[101] << 16); |
1318 | lba48 = true; /* use BigLBA */ | 1215 | lba48 = true; /* use BigLBA */ |
1319 | } | 1216 | } |
1320 | #endif | 1217 | #endif /* HAVE_LBA48 */ |
1218 | |||
1321 | rc = freeze_lock(); | 1219 | rc = freeze_lock(); |
1322 | 1220 | ||
1323 | if (rc) | 1221 | if (rc) { |
1324 | return -50 + rc; | 1222 | rc = -50 + rc; |
1223 | goto error; | ||
1224 | } | ||
1325 | 1225 | ||
1326 | rc = set_features(); | 1226 | rc = set_features(); |
1327 | if (rc) | 1227 | if (rc) { |
1328 | return -60 + rc; | 1228 | rc = -60 + rc; |
1229 | goto error; | ||
1230 | } | ||
1329 | 1231 | ||
1330 | #ifdef MAX_PHYS_SECTOR_SIZE | 1232 | #ifdef MAX_PHYS_SECTOR_SIZE |
1331 | /* Find out the physical sector size */ | 1233 | /* Find out the physical sector size */ |
@@ -1351,44 +1253,20 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1351 | if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE)) | 1253 | if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE)) |
1352 | panicf("Unsupported physical sector size: %d", | 1254 | panicf("Unsupported physical sector size: %d", |
1353 | phys_sector_mult * SECTOR_SIZE); | 1255 | phys_sector_mult * SECTOR_SIZE); |
1354 | #endif | 1256 | #endif /* MAX_PHYS_SECTOR_SIZE */ |
1355 | |||
1356 | mutex_lock(&ata_mtx); /* Balance unlock below */ | ||
1357 | |||
1358 | last_disk_activity = current_tick; | ||
1359 | #ifdef ATA_DRIVER_CLOSE | ||
1360 | ata_thread_id = | ||
1361 | #endif | ||
1362 | create_thread(ata_thread, ata_stack, | ||
1363 | sizeof(ata_stack), 0, ata_thread_name | ||
1364 | IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
1365 | IF_COP(, CPU)); | ||
1366 | initialized = true; | ||
1367 | 1257 | ||
1258 | ata_state = ATA_ON; | ||
1259 | keep_ata_active(); | ||
1368 | } | 1260 | } |
1369 | rc = set_multiple_mode(multisectors); | 1261 | rc = set_multiple_mode(multisectors); |
1370 | if (rc) | 1262 | if (rc) |
1371 | rc = -70 + rc; | 1263 | rc = -70 + rc; |
1372 | 1264 | ||
1265 | error: | ||
1373 | mutex_unlock(&ata_mtx); | 1266 | mutex_unlock(&ata_mtx); |
1374 | return rc; | 1267 | return rc; |
1375 | } | 1268 | } |
1376 | 1269 | ||
1377 | #ifdef ATA_DRIVER_CLOSE | ||
1378 | void ata_close(void) | ||
1379 | { | ||
1380 | unsigned int thread_id = ata_thread_id; | ||
1381 | |||
1382 | if (thread_id == 0) | ||
1383 | return; | ||
1384 | |||
1385 | ata_thread_id = 0; | ||
1386 | |||
1387 | queue_post(&ata_queue, Q_CLOSE, 0); | ||
1388 | thread_wait(thread_id); | ||
1389 | } | ||
1390 | #endif /* ATA_DRIVER_CLOSE */ | ||
1391 | |||
1392 | #if (CONFIG_LED == LED_REAL) | 1270 | #if (CONFIG_LED == LED_REAL) |
1393 | void ata_set_led_enabled(bool enabled) | 1271 | void ata_set_led_enabled(bool enabled) |
1394 | { | 1272 | { |
@@ -1453,9 +1331,7 @@ int ata_get_dma_mode(void) | |||
1453 | 1331 | ||
1454 | /* Needed to allow updating while waiting for DMA to complete */ | 1332 | /* Needed to allow updating while waiting for DMA to complete */ |
1455 | void ata_keep_active(void) | 1333 | void ata_keep_active(void) |
1456 | { | 1334 | __attribute__((alias("ata_spin"))); |
1457 | last_disk_activity = current_tick; | ||
1458 | } | ||
1459 | #endif | 1335 | #endif |
1460 | 1336 | ||
1461 | #ifdef CONFIG_STORAGE_MULTI | 1337 | #ifdef CONFIG_STORAGE_MULTI |
@@ -1467,3 +1343,58 @@ int ata_num_drives(int first_drive) | |||
1467 | return 1; | 1343 | return 1; |
1468 | } | 1344 | } |
1469 | #endif | 1345 | #endif |
1346 | |||
1347 | int ata_event(long id, intptr_t data) | ||
1348 | { | ||
1349 | int rc = 0; | ||
1350 | |||
1351 | /* GCC does a lousy job culling unreachable cases in the default handler | ||
1352 | if statements are in a switch statement, so we'll do it this way. Only | ||
1353 | the first case is frequently hit anyway. */ | ||
1354 | if (LIKELY(id == Q_STORAGE_TICK)) { | ||
1355 | /* won't see ATA_BOOT in here */ | ||
1356 | int state = ata_state; | ||
1357 | if (state != ATA_ON || !ata_sleep_timed_out()) { | ||
1358 | if (state == ATA_SLEEPING && ata_power_off_timed_out()) { | ||
1359 | mutex_lock(&ata_mtx); | ||
1360 | if (ata_state == ATA_SLEEPING) { | ||
1361 | ide_power_enable(false); | ||
1362 | ata_state = ATA_OFF; | ||
1363 | } | ||
1364 | mutex_unlock(&ata_mtx); | ||
1365 | } | ||
1366 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); | ||
1367 | } | ||
1368 | } | ||
1369 | else if (id == Q_STORAGE_SLEEPNOW) { | ||
1370 | ata_sleepnow(); | ||
1371 | } | ||
1372 | else if (id == Q_STORAGE_SLEEP) { | ||
1373 | schedule_ata_sleep(HZ/5); | ||
1374 | } | ||
1375 | #ifndef USB_NONE | ||
1376 | else if (id == SYS_USB_CONNECTED) { | ||
1377 | if (ATA_ACTIVE_IN_USB) { | ||
1378 | /* There is no need to force ATA power on */ | ||
1379 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); | ||
1380 | } | ||
1381 | else { | ||
1382 | mutex_lock(&ata_mtx); | ||
1383 | if (ata_state < ATA_ON) { | ||
1384 | ata_led(true); | ||
1385 | if (!(rc = ata_perform_wakeup(ata_state))) { | ||
1386 | ata_state = ATA_ON; | ||
1387 | } | ||
1388 | ata_led(false); | ||
1389 | } | ||
1390 | mutex_unlock(&ata_mtx); | ||
1391 | } | ||
1392 | } | ||
1393 | #endif /* ndef USB_NONE */ | ||
1394 | else { | ||
1395 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
1396 | STORAGE_ATA); | ||
1397 | } | ||
1398 | |||
1399 | return rc; | ||
1400 | } | ||
diff --git a/firmware/drivers/ramdisk.c b/firmware/drivers/ramdisk.c index 44235c4575..9f73b6b5c3 100644 --- a/firmware/drivers/ramdisk.c +++ b/firmware/drivers/ramdisk.c | |||
@@ -159,3 +159,8 @@ bool ramdisk_present(IF_MD(int drive)) | |||
159 | } | 159 | } |
160 | #endif | 160 | #endif |
161 | 161 | ||
162 | int ramdisk_event(long id, intptr_t data) | ||
163 | { | ||
164 | return storage_event_default_handler(id, data, last_disk_activity, | ||
165 | STORAGE_RAMDISK); | ||
166 | } | ||
diff --git a/firmware/export/ata.h b/firmware/export/ata.h index a1b7ab6372..e6ca9422ea 100644 --- a/firmware/export/ata.h +++ b/firmware/export/ata.h | |||
@@ -175,4 +175,8 @@ int ata_get_dma_mode(void); | |||
175 | int ata_read_smart(struct ata_smart_values*); | 175 | int ata_read_smart(struct ata_smart_values*); |
176 | #endif | 176 | #endif |
177 | 177 | ||
178 | #ifdef BOOTLOADER | ||
179 | #define STORAGE_CLOSE | ||
180 | #endif | ||
181 | |||
178 | #endif /* __ATA_H__ */ | 182 | #endif /* __ATA_H__ */ |
diff --git a/firmware/export/ata_mmc.h b/firmware/export/ata_mmc.h index 2f8011cf8f..cde1fc7ad1 100644 --- a/firmware/export/ata_mmc.h +++ b/firmware/export/ata_mmc.h | |||
@@ -21,6 +21,8 @@ | |||
21 | #ifndef __ATA_MMC_H__ | 21 | #ifndef __ATA_MMC_H__ |
22 | #define __ATA_MMC_H__ | 22 | #define __ATA_MMC_H__ |
23 | 23 | ||
24 | #include <stdbool.h> | ||
25 | |||
24 | void mmc_enable_int_flash_clock(bool on); | 26 | void mmc_enable_int_flash_clock(bool on); |
25 | bool mmc_detect(void); | 27 | bool mmc_detect(void); |
26 | bool mmc_touched(void); | 28 | bool mmc_touched(void); |
diff --git a/firmware/export/sd.h b/firmware/export/sd.h index 9ae3313ffd..c657f8a545 100644 --- a/firmware/export/sd.h +++ b/firmware/export/sd.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "mv.h" /* for HAVE_MULTIDRIVE or not */ | 27 | #include "mv.h" /* for HAVE_MULTIDRIVE or not */ |
28 | 28 | ||
29 | #ifdef HAVE_BOOTLOADER_USB_MODE | 29 | #ifdef HAVE_BOOTLOADER_USB_MODE |
30 | #define SD_DRIVER_CLOSE | 30 | #define STORAGE_CLOSE |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define SD_BLOCK_SIZE 512 /* XXX : support other sizes ? */ | 33 | #define SD_BLOCK_SIZE 512 /* XXX : support other sizes ? */ |
diff --git a/firmware/export/storage.h b/firmware/export/storage.h index 14cba09b35..8a4c95c05b 100644 --- a/firmware/export/storage.h +++ b/firmware/export/storage.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <stdbool.h> | 25 | #include <stdbool.h> |
26 | #include "config.h" /* for HAVE_MULTIDRIVE or not */ | 26 | #include "config.h" /* for HAVE_MULTIDRIVE or not */ |
27 | #include "mv.h" | 27 | #include "mv.h" |
28 | #include <kernel.h> | ||
28 | 29 | ||
29 | #if (CONFIG_STORAGE & STORAGE_HOSTFS) || defined(SIMULATOR) | 30 | #if (CONFIG_STORAGE & STORAGE_HOSTFS) || defined(SIMULATOR) |
30 | #define HAVE_HOSTFS | 31 | #define HAVE_HOSTFS |
@@ -46,6 +47,57 @@ | |||
46 | #include "ramdisk.h" | 47 | #include "ramdisk.h" |
47 | #endif | 48 | #endif |
48 | 49 | ||
50 | enum | ||
51 | { | ||
52 | Q_STORAGE_TICK = 1, | ||
53 | Q_STORAGE_SLEEP, | ||
54 | Q_STORAGE_SLEEPNOW, | ||
55 | #ifdef STORAGE_CLOSE | ||
56 | Q_STORAGE_CLOSE, | ||
57 | #endif | ||
58 | }; | ||
59 | |||
60 | #define STG_EVENT_ASSERT_ACTIVE(type) \ | ||
61 | ({ intptr_t __data = (data); \ | ||
62 | *((unsigned int *)(__data)) |= (type); }) | ||
63 | |||
64 | static FORCE_INLINE int storage_event_default_handler(long id, | ||
65 | intptr_t data, | ||
66 | long last_activity, | ||
67 | unsigned int type) | ||
68 | { | ||
69 | /* fake sleep in order to trigger storage idle sequence */ | ||
70 | static long slept_at = -1; | ||
71 | |||
72 | if (id == Q_STORAGE_TICK) { | ||
73 | if (last_activity == slept_at || | ||
74 | TIME_BEFORE(current_tick, last_activity + 3*HZ)) { | ||
75 | STG_EVENT_ASSERT_ACTIVE(type); | ||
76 | } | ||
77 | } | ||
78 | else if (id == Q_STORAGE_SLEEPNOW) { | ||
79 | slept_at = last_activity; | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | #if (CONFIG_STORAGE & STORAGE_SD) | ||
86 | int sd_event(long id, intptr_t data); | ||
87 | #endif | ||
88 | #if (CONFIG_STORAGE & STORAGE_MMC) | ||
89 | int mmc_event(long id, intptr_t data); | ||
90 | #endif | ||
91 | #if (CONFIG_STORAGE & STORAGE_ATA) | ||
92 | int ata_event(long id, intptr_t data); | ||
93 | #endif | ||
94 | #if (CONFIG_STORAGE & STORAGE_NAND) | ||
95 | int nand_event(long id, intptr_t data); | ||
96 | #endif | ||
97 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | ||
98 | int ramdisk_event(long id, intptr_t data); | ||
99 | #endif | ||
100 | |||
49 | struct storage_info | 101 | struct storage_info |
50 | { | 102 | { |
51 | unsigned int sector_size; | 103 | unsigned int sector_size; |
@@ -55,13 +107,24 @@ struct storage_info | |||
55 | char *revision; | 107 | char *revision; |
56 | }; | 108 | }; |
57 | 109 | ||
110 | int storage_init(void) STORAGE_INIT_ATTR; | ||
111 | void storage_close(void); | ||
112 | |||
58 | #ifdef HAVE_HOSTFS | 113 | #ifdef HAVE_HOSTFS |
59 | #include "hostfs.h" | 114 | #include "hostfs.h" |
60 | /* stubs for the plugin api */ | 115 | /* stubs for the plugin api */ |
61 | static inline void stub_storage_sleep(void) {} | 116 | static inline void stub_storage_sleep(void) {} |
62 | static inline void stub_storage_spin(void) {} | 117 | static inline void stub_storage_spin(void) {} |
63 | static inline void stub_storage_spindown(int timeout) { (void)timeout; } | 118 | static inline void stub_storage_spindown(int timeout) { (void)timeout; } |
119 | static inline int stub_storage_event(long id, intptr_t data) | ||
120 | { return 0; (void)id; (void)data; } | ||
121 | #else /* ndef HAVE_HOSTFS */ | ||
122 | #if (CONFIG_STORAGE & STORAGE_ATA) | ||
123 | void storage_sleep(void); | ||
124 | #else | ||
125 | static inline void storage_sleep(void) {} | ||
64 | #endif | 126 | #endif |
127 | #endif /* HAVE_HOSTFS */ | ||
65 | 128 | ||
66 | #if !defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOSTFS) | 129 | #if !defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOSTFS) |
67 | /* storage_spindown, storage_sleep and storage_spin are passed as | 130 | /* storage_spindown, storage_sleep and storage_spin are passed as |
@@ -70,6 +133,7 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; } | |||
70 | #define storage_num_drives() NUM_DRIVES | 133 | #define storage_num_drives() NUM_DRIVES |
71 | #if defined(HAVE_HOSTFS) | 134 | #if defined(HAVE_HOSTFS) |
72 | #define STORAGE_FUNCTION(NAME) (stub_## NAME) | 135 | #define STORAGE_FUNCTION(NAME) (stub_## NAME) |
136 | #define storage_event stub_storage_event | ||
73 | #define storage_spindown stub_storage_spindown | 137 | #define storage_spindown stub_storage_spindown |
74 | #define storage_sleep stub_storage_sleep | 138 | #define storage_sleep stub_storage_sleep |
75 | #define storage_spin stub_storage_spin | 139 | #define storage_spin stub_storage_spin |
@@ -97,15 +161,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; } | |||
97 | #elif (CONFIG_STORAGE & STORAGE_ATA) | 161 | #elif (CONFIG_STORAGE & STORAGE_ATA) |
98 | #define STORAGE_FUNCTION(NAME) (ata_## NAME) | 162 | #define STORAGE_FUNCTION(NAME) (ata_## NAME) |
99 | #define storage_spindown ata_spindown | 163 | #define storage_spindown ata_spindown |
100 | #define storage_sleep ata_sleep | ||
101 | #define storage_spin ata_spin | 164 | #define storage_spin ata_spin |
102 | 165 | ||
103 | #define storage_enable(on) ata_enable(on) | 166 | #define storage_enable(on) ata_enable(on) |
104 | #define storage_sleepnow() ata_sleepnow() | 167 | #define storage_sleepnow() ata_sleepnow() |
105 | #define storage_disk_is_active() ata_disk_is_active() | 168 | #define storage_disk_is_active() ata_disk_is_active() |
106 | #define storage_soft_reset() ata_soft_reset() | 169 | #define storage_soft_reset() ata_soft_reset() |
107 | #define storage_init() ata_init() | ||
108 | #define storage_close() ata_close() | ||
109 | #ifdef HAVE_STORAGE_FLUSH | 170 | #ifdef HAVE_STORAGE_FLUSH |
110 | #define storage_flush() (void)0 | 171 | #define storage_flush() (void)0 |
111 | #endif | 172 | #endif |
@@ -124,15 +185,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; } | |||
124 | #elif (CONFIG_STORAGE & STORAGE_SD) | 185 | #elif (CONFIG_STORAGE & STORAGE_SD) |
125 | #define STORAGE_FUNCTION(NAME) (sd_## NAME) | 186 | #define STORAGE_FUNCTION(NAME) (sd_## NAME) |
126 | #define storage_spindown sd_spindown | 187 | #define storage_spindown sd_spindown |
127 | #define storage_sleep sd_sleep | ||
128 | #define storage_spin sd_spin | 188 | #define storage_spin sd_spin |
129 | 189 | ||
130 | #define storage_enable(on) sd_enable(on) | 190 | #define storage_enable(on) sd_enable(on) |
131 | #define storage_sleepnow() sd_sleepnow() | 191 | #define storage_sleepnow() sd_sleepnow() |
132 | #define storage_disk_is_active() 0 | 192 | #define storage_disk_is_active() 0 |
133 | #define storage_soft_reset() (void)0 | 193 | #define storage_soft_reset() (void)0 |
134 | #define storage_init() sd_init() | ||
135 | #define storage_close() sd_close() | ||
136 | #ifdef HAVE_STORAGE_FLUSH | 194 | #ifdef HAVE_STORAGE_FLUSH |
137 | #define storage_flush() (void)0 | 195 | #define storage_flush() (void)0 |
138 | #endif | 196 | #endif |
@@ -151,14 +209,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; } | |||
151 | #elif (CONFIG_STORAGE & STORAGE_MMC) | 209 | #elif (CONFIG_STORAGE & STORAGE_MMC) |
152 | #define STORAGE_FUNCTION(NAME) (mmc_## NAME) | 210 | #define STORAGE_FUNCTION(NAME) (mmc_## NAME) |
153 | #define storage_spindown mmc_spindown | 211 | #define storage_spindown mmc_spindown |
154 | #define storage_sleep mmc_sleep | ||
155 | #define storage_spin mmc_spin | 212 | #define storage_spin mmc_spin |
156 | 213 | ||
157 | #define storage_enable(on) mmc_enable(on) | 214 | #define storage_enable(on) mmc_enable(on) |
158 | #define storage_sleepnow() mmc_sleepnow() | 215 | #define storage_sleepnow() mmc_sleepnow() |
159 | #define storage_disk_is_active() mmc_disk_is_active() | 216 | #define storage_disk_is_active() mmc_disk_is_active() |
160 | #define storage_soft_reset() (void)0 | 217 | #define storage_soft_reset() (void)0 |
161 | #define storage_init() mmc_init() | ||
162 | #ifdef HAVE_STORAGE_FLUSH | 218 | #ifdef HAVE_STORAGE_FLUSH |
163 | #define storage_flush() (void)0 | 219 | #define storage_flush() (void)0 |
164 | #endif | 220 | #endif |
@@ -177,14 +233,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; } | |||
177 | #elif (CONFIG_STORAGE & STORAGE_NAND) | 233 | #elif (CONFIG_STORAGE & STORAGE_NAND) |
178 | #define STORAGE_FUNCTION(NAME) (nand_## NAME) | 234 | #define STORAGE_FUNCTION(NAME) (nand_## NAME) |
179 | #define storage_spindown nand_spindown | 235 | #define storage_spindown nand_spindown |
180 | #define storage_sleep nand_sleep | ||
181 | #define storage_spin nand_spin | 236 | #define storage_spin nand_spin |
182 | 237 | ||
183 | #define storage_enable(on) (void)0 | 238 | #define storage_enable(on) (void)0 |
184 | #define storage_sleepnow() nand_sleepnow() | 239 | #define storage_sleepnow() nand_sleepnow() |
185 | #define storage_disk_is_active() 0 | 240 | #define storage_disk_is_active() 0 |
186 | #define storage_soft_reset() (void)0 | 241 | #define storage_soft_reset() (void)0 |
187 | #define storage_init() nand_init() | ||
188 | #ifdef HAVE_STORAGE_FLUSH | 242 | #ifdef HAVE_STORAGE_FLUSH |
189 | #define storage_flush() nand_flush() | 243 | #define storage_flush() nand_flush() |
190 | #endif | 244 | #endif |
@@ -203,14 +257,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; } | |||
203 | #elif (CONFIG_STORAGE & STORAGE_RAMDISK) | 257 | #elif (CONFIG_STORAGE & STORAGE_RAMDISK) |
204 | #define STORAGE_FUNCTION(NAME) (ramdisk_## NAME) | 258 | #define STORAGE_FUNCTION(NAME) (ramdisk_## NAME) |
205 | #define storage_spindown ramdisk_spindown | 259 | #define storage_spindown ramdisk_spindown |
206 | #define storage_sleep ramdisk_sleep | ||
207 | #define storage_spin ramdisk_spin | 260 | #define storage_spin ramdisk_spin |
208 | 261 | ||
209 | #define storage_enable(on) (void)0 | 262 | #define storage_enable(on) (void)0 |
210 | #define storage_sleepnow() ramdisk_sleepnow() | 263 | #define storage_sleepnow() ramdisk_sleepnow() |
211 | #define storage_disk_is_active() 0 | 264 | #define storage_disk_is_active() 0 |
212 | #define storage_soft_reset() (void)0 | 265 | #define storage_soft_reset() (void)0 |
213 | #define storage_init() ramdisk_init() | ||
214 | #ifdef HAVE_STORAGE_FLUSH | 266 | #ifdef HAVE_STORAGE_FLUSH |
215 | #define storage_flush() (void)0 | 267 | #define storage_flush() (void)0 |
216 | #endif | 268 | #endif |
@@ -234,11 +286,9 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; } | |||
234 | /* Multi-driver use normal functions */ | 286 | /* Multi-driver use normal functions */ |
235 | 287 | ||
236 | void storage_enable(bool on); | 288 | void storage_enable(bool on); |
237 | void storage_sleep(void); | ||
238 | void storage_sleepnow(void); | 289 | void storage_sleepnow(void); |
239 | bool storage_disk_is_active(void); | 290 | bool storage_disk_is_active(void); |
240 | int storage_soft_reset(void); | 291 | int storage_soft_reset(void); |
241 | int storage_init(void) STORAGE_INIT_ATTR; | ||
242 | int storage_flush(void); | 292 | int storage_flush(void); |
243 | void storage_spin(void); | 293 | void storage_spin(void); |
244 | void storage_spindown(int seconds); | 294 | void storage_spindown(int seconds); |
diff --git a/firmware/storage.c b/firmware/storage.c index e9a3396f30..790cddcd1a 100644 --- a/firmware/storage.c +++ b/firmware/storage.c | |||
@@ -20,6 +20,9 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "storage.h" | 21 | #include "storage.h" |
22 | #include "kernel.h" | 22 | #include "kernel.h" |
23 | #include "ata_idle_notify.h" | ||
24 | #include "usb.h" | ||
25 | #include "disk.h" | ||
23 | 26 | ||
24 | #ifdef CONFIG_STORAGE_MULTI | 27 | #ifdef CONFIG_STORAGE_MULTI |
25 | 28 | ||
@@ -31,118 +34,243 @@ | |||
31 | 34 | ||
32 | static unsigned int storage_drivers[NUM_DRIVES]; | 35 | static unsigned int storage_drivers[NUM_DRIVES]; |
33 | static unsigned int num_drives; | 36 | static unsigned int num_drives; |
37 | #endif /* CONFIG_STORAGE_MULTI */ | ||
38 | |||
39 | /* defaults: override elsewhere target-wise if they must be different */ | ||
40 | #if (CONFIG_STORAGE & STORAGE_ATA) | ||
41 | #ifndef ATA_THREAD_STACK_SIZE | ||
42 | #define ATA_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2) | ||
43 | #endif | ||
44 | #endif | ||
45 | #if (CONFIG_STORAGE & STORAGE_MMC) | ||
46 | #ifndef MMC_THREAD_STACK_SIZE | ||
47 | #define MMC_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2) | ||
48 | #endif | ||
49 | #endif | ||
50 | #if (CONFIG_STORAGE & STORAGE_SD) | ||
51 | #ifndef SD_THREAD_STACK_SIZE | ||
52 | #define SD_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2) | ||
53 | #endif | ||
54 | #endif | ||
55 | #if (CONFIG_STORAGE & STORAGE_NAND) | ||
56 | #ifndef NAND_THREAD_STACK_SIZE | ||
57 | #define NAND_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2) | ||
58 | #endif | ||
59 | #endif | ||
60 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | ||
61 | #ifndef RAMDISK_THREAD_STACK_SIZE | ||
62 | #define RAMDISK_THREAD_STACK_SIZE (0) /* not used on its own */ | ||
63 | #endif | ||
34 | #endif | 64 | #endif |
35 | 65 | ||
36 | int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count, | 66 | static struct event_queue storage_queue SHAREDBSS_ATTR; |
37 | void* buf) | 67 | static unsigned int storage_thread_id = 0; |
38 | { | ||
39 | #ifdef CONFIG_STORAGE_MULTI | ||
40 | int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; | ||
41 | int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET; | ||
42 | 68 | ||
43 | switch (driver) | 69 | static union { |
44 | { | ||
45 | #if (CONFIG_STORAGE & STORAGE_ATA) | 70 | #if (CONFIG_STORAGE & STORAGE_ATA) |
46 | case STORAGE_ATA: | 71 | long stk_ata[ATA_THREAD_STACK_SIZE / sizeof (long)]; |
47 | return ata_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
48 | #endif | 72 | #endif |
49 | |||
50 | #if (CONFIG_STORAGE & STORAGE_MMC) | 73 | #if (CONFIG_STORAGE & STORAGE_MMC) |
51 | case STORAGE_MMC: | 74 | long stk_mmc[MMC_THREAD_STACK_SIZE / sizeof (long)]; |
52 | return mmc_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
53 | #endif | 75 | #endif |
54 | |||
55 | #if (CONFIG_STORAGE & STORAGE_SD) | 76 | #if (CONFIG_STORAGE & STORAGE_SD) |
56 | case STORAGE_SD: | 77 | long stk_sd[SD_THREAD_STACK_SIZE / sizeof (long)]; |
57 | return sd_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
58 | #endif | 78 | #endif |
59 | |||
60 | #if (CONFIG_STORAGE & STORAGE_NAND) | 79 | #if (CONFIG_STORAGE & STORAGE_NAND) |
61 | case STORAGE_NAND: | 80 | long stk_nand[NAND_THREAD_STACK_SIZE / sizeof (long)]; |
62 | return nand_read_sectors(IF_MD(ldrive,) start,count,buf); | 81 | #endif |
82 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | ||
83 | long stk_ramdisk[RAMDISK_THREAD_STACK_SIZE / sizeof (long)]; | ||
63 | #endif | 84 | #endif |
85 | } storage_thread_stack; | ||
64 | 86 | ||
87 | static const char storage_thread_name[] = | ||
88 | #if (CONFIG_STORAGE & STORAGE_ATA) | ||
89 | "/ata" | ||
90 | #endif | ||
91 | #if (CONFIG_STORAGE & STORAGE_MMC) | ||
92 | "/mmc" | ||
93 | #endif | ||
94 | #if (CONFIG_STORAGE & STORAGE_SD) | ||
95 | "/sd" | ||
96 | #endif | ||
97 | #if (CONFIG_STORAGE & STORAGE_NAND) | ||
98 | "/nand" | ||
99 | #endif | ||
65 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | 100 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) |
66 | case STORAGE_RAMDISK: | 101 | "/ramdisk" |
67 | return ramdisk_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
68 | #endif | 102 | #endif |
69 | } | 103 | ; |
70 | |||
71 | return -1; | ||
72 | #else /* CONFIG_STORAGE_MULTI */ | ||
73 | return STORAGE_FUNCTION(read_sectors)(IF_MD(drive,)start,count,buf); | ||
74 | #endif /* CONFIG_STORAGE_MULTI */ | ||
75 | 104 | ||
76 | } | 105 | /* event is targeted to a specific drive */ |
106 | #define DRIVE_EVT (1 << STORAGE_NUM_TYPES) | ||
77 | 107 | ||
78 | int storage_write_sectors(IF_MD(int drive,) unsigned long start, int count, | ||
79 | const void* buf) | ||
80 | { | ||
81 | #ifdef CONFIG_STORAGE_MULTI | 108 | #ifdef CONFIG_STORAGE_MULTI |
82 | int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; | 109 | static int storage_event_send(unsigned int route, long id, intptr_t data) |
83 | int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET; | 110 | { |
84 | 111 | /* most events go to everyone */ | |
85 | switch (driver) | 112 | if (UNLIKELY(route == DRIVE_EVT)) { |
86 | { | 113 | route = (storage_drivers[data] & DRIVER_MASK) >> DRIVER_OFFSET; |
114 | data = (storage_drivers[data] & DRIVE_MASK) >> DRIVE_OFFSET; | ||
115 | } | ||
116 | |||
117 | int rc = 0; | ||
118 | |||
87 | #if (CONFIG_STORAGE & STORAGE_ATA) | 119 | #if (CONFIG_STORAGE & STORAGE_ATA) |
88 | case STORAGE_ATA: | 120 | if (route & STORAGE_ATA) { |
89 | return ata_write_sectors(IF_MD(ldrive,)start,count,buf); | 121 | rc = ata_event(id, data); |
122 | } | ||
90 | #endif | 123 | #endif |
91 | |||
92 | #if (CONFIG_STORAGE & STORAGE_MMC) | 124 | #if (CONFIG_STORAGE & STORAGE_MMC) |
93 | case STORAGE_MMC: | 125 | if (route & STORAGE_MMC) { |
94 | return mmc_write_sectors(IF_MD(ldrive,)start,count,buf); | 126 | rc = mmc_event(id, data); |
127 | } | ||
95 | #endif | 128 | #endif |
96 | |||
97 | #if (CONFIG_STORAGE & STORAGE_SD) | 129 | #if (CONFIG_STORAGE & STORAGE_SD) |
98 | case STORAGE_SD: | 130 | if (route & STORAGE_SD) { |
99 | return sd_write_sectors(IF_MD(ldrive,)start,count,buf); | 131 | rc = sd_event(id, data); |
132 | } | ||
100 | #endif | 133 | #endif |
101 | |||
102 | #if (CONFIG_STORAGE & STORAGE_NAND) | 134 | #if (CONFIG_STORAGE & STORAGE_NAND) |
103 | case STORAGE_NAND: | 135 | if (route & STORAGE_NAND) { |
104 | return nand_write_sectors(IF_MD(ldrive,)start,count,buf); | 136 | rc = nand_event(id, data); |
137 | } | ||
105 | #endif | 138 | #endif |
106 | |||
107 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | 139 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) |
108 | case STORAGE_RAMDISK: | 140 | if (route & STORAGE_RAMDISK) { |
109 | return ramdisk_write_sectors(IF_MD(ldrive,)start,count,buf); | 141 | rc = ramdisk_event(id, data); |
110 | #endif | ||
111 | } | 142 | } |
112 | 143 | #endif | |
113 | return -1; | 144 | |
114 | #else /* CONFIG_STORAGE_MULTI */ | 145 | return rc; |
115 | return STORAGE_FUNCTION(write_sectors)(IF_MD(drive,)start,count,buf); | 146 | } |
116 | #endif /* CONFIG_STORAGE_MULTI */ | 147 | #endif /* CONFIG_STORAGE_MULTI */ |
148 | |||
149 | #ifndef CONFIG_STORAGE_MULTI | ||
150 | static FORCE_INLINE int storage_event_send(unsigned int route, long id, | ||
151 | intptr_t data) | ||
152 | { | ||
153 | return route ? STORAGE_FUNCTION(event)(id, data) : 0; | ||
117 | } | 154 | } |
155 | #endif /* ndef CONFIG_STORAGE_MULTI */ | ||
118 | 156 | ||
119 | #ifdef CONFIG_STORAGE_MULTI | 157 | static void NORETURN_ATTR storage_thread(void) |
158 | { | ||
159 | unsigned int bdcast = CONFIG_STORAGE; | ||
160 | bool usb_mode = false; | ||
161 | struct queue_event ev; | ||
120 | 162 | ||
121 | #define DRIVER_MASK 0xff000000 | 163 | while (1) |
122 | #define DRIVER_OFFSET 24 | 164 | { |
123 | #define DRIVE_MASK 0x00ff0000 | 165 | queue_wait_w_tmo(&storage_queue, &ev, HZ/2); |
124 | #define DRIVE_OFFSET 16 | 166 | |
125 | #define PARTITION_MASK 0x0000ff00 | 167 | switch (ev.id) |
168 | { | ||
169 | case SYS_TIMEOUT:; | ||
170 | /* drivers hold their bit low when they want to | ||
171 | sleep and keep it high otherwise */ | ||
172 | unsigned int trig = 0; | ||
173 | storage_event_send(bdcast, Q_STORAGE_TICK, (intptr_t)&trig); | ||
174 | trig = bdcast & ~trig; | ||
175 | if (trig) { | ||
176 | if (!usb_mode) { | ||
177 | call_storage_idle_notifys(false); | ||
178 | } | ||
179 | storage_event_send(trig, Q_STORAGE_SLEEPNOW, 0); | ||
180 | } | ||
181 | break; | ||
126 | 182 | ||
127 | static unsigned int storage_drivers[NUM_DRIVES]; | 183 | #if (CONFIG_STORAGE & STORAGE_ATA) |
128 | static unsigned int num_drives; | 184 | case Q_STORAGE_SLEEP: |
185 | storage_event_send(bdcast, ev.id, 0); | ||
186 | break; | ||
187 | #endif | ||
129 | 188 | ||
130 | int storage_num_drives(void) | 189 | #ifdef STORAGE_CLOSE |
190 | case Q_STORAGE_CLOSE: | ||
191 | storage_event_send(CONFIG_STORAGE, ev.id, 0); | ||
192 | thread_exit(); | ||
193 | #endif /* STORAGE_CLOSE */ | ||
194 | |||
195 | #ifdef HAVE_HOTSWAP | ||
196 | case SYS_HOTSWAP_INSERTED: | ||
197 | case SYS_HOTSWAP_EXTRACTED: | ||
198 | if (!usb_mode) { | ||
199 | int drive = IF_MD_DRV(ev.data); | ||
200 | if (!CHECK_DRV(drive)) { | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | int umnt = disk_unmount(drive); | ||
205 | int mnt = 0; | ||
206 | int rci = storage_event_send(DRIVE_EVT, ev.id, drive); | ||
207 | |||
208 | if (ev.id == SYS_HOTSWAP_INSERTED && !rci) { | ||
209 | mnt = disk_mount(drive); | ||
210 | } | ||
211 | |||
212 | if (umnt > 0 || mnt > 0) { | ||
213 | /* something was unmounted and/or mounted */ | ||
214 | queue_broadcast(SYS_FS_CHANGED, drive); | ||
215 | } | ||
216 | } | ||
217 | break; | ||
218 | #endif /* HAVE_HOTSWAP */ | ||
219 | |||
220 | #ifndef USB_NONE | ||
221 | case SYS_USB_CONNECTED: | ||
222 | case SYS_USB_DISCONNECTED: | ||
223 | bdcast = 0; | ||
224 | storage_event_send(CONFIG_STORAGE, ev.id, (intptr_t)&bdcast); | ||
225 | usb_mode = ev.id == SYS_USB_CONNECTED; | ||
226 | if (usb_mode) { | ||
227 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
228 | } | ||
229 | else { | ||
230 | bdcast = CONFIG_STORAGE; | ||
231 | } | ||
232 | break; | ||
233 | #endif /* ndef USB_NONE */ | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | #if (CONFIG_STORAGE & STORAGE_ATA) | ||
239 | void storage_sleep(void) | ||
131 | { | 240 | { |
132 | return num_drives; | 241 | if (storage_thread_id) { |
242 | queue_post(&storage_queue, Q_STORAGE_SLEEP, 0); | ||
243 | } | ||
133 | } | 244 | } |
245 | #endif /* (CONFIG_STORAGE & STORAGE_ATA) */ | ||
134 | 246 | ||
135 | int storage_driver_type(int drive) | 247 | #ifdef STORAGE_CLOSE |
248 | void storage_close(void) | ||
136 | { | 249 | { |
137 | if ((unsigned int)drive >= num_drives) | 250 | if (storage_thread_id) { |
138 | return -1; | 251 | queue_post(&storage_queue, Q_STORAGE_CLOSE, 0); |
252 | thread_wait(storage_thread_id); | ||
253 | } | ||
254 | } | ||
255 | #endif /* STORAGE_CLOSE */ | ||
139 | 256 | ||
140 | unsigned int bit = (storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; | 257 | static inline void storage_thread_init(void) |
141 | return bit ? find_first_set_bit(bit) : -1; | 258 | { |
259 | if (storage_thread_id) { | ||
260 | return; | ||
261 | } | ||
262 | |||
263 | queue_init(&storage_queue, true); | ||
264 | storage_thread_id = create_thread(storage_thread, &storage_thread_stack, | ||
265 | sizeof (storage_thread_stack), | ||
266 | 0, &storage_thread_name[1] | ||
267 | IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
268 | IF_COP(, CPU)); | ||
142 | } | 269 | } |
143 | 270 | ||
144 | int storage_init(void) | 271 | int storage_init(void) |
145 | { | 272 | { |
273 | #ifdef CONFIG_STORAGE_MULTI | ||
146 | int rc=0; | 274 | int rc=0; |
147 | int i; | 275 | int i; |
148 | num_drives=0; | 276 | num_drives=0; |
@@ -201,54 +329,142 @@ int storage_init(void) | |||
201 | (STORAGE_RAMDISK<<DRIVER_OFFSET) | (i << DRIVE_OFFSET); | 329 | (STORAGE_RAMDISK<<DRIVER_OFFSET) | (i << DRIVE_OFFSET); |
202 | } | 330 | } |
203 | #endif | 331 | #endif |
332 | #else /* ndef CONFIG_STORAGE_MULTI */ | ||
333 | STORAGE_FUNCTION(init)(); | ||
334 | #endif /* CONFIG_STORAGE_MULTI */ | ||
204 | 335 | ||
336 | storage_thread_init(); | ||
205 | return 0; | 337 | return 0; |
206 | } | 338 | } |
207 | 339 | ||
340 | int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count, | ||
341 | void* buf) | ||
342 | { | ||
343 | #ifdef CONFIG_STORAGE_MULTI | ||
344 | int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; | ||
345 | int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET; | ||
208 | 346 | ||
209 | void storage_enable(bool on) | 347 | switch (driver) |
348 | { | ||
349 | #if (CONFIG_STORAGE & STORAGE_ATA) | ||
350 | case STORAGE_ATA: | ||
351 | return ata_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
352 | #endif | ||
353 | |||
354 | #if (CONFIG_STORAGE & STORAGE_MMC) | ||
355 | case STORAGE_MMC: | ||
356 | return mmc_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
357 | #endif | ||
358 | |||
359 | #if (CONFIG_STORAGE & STORAGE_SD) | ||
360 | case STORAGE_SD: | ||
361 | return sd_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
362 | #endif | ||
363 | |||
364 | #if (CONFIG_STORAGE & STORAGE_NAND) | ||
365 | case STORAGE_NAND: | ||
366 | return nand_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
367 | #endif | ||
368 | |||
369 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | ||
370 | case STORAGE_RAMDISK: | ||
371 | return ramdisk_read_sectors(IF_MD(ldrive,) start,count,buf); | ||
372 | #endif | ||
373 | } | ||
374 | |||
375 | return -1; | ||
376 | #else /* CONFIG_STORAGE_MULTI */ | ||
377 | return STORAGE_FUNCTION(read_sectors)(IF_MD(drive,)start,count,buf); | ||
378 | #endif /* CONFIG_STORAGE_MULTI */ | ||
379 | |||
380 | } | ||
381 | |||
382 | int storage_write_sectors(IF_MD(int drive,) unsigned long start, int count, | ||
383 | const void* buf) | ||
210 | { | 384 | { |
385 | #ifdef CONFIG_STORAGE_MULTI | ||
386 | int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; | ||
387 | int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET; | ||
388 | |||
389 | switch (driver) | ||
390 | { | ||
211 | #if (CONFIG_STORAGE & STORAGE_ATA) | 391 | #if (CONFIG_STORAGE & STORAGE_ATA) |
212 | ata_enable(on); | 392 | case STORAGE_ATA: |
393 | return ata_write_sectors(IF_MD(ldrive,)start,count,buf); | ||
213 | #endif | 394 | #endif |
214 | 395 | ||
215 | #if (CONFIG_STORAGE & STORAGE_MMC) | 396 | #if (CONFIG_STORAGE & STORAGE_MMC) |
216 | mmc_enable(on); | 397 | case STORAGE_MMC: |
398 | return mmc_write_sectors(IF_MD(ldrive,)start,count,buf); | ||
217 | #endif | 399 | #endif |
218 | 400 | ||
219 | #if (CONFIG_STORAGE & STORAGE_SD) | 401 | #if (CONFIG_STORAGE & STORAGE_SD) |
220 | sd_enable(on); | 402 | case STORAGE_SD: |
403 | return sd_write_sectors(IF_MD(ldrive,)start,count,buf); | ||
221 | #endif | 404 | #endif |
222 | 405 | ||
223 | #if (CONFIG_STORAGE & STORAGE_NAND) | 406 | #if (CONFIG_STORAGE & STORAGE_NAND) |
224 | nand_enable(on); | 407 | case STORAGE_NAND: |
408 | return nand_write_sectors(IF_MD(ldrive,)start,count,buf); | ||
225 | #endif | 409 | #endif |
226 | 410 | ||
227 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | 411 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) |
228 | ramdisk_enable(on); | 412 | case STORAGE_RAMDISK: |
413 | return ramdisk_write_sectors(IF_MD(ldrive,)start,count,buf); | ||
229 | #endif | 414 | #endif |
415 | } | ||
416 | |||
417 | return -1; | ||
418 | #else /* CONFIG_STORAGE_MULTI */ | ||
419 | return STORAGE_FUNCTION(write_sectors)(IF_MD(drive,)start,count,buf); | ||
420 | #endif /* CONFIG_STORAGE_MULTI */ | ||
230 | } | 421 | } |
231 | 422 | ||
232 | void storage_sleep(void) | 423 | #ifdef CONFIG_STORAGE_MULTI |
424 | |||
425 | #define DRIVER_MASK 0xff000000 | ||
426 | #define DRIVER_OFFSET 24 | ||
427 | #define DRIVE_MASK 0x00ff0000 | ||
428 | #define DRIVE_OFFSET 16 | ||
429 | #define PARTITION_MASK 0x0000ff00 | ||
430 | |||
431 | static unsigned int storage_drivers[NUM_DRIVES]; | ||
432 | static unsigned int num_drives; | ||
433 | |||
434 | int storage_num_drives(void) | ||
435 | { | ||
436 | return num_drives; | ||
437 | } | ||
438 | |||
439 | int storage_driver_type(int drive) | ||
440 | { | ||
441 | if ((unsigned int)drive >= num_drives) | ||
442 | return -1; | ||
443 | |||
444 | unsigned int bit = (storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; | ||
445 | return bit ? find_first_set_bit(bit) : -1; | ||
446 | } | ||
447 | |||
448 | void storage_enable(bool on) | ||
233 | { | 449 | { |
234 | #if (CONFIG_STORAGE & STORAGE_ATA) | 450 | #if (CONFIG_STORAGE & STORAGE_ATA) |
235 | ata_sleep(); | 451 | ata_enable(on); |
236 | #endif | 452 | #endif |
237 | 453 | ||
238 | #if (CONFIG_STORAGE & STORAGE_MMC) | 454 | #if (CONFIG_STORAGE & STORAGE_MMC) |
239 | mmc_sleep(); | 455 | mmc_enable(on); |
240 | #endif | 456 | #endif |
241 | 457 | ||
242 | #if (CONFIG_STORAGE & STORAGE_SD) | 458 | #if (CONFIG_STORAGE & STORAGE_SD) |
243 | sd_sleep(); | 459 | sd_enable(on); |
244 | #endif | 460 | #endif |
245 | 461 | ||
246 | #if (CONFIG_STORAGE & STORAGE_NAND) | 462 | #if (CONFIG_STORAGE & STORAGE_NAND) |
247 | nand_sleep(); | 463 | nand_enable(on); |
248 | #endif | 464 | #endif |
249 | 465 | ||
250 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) | 466 | #if (CONFIG_STORAGE & STORAGE_RAMDISK) |
251 | ramdisk_sleep(); | 467 | ramdisk_enable(on); |
252 | #endif | 468 | #endif |
253 | } | 469 | } |
254 | 470 | ||
@@ -603,6 +819,5 @@ bool storage_present(int drive) | |||
603 | return false; | 819 | return false; |
604 | } | 820 | } |
605 | } | 821 | } |
606 | #endif | 822 | #endif /* HAVE_HOTSWAP */ |
607 | |||
608 | #endif /*CONFIG_STORAGE_MULTI*/ | 823 | #endif /*CONFIG_STORAGE_MULTI*/ |
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c index e65a7525b6..d6c6654319 100644 --- a/firmware/target/arm/as3525/sd-as3525.c +++ b/firmware/target/arm/as3525/sd-as3525.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include "config.h" /* for HAVE_MULTIDRIVE & AMS_OF_SIZE */ | 25 | #include "config.h" /* for HAVE_MULTIDRIVE & AMS_OF_SIZE */ |
26 | #include "fs_defines.h" | 26 | #include "fs_defines.h" |
27 | #include "thread.h" | ||
28 | #include "led.h" | 27 | #include "led.h" |
29 | #include "sdmmc.h" | 28 | #include "sdmmc.h" |
30 | #include "system.h" | 29 | #include "system.h" |
@@ -39,20 +38,15 @@ | |||
39 | #include "dma-target.h" /* DMA request lines */ | 38 | #include "dma-target.h" /* DMA request lines */ |
40 | #include "clock-target.h" | 39 | #include "clock-target.h" |
41 | #include "panic.h" | 40 | #include "panic.h" |
41 | #include "storage.h" | ||
42 | |||
42 | #ifdef HAVE_BUTTON_LIGHT | 43 | #ifdef HAVE_BUTTON_LIGHT |
43 | #include "backlight-target.h" | 44 | #include "backlight-target.h" |
44 | #endif | 45 | #endif |
45 | #include "stdbool.h" | 46 | |
46 | #include "ata_idle_notify.h" | ||
47 | #include "sd.h" | ||
48 | #include "usb.h" | ||
49 | /*#define LOGF_ENABLE*/ | 47 | /*#define LOGF_ENABLE*/ |
50 | #include "logf.h" | 48 | #include "logf.h" |
51 | 49 | ||
52 | #ifdef HAVE_HOTSWAP | ||
53 | #include "disk.h" | ||
54 | #endif | ||
55 | |||
56 | //#define VERIFY_WRITE 1 | 50 | //#define VERIFY_WRITE 1 |
57 | 51 | ||
58 | /* command flags */ | 52 | /* command flags */ |
@@ -119,16 +113,19 @@ static tCardInfo card_info[NUM_DRIVES]; | |||
119 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ | 113 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ |
120 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ | 114 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ |
121 | 115 | ||
116 | #ifdef CONFIG_STORAGE_MULTI | ||
117 | static int sd_first_drive = 0; | ||
118 | #else | ||
119 | #define sd_first_drive 0 | ||
120 | #endif | ||
121 | |||
122 | /* for compatibility */ | 122 | /* for compatibility */ |
123 | static long last_disk_activity = -1; | 123 | static long last_disk_activity = -1; |
124 | 124 | ||
125 | #define MIN_YIELD_PERIOD 5 /* ticks */ | 125 | #define MIN_YIELD_PERIOD 5 /* ticks */ |
126 | static long next_yield = 0; | 126 | static long next_yield = 0; |
127 | 127 | ||
128 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | 128 | static struct mutex sd_mtx; |
129 | static const char sd_thread_name[] = "ata/sd"; | ||
130 | static struct mutex sd_mtx; | ||
131 | static struct event_queue sd_queue; | ||
132 | bool sd_enabled = false; | 129 | bool sd_enabled = false; |
133 | 130 | ||
134 | #if defined(HAVE_MULTIDRIVE) | 131 | #if defined(HAVE_MULTIDRIVE) |
@@ -147,6 +144,59 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0]) | |||
147 | 144 | ||
148 | static inline void mci_delay(void) { udelay(1000) ; } | 145 | static inline void mci_delay(void) { udelay(1000) ; } |
149 | 146 | ||
147 | static void enable_controller(bool on) | ||
148 | { | ||
149 | |||
150 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
151 | extern int buttonlight_is_on; | ||
152 | #endif | ||
153 | |||
154 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
155 | static bool cpu_boosted = false; | ||
156 | #endif | ||
157 | |||
158 | if (sd_enabled == on) | ||
159 | return; /* nothing to do */ | ||
160 | |||
161 | sd_enabled = on; | ||
162 | |||
163 | if(on) | ||
164 | { | ||
165 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
166 | /* buttonlight AMSes need a bit of special handling for the buttonlight | ||
167 | * here due to the dual mapping of GPIOD and XPD */ | ||
168 | bitmod32(&CCU_IO, 1<<2, 3<<2); /* XPD is SD-MCI interface (b3:2 = 01) */ | ||
169 | if (buttonlight_is_on) | ||
170 | GPIOD_DIR &= ~(1<<7); | ||
171 | else | ||
172 | buttonlight_hw_off(); | ||
173 | #endif | ||
174 | |||
175 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
176 | if(card_detect_target()) /* If SD card present Boost cpu for voltage */ | ||
177 | { | ||
178 | cpu_boosted = true; | ||
179 | cpu_boost(true); | ||
180 | } | ||
181 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
186 | if(cpu_boosted) | ||
187 | { | ||
188 | cpu_boost(false); | ||
189 | cpu_boosted = false; | ||
190 | } | ||
191 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
192 | |||
193 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
194 | bitmod32(&CCU_IO, 0<<2, 3<<2); /* XPD is general purpose IO (b3:2 = 00) */ | ||
195 | if (buttonlight_is_on) | ||
196 | buttonlight_hw_on(); | ||
197 | #endif | ||
198 | } | ||
199 | } | ||
150 | 200 | ||
151 | static inline bool card_detect_target(void) | 201 | static inline bool card_detect_target(void) |
152 | { | 202 | { |
@@ -161,18 +211,13 @@ static inline bool card_detect_target(void) | |||
161 | #ifdef HAVE_HOTSWAP | 211 | #ifdef HAVE_HOTSWAP |
162 | static int sd1_oneshot_callback(struct timeout *tmo) | 212 | static int sd1_oneshot_callback(struct timeout *tmo) |
163 | { | 213 | { |
164 | (void)tmo; | ||
165 | |||
166 | /* This is called only if the state was stable for 300ms - check state | 214 | /* This is called only if the state was stable for 300ms - check state |
167 | * and post appropriate event. */ | 215 | * and post appropriate event. */ |
168 | if (card_detect_target()) | 216 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
169 | { | 217 | SYS_HOTSWAP_EXTRACTED, |
170 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 218 | sd_first_drive + SD_SLOT_AS3525); |
171 | } | ||
172 | else | ||
173 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
174 | |||
175 | return 0; | 219 | return 0; |
220 | (void)tmo; | ||
176 | } | 221 | } |
177 | 222 | ||
178 | void sd_gpioa_isr(void) | 223 | void sd_gpioa_isr(void) |
@@ -435,87 +480,6 @@ static int sd_init_card(const int drive) | |||
435 | return 0; | 480 | return 0; |
436 | } | 481 | } |
437 | 482 | ||
438 | static void sd_thread(void) NORETURN_ATTR; | ||
439 | static void sd_thread(void) | ||
440 | { | ||
441 | struct queue_event ev; | ||
442 | bool idle_notified = false; | ||
443 | |||
444 | while (1) | ||
445 | { | ||
446 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
447 | |||
448 | switch ( ev.id ) | ||
449 | { | ||
450 | #ifdef HAVE_HOTSWAP | ||
451 | case SYS_HOTSWAP_INSERTED: | ||
452 | case SYS_HOTSWAP_EXTRACTED:; | ||
453 | int success = 1; | ||
454 | |||
455 | disk_unmount(SD_SLOT_AS3525); /* release "by force" */ | ||
456 | |||
457 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
458 | |||
459 | /* Force card init for new card, re-init for re-inserted one or | ||
460 | * clear if the last attempt to init failed with an error. */ | ||
461 | card_info[SD_SLOT_AS3525].initialized = 0; | ||
462 | |||
463 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
464 | { | ||
465 | success = 0; | ||
466 | sd_enable(true); | ||
467 | init_pl180_controller(SD_SLOT_AS3525); | ||
468 | int rc = sd_init_card(SD_SLOT_AS3525); | ||
469 | sd_enable(false); | ||
470 | if (rc >= 0) | ||
471 | success = 2; | ||
472 | else /* initialisation failed */ | ||
473 | panicf("microSD init failed : %d", rc); | ||
474 | } | ||
475 | |||
476 | mutex_unlock(&sd_mtx); | ||
477 | |||
478 | if (success > 1) | ||
479 | success = disk_mount(SD_SLOT_AS3525); /* 0 if fail */ | ||
480 | |||
481 | /* | ||
482 | * Mount succeeded, or this was an EXTRACTED event, | ||
483 | * in both cases notify the system about the changed filesystems | ||
484 | */ | ||
485 | if (success) | ||
486 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
487 | |||
488 | break; | ||
489 | #endif /* HAVE_HOTSWAP */ | ||
490 | |||
491 | case SYS_TIMEOUT: | ||
492 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
493 | { | ||
494 | idle_notified = false; | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | /* never let a timer wrap confuse us */ | ||
499 | next_yield = current_tick; | ||
500 | |||
501 | if (!idle_notified) | ||
502 | { | ||
503 | call_storage_idle_notifys(false); | ||
504 | idle_notified = true; | ||
505 | } | ||
506 | } | ||
507 | break; | ||
508 | |||
509 | case SYS_USB_CONNECTED: | ||
510 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
511 | /* Wait until the USB cable is extracted again */ | ||
512 | usb_wait_for_disconnect(&sd_queue); | ||
513 | |||
514 | break; | ||
515 | } | ||
516 | } | ||
517 | } | ||
518 | |||
519 | static void init_pl180_controller(const int drive) | 483 | static void init_pl180_controller(const int drive) |
520 | { | 484 | { |
521 | MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0; | 485 | MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0; |
@@ -576,12 +540,8 @@ int sd_init(void) | |||
576 | /* init mutex */ | 540 | /* init mutex */ |
577 | mutex_init(&sd_mtx); | 541 | mutex_init(&sd_mtx); |
578 | 542 | ||
579 | queue_init(&sd_queue, true); | 543 | sd_enabled = true; /* force action on next call */ |
580 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | 544 | enable_controller(false); |
581 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
582 | |||
583 | sd_enabled = true; | ||
584 | sd_enable(false); | ||
585 | 545 | ||
586 | return 0; | 546 | return 0; |
587 | } | 547 | } |
@@ -698,7 +658,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
698 | unsigned long response; | 658 | unsigned long response; |
699 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); | 659 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); |
700 | 660 | ||
701 | sd_enable(true); | 661 | enable_controller(true); |
702 | led(true); | 662 | led(true); |
703 | 663 | ||
704 | if (card_info[drive].initialized <= 0) | 664 | if (card_info[drive].initialized <= 0) |
@@ -873,7 +833,7 @@ sd_transfer_error: | |||
873 | sd_transfer_error_nodma: | 833 | sd_transfer_error_nodma: |
874 | 834 | ||
875 | led(false); | 835 | led(false); |
876 | sd_enable(false); | 836 | enable_controller(false); |
877 | 837 | ||
878 | if (ret) /* error */ | 838 | if (ret) /* error */ |
879 | card_info[drive].initialized = 0; | 839 | card_info[drive].initialized = 0; |
@@ -947,55 +907,9 @@ long sd_last_disk_activity(void) | |||
947 | 907 | ||
948 | void sd_enable(bool on) | 908 | void sd_enable(bool on) |
949 | { | 909 | { |
950 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | 910 | mutex_lock(&sd_mtx); |
951 | extern int buttonlight_is_on; | 911 | enable_controller(on); |
952 | #endif | 912 | mutex_unlock(&sd_mtx); |
953 | |||
954 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
955 | static bool cpu_boosted = false; | ||
956 | #endif | ||
957 | |||
958 | if (sd_enabled == on) | ||
959 | return; /* nothing to do */ | ||
960 | |||
961 | sd_enabled = on; | ||
962 | |||
963 | if(on) | ||
964 | { | ||
965 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
966 | /* buttonlight AMSes need a bit of special handling for the buttonlight | ||
967 | * here due to the dual mapping of GPIOD and XPD */ | ||
968 | bitmod32(&CCU_IO, 1<<2, 3<<2); /* XPD is SD-MCI interface (b3:2 = 01) */ | ||
969 | if (buttonlight_is_on) | ||
970 | GPIOD_DIR &= ~(1<<7); | ||
971 | else | ||
972 | buttonlight_hw_off(); | ||
973 | #endif | ||
974 | |||
975 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
976 | if(card_detect_target()) /* If SD card present Boost cpu for voltage */ | ||
977 | { | ||
978 | cpu_boosted = true; | ||
979 | cpu_boost(true); | ||
980 | } | ||
981 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
982 | } | ||
983 | else | ||
984 | { | ||
985 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
986 | if(cpu_boosted) | ||
987 | { | ||
988 | cpu_boost(false); | ||
989 | cpu_boosted = false; | ||
990 | } | ||
991 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
992 | |||
993 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
994 | bitmod32(&CCU_IO, 0<<2, 3<<2); /* XPD is general purpose IO (b3:2 = 00) */ | ||
995 | if (buttonlight_is_on) | ||
996 | buttonlight_hw_on(); | ||
997 | #endif | ||
998 | } | ||
999 | } | 913 | } |
1000 | 914 | ||
1001 | tCardInfo *card_get_info_target(int card_no) | 915 | tCardInfo *card_get_info_target(int card_no) |
@@ -1006,9 +920,45 @@ tCardInfo *card_get_info_target(int card_no) | |||
1006 | #ifdef CONFIG_STORAGE_MULTI | 920 | #ifdef CONFIG_STORAGE_MULTI |
1007 | int sd_num_drives(int first_drive) | 921 | int sd_num_drives(int first_drive) |
1008 | { | 922 | { |
1009 | /* We don't care which logical drive number(s) we have been assigned */ | 923 | sd_first_drive = first_drive; |
1010 | (void)first_drive; | ||
1011 | |||
1012 | return NUM_DRIVES; | 924 | return NUM_DRIVES; |
1013 | } | 925 | } |
1014 | #endif /* CONFIG_STORAGE_MULTI */ | 926 | #endif /* CONFIG_STORAGE_MULTI */ |
927 | |||
928 | int sd_event(long id, intptr_t data) | ||
929 | { | ||
930 | int rc = 0; | ||
931 | |||
932 | switch (id) | ||
933 | { | ||
934 | #ifdef HAVE_HOTSWAP | ||
935 | case SYS_HOTSWAP_INSERTED: | ||
936 | case SYS_HOTSWAP_EXTRACTED: | ||
937 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
938 | |||
939 | /* Force card init for new card, re-init for re-inserted one or | ||
940 | * clear if the last attempt to init failed with an error. */ | ||
941 | card_info[data].initialized = 0; | ||
942 | |||
943 | if (id == SYS_HOTSWAP_INSERTED) | ||
944 | { | ||
945 | enable_controller(true); | ||
946 | init_pl180_controller(data); | ||
947 | rc = sd_init_card(data); | ||
948 | enable_controller(false); | ||
949 | } | ||
950 | |||
951 | mutex_unlock(&sd_mtx); | ||
952 | break; | ||
953 | #endif /* HAVE_HOTSWAP */ | ||
954 | case Q_STORAGE_TICK: | ||
955 | /* never let a timer wrap confuse us */ | ||
956 | next_yield = current_tick; | ||
957 | default: | ||
958 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
959 | STORAGE_SD); | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | return rc; | ||
964 | } | ||
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c index 3f39629e0b..f78345577c 100644 --- a/firmware/target/arm/as3525/sd-as3525v2.c +++ b/firmware/target/arm/as3525/sd-as3525v2.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include "config.h" /* for HAVE_MULTIVOLUME */ | 23 | #include "config.h" /* for HAVE_MULTIVOLUME */ |
24 | #include "fs_defines.h" | 24 | #include "fs_defines.h" |
25 | #include "thread.h" | ||
26 | #include "gcc_extensions.h" | 25 | #include "gcc_extensions.h" |
27 | #include "led.h" | 26 | #include "led.h" |
28 | #include "sdmmc.h" | 27 | #include "sdmmc.h" |
@@ -36,19 +35,7 @@ | |||
36 | #include "pl081.h" /* DMA controller */ | 35 | #include "pl081.h" /* DMA controller */ |
37 | #include "dma-target.h" /* DMA request lines */ | 36 | #include "dma-target.h" /* DMA request lines */ |
38 | #include "clock-target.h" | 37 | #include "clock-target.h" |
39 | #include "panic.h" | 38 | #include "storage.h" |
40 | #include "stdbool.h" | ||
41 | #include "ata_idle_notify.h" | ||
42 | #include "sd.h" | ||
43 | #include "usb.h" | ||
44 | |||
45 | #ifdef HAVE_HOTSWAP | ||
46 | #include "disk.h" | ||
47 | #endif | ||
48 | |||
49 | #include "lcd.h" | ||
50 | #include <stdarg.h> | ||
51 | #include "sysfont.h" | ||
52 | 39 | ||
53 | #define INTERNAL_AS3525 0 /* embedded SD card */ | 40 | #define INTERNAL_AS3525 0 /* embedded SD card */ |
54 | #define SD_SLOT_AS3525 1 /* SD slot if present */ | 41 | #define SD_SLOT_AS3525 1 /* SD slot if present */ |
@@ -327,13 +314,15 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0]) | |||
327 | 314 | ||
328 | static tCardInfo card_info[NUM_DRIVES]; | 315 | static tCardInfo card_info[NUM_DRIVES]; |
329 | 316 | ||
317 | #ifdef CONFIG_STORAGE_MULTI | ||
318 | static int sd_first_drive = 0; | ||
319 | #else | ||
320 | #define sd_first_drive 0 | ||
321 | #endif | ||
322 | |||
330 | /* for compatibility */ | 323 | /* for compatibility */ |
331 | static long last_disk_activity = -1; | 324 | static long last_disk_activity = -1; |
332 | |||
333 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
334 | static const char sd_thread_name[] = "ata/sd"; | ||
335 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 325 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
336 | static struct event_queue sd_queue; | ||
337 | #ifndef BOOTLOADER | 326 | #ifndef BOOTLOADER |
338 | bool sd_enabled = false; | 327 | bool sd_enabled = false; |
339 | #endif | 328 | #endif |
@@ -371,6 +360,22 @@ void INT_NAND(void) | |||
371 | MCI_CTRL |= INT_ENABLE; | 360 | MCI_CTRL |= INT_ENABLE; |
372 | } | 361 | } |
373 | 362 | ||
363 | #ifndef BOOTLOADER | ||
364 | static void enable_controller(bool on) | ||
365 | { | ||
366 | if (on) | ||
367 | { | ||
368 | bitset32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | ||
369 | CGU_SDSLOT |= (1<<7); /* interface enable */ | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | CGU_SDSLOT &= ~(1<<7); /* interface enable */ | ||
374 | bitclr32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | ||
375 | } | ||
376 | } | ||
377 | #endif /* BOOTLOADER */ | ||
378 | |||
374 | static inline bool card_detect_target(void) | 379 | static inline bool card_detect_target(void) |
375 | { | 380 | { |
376 | #if defined(HAVE_MULTIDRIVE) | 381 | #if defined(HAVE_MULTIDRIVE) |
@@ -577,75 +582,6 @@ static int sd_init_card(const int drive) | |||
577 | return 0; | 582 | return 0; |
578 | } | 583 | } |
579 | 584 | ||
580 | static void sd_thread(void) NORETURN_ATTR; | ||
581 | static void sd_thread(void) | ||
582 | { | ||
583 | struct queue_event ev; | ||
584 | bool idle_notified = false; | ||
585 | |||
586 | while (1) | ||
587 | { | ||
588 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
589 | |||
590 | switch ( ev.id ) | ||
591 | { | ||
592 | #ifdef HAVE_HOTSWAP | ||
593 | case SYS_HOTSWAP_INSERTED: | ||
594 | case SYS_HOTSWAP_EXTRACTED:; | ||
595 | int success = 1; | ||
596 | |||
597 | disk_unmount(SD_SLOT_AS3525); /* release "by force" */ | ||
598 | |||
599 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
600 | |||
601 | /* Force card init for new card, re-init for re-inserted one or | ||
602 | * clear if the last attempt to init failed with an error. */ | ||
603 | card_info[SD_SLOT_AS3525].initialized = 0; | ||
604 | |||
605 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
606 | { | ||
607 | sd_enable(true); | ||
608 | success = sd_init_card(SD_SLOT_AS3525) == 0 ? 2 : 0; | ||
609 | sd_enable(false); | ||
610 | } | ||
611 | |||
612 | mutex_unlock(&sd_mtx); | ||
613 | |||
614 | if (success > 1) | ||
615 | success = disk_mount(SD_SLOT_AS3525); /* 0 if fail */ | ||
616 | |||
617 | /* | ||
618 | * Mount succeeded, or this was an EXTRACTED event, | ||
619 | * in both cases notify the system about the changed filesystems | ||
620 | */ | ||
621 | if (success) | ||
622 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
623 | |||
624 | break; | ||
625 | #endif /* HAVE_HOTSWAP */ | ||
626 | |||
627 | case SYS_TIMEOUT: | ||
628 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
629 | { | ||
630 | idle_notified = false; | ||
631 | } | ||
632 | else if (!idle_notified) | ||
633 | { | ||
634 | call_storage_idle_notifys(false); | ||
635 | idle_notified = true; | ||
636 | } | ||
637 | break; | ||
638 | |||
639 | case SYS_USB_CONNECTED: | ||
640 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
641 | /* Wait until the USB cable is extracted again */ | ||
642 | usb_wait_for_disconnect(&sd_queue); | ||
643 | |||
644 | break; | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
649 | static void init_controller(void) | 585 | static void init_controller(void) |
650 | { | 586 | { |
651 | int hcon_numcards = ((MCI_HCON>>1) & 0x1F) + 1; | 587 | int hcon_numcards = ((MCI_HCON>>1) & 0x1F) + 1; |
@@ -706,6 +642,7 @@ int sd_init(void) | |||
706 | | (AS3525_SDSLOT_DIV << 2) | 642 | | (AS3525_SDSLOT_DIV << 2) |
707 | | 1; /* clock source = PLLA */ | 643 | | 1; /* clock source = PLLA */ |
708 | 644 | ||
645 | mutex_init(&sd_mtx); | ||
709 | semaphore_init(&transfer_completion_signal, 1, 0); | 646 | semaphore_init(&transfer_completion_signal, 1, 0); |
710 | semaphore_init(&command_completion_signal, 1, 0); | 647 | semaphore_init(&command_completion_signal, 1, 0); |
711 | 648 | ||
@@ -737,16 +674,9 @@ int sd_init(void) | |||
737 | if(ret < 0) | 674 | if(ret < 0) |
738 | return ret; | 675 | return ret; |
739 | 676 | ||
740 | /* init mutex */ | ||
741 | mutex_init(&sd_mtx); | ||
742 | |||
743 | queue_init(&sd_queue, true); | ||
744 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
745 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
746 | |||
747 | #ifndef BOOTLOADER | 677 | #ifndef BOOTLOADER |
748 | sd_enabled = true; | 678 | sd_enabled = true; |
749 | sd_enable(false); | 679 | enable_controller(false); |
750 | #endif | 680 | #endif |
751 | return 0; | 681 | return 0; |
752 | } | 682 | } |
@@ -767,7 +697,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
767 | 697 | ||
768 | mutex_lock(&sd_mtx); | 698 | mutex_lock(&sd_mtx); |
769 | #ifndef BOOTLOADER | 699 | #ifndef BOOTLOADER |
770 | sd_enable(true); | 700 | enable_controller(true); |
771 | led(true); | 701 | led(true); |
772 | #endif | 702 | #endif |
773 | 703 | ||
@@ -925,7 +855,7 @@ retry_with_reinit: | |||
925 | 855 | ||
926 | exit: | 856 | exit: |
927 | #ifndef BOOTLOADER | 857 | #ifndef BOOTLOADER |
928 | sd_enable(false); | 858 | enable_controller(false); |
929 | led(false); | 859 | led(false); |
930 | #endif | 860 | #endif |
931 | mutex_unlock(&sd_mtx); | 861 | mutex_unlock(&sd_mtx); |
@@ -952,16 +882,9 @@ long sd_last_disk_activity(void) | |||
952 | 882 | ||
953 | void sd_enable(bool on) | 883 | void sd_enable(bool on) |
954 | { | 884 | { |
955 | if (on) | 885 | mutex_lock(&sd_mtx); |
956 | { | 886 | enable_controller(on); |
957 | bitset32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | 887 | mutex_unlock(&sd_mtx); |
958 | CGU_SDSLOT |= (1<<7); /* interface enable */ | ||
959 | } | ||
960 | else | ||
961 | { | ||
962 | CGU_SDSLOT &= ~(1<<7); /* interface enable */ | ||
963 | bitclr32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | ||
964 | } | ||
965 | } | 888 | } |
966 | #endif /* BOOTLOADER */ | 889 | #endif /* BOOTLOADER */ |
967 | 890 | ||
@@ -983,18 +906,13 @@ bool sd_present(IF_MD_NONVOID(int drive)) | |||
983 | 906 | ||
984 | static int sd1_oneshot_callback(struct timeout *tmo) | 907 | static int sd1_oneshot_callback(struct timeout *tmo) |
985 | { | 908 | { |
986 | (void)tmo; | ||
987 | |||
988 | /* This is called only if the state was stable for 300ms - check state | 909 | /* This is called only if the state was stable for 300ms - check state |
989 | * and post appropriate event. */ | 910 | * and post appropriate event. */ |
990 | if (card_detect_target()) | 911 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
991 | { | 912 | SYS_HOTSWAP_EXTRACTED, |
992 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 913 | sd_first_drive + SD_SLOT_AS3525); |
993 | } | ||
994 | else | ||
995 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
996 | |||
997 | return 0; | 914 | return 0; |
915 | (void)tmo; | ||
998 | } | 916 | } |
999 | 917 | ||
1000 | void sd_gpioa_isr(void) | 918 | void sd_gpioa_isr(void) |
@@ -1012,9 +930,41 @@ void sd_gpioa_isr(void) | |||
1012 | #ifdef CONFIG_STORAGE_MULTI | 930 | #ifdef CONFIG_STORAGE_MULTI |
1013 | int sd_num_drives(int first_drive) | 931 | int sd_num_drives(int first_drive) |
1014 | { | 932 | { |
1015 | /* We don't care which logical drive number(s) we have been assigned */ | 933 | sd_first_drive = first_drive; |
1016 | (void)first_drive; | ||
1017 | |||
1018 | return NUM_DRIVES; | 934 | return NUM_DRIVES; |
1019 | } | 935 | } |
1020 | #endif /* CONFIG_STORAGE_MULTI */ | 936 | #endif /* CONFIG_STORAGE_MULTI */ |
937 | |||
938 | int sd_event(long id, intptr_t data) | ||
939 | { | ||
940 | int rc = 0; | ||
941 | |||
942 | switch (id) | ||
943 | { | ||
944 | #ifdef HAVE_HOTSWAP | ||
945 | case SYS_HOTSWAP_INSERTED: | ||
946 | case SYS_HOTSWAP_EXTRACTED: | ||
947 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
948 | |||
949 | /* Force card init for new card, re-init for re-inserted one or | ||
950 | * clear if the last attempt to init failed with an error. */ | ||
951 | card_info[data].initialized = 0; | ||
952 | |||
953 | if (id == SYS_HOTSWAP_INSERTED) | ||
954 | { | ||
955 | enable_controller(true); | ||
956 | rc = sd_init_card(data); | ||
957 | enable_controller(false); | ||
958 | } | ||
959 | |||
960 | mutex_unlock(&sd_mtx); | ||
961 | break; | ||
962 | #endif /* HAVE_HOTSWAP */ | ||
963 | default: | ||
964 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
965 | STORAGE_SD); | ||
966 | break; | ||
967 | } | ||
968 | |||
969 | return rc; | ||
970 | } | ||
diff --git a/firmware/target/arm/ata-nand-telechips.c b/firmware/target/arm/ata-nand-telechips.c index 869a53c1ef..73d92a5215 100644 --- a/firmware/target/arm/ata-nand-telechips.c +++ b/firmware/target/arm/ata-nand-telechips.c | |||
@@ -1065,3 +1065,9 @@ void nand_enable(bool onoff) | |||
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | #endif /* CONFIG_STORAGE_MULTI */ | 1067 | #endif /* CONFIG_STORAGE_MULTI */ |
1068 | |||
1069 | int nand_event(long id, intptr_t data) | ||
1070 | { | ||
1071 | return storage_event_default_handler(id, data, last_disk_activity, | ||
1072 | STORAGE_NAND); | ||
1073 | } | ||
diff --git a/firmware/target/arm/imx233/ata-target.h b/firmware/target/arm/imx233/ata-target.h index a95ea03247..2c553ebbff 100644 --- a/firmware/target/arm/imx233/ata-target.h +++ b/firmware/target/arm/imx233/ata-target.h | |||
@@ -23,10 +23,6 @@ | |||
23 | 23 | ||
24 | #include "config.h" | 24 | #include "config.h" |
25 | 25 | ||
26 | #ifdef BOOTLOADER | ||
27 | #define ATA_DRIVER_CLOSE | ||
28 | #endif | ||
29 | |||
30 | #ifdef HAVE_ATA_DMA | 26 | #ifdef HAVE_ATA_DMA |
31 | /* FIXME does this chips does MWDMA ? */ | 27 | /* FIXME does this chips does MWDMA ? */ |
32 | #define ATA_MAX_MWDMA 2 | 28 | #define ATA_MAX_MWDMA 2 |
diff --git a/firmware/target/arm/imx233/sdmmc-imx233.c b/firmware/target/arm/imx233/sdmmc-imx233.c index d3dabafecb..af090e8a07 100644 --- a/firmware/target/arm/imx233/sdmmc-imx233.c +++ b/firmware/target/arm/imx233/sdmmc-imx233.c | |||
@@ -217,9 +217,6 @@ static struct sdmmc_status_t sdmmc_status[SDMMC_NUM_DRIVES]; | |||
217 | #define SDMMC_STATUS(drive) sdmmc_status[drive] | 217 | #define SDMMC_STATUS(drive) sdmmc_status[drive] |
218 | 218 | ||
219 | /* sd only */ | 219 | /* sd only */ |
220 | static long sdmmc_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
221 | static const char sdmmc_thread_name[] = "sdmmc"; | ||
222 | static struct event_queue sdmmc_queue; | ||
223 | #if CONFIG_STORAGE & STORAGE_SD | 220 | #if CONFIG_STORAGE & STORAGE_SD |
224 | static int sd_first_drive; | 221 | static int sd_first_drive; |
225 | static unsigned _sd_num_drives; | 222 | static unsigned _sd_num_drives; |
@@ -260,10 +257,38 @@ static void sdmmc_detect_callback(int ssp) | |||
260 | { | 257 | { |
261 | /* This is called only if the state was stable for 300ms - check state | 258 | /* This is called only if the state was stable for 300ms - check state |
262 | * and post appropriate event. */ | 259 | * and post appropriate event. */ |
263 | if(imx233_ssp_sdmmc_detect(ssp)) | 260 | long evid = imx233_ssp_sdmmc_detect(ssp) ? |
264 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 261 | SYS_HOTSWAP_INSERTED : SYS_HOTSWAP_EXTRACTED; |
265 | else | 262 | |
266 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | 263 | /* Have to reverse lookup the ssp */ |
264 | for (unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) | ||
265 | { | ||
266 | if (SDMMC_SSP(drive) != ssp) | ||
267 | continue; | ||
268 | |||
269 | int first_drive, *map; | ||
270 | switch (SDMMC_MODE(drive)) | ||
271 | { | ||
272 | #if (CONFIG_STORAGE & STORAGE_MMC) | ||
273 | case MMC_MODE: | ||
274 | first_drive = mmc_first_drive; | ||
275 | map = mmc_map; | ||
276 | break; | ||
277 | #endif | ||
278 | #if (CONFIG_STORAGE & STORAGE_SD) | ||
279 | case SD_MODE: | ||
280 | first_drive = sd_first_drive; | ||
281 | map = sd_map; | ||
282 | break; | ||
283 | #endif | ||
284 | default: | ||
285 | continue; | ||
286 | } | ||
287 | |||
288 | /* message requires logical drive number as data */ | ||
289 | queue_broadcast(evid, first_drive + map[drive]); | ||
290 | } | ||
291 | |||
267 | imx233_ssp_sdmmc_setup_detect(ssp, true, sdmmc_detect_callback, false, | 292 | imx233_ssp_sdmmc_setup_detect(ssp, true, sdmmc_detect_callback, false, |
268 | imx233_ssp_sdmmc_is_detect_inverted(ssp)); | 293 | imx233_ssp_sdmmc_is_detect_inverted(ssp)); |
269 | } | 294 | } |
@@ -483,7 +508,48 @@ static int init_sd_card(int drive) | |||
483 | 508 | ||
484 | return 0; | 509 | return 0; |
485 | } | 510 | } |
486 | #endif | 511 | |
512 | int sd_event(long id, intptr_t data) | ||
513 | { | ||
514 | int rc = 0; | ||
515 | |||
516 | switch (id) | ||
517 | { | ||
518 | #ifdef HAVE_HOTSWAP | ||
519 | case SYS_HOTSWAP_INSERTED: | ||
520 | case SYS_HOTSWAP_EXTRACTED:; | ||
521 | const int drive = sd_map[data]; | ||
522 | |||
523 | /* Skip non-removable drivers */ | ||
524 | if(!sdmmc_removable(drive)) | ||
525 | { | ||
526 | rc = -1; | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | mutex_lock(&mutex[drive]); /* lock-out card activity */ | ||
531 | |||
532 | /* Force card init for new card, re-init for re-inserted one or | ||
533 | * clear if the last attempt to init failed with an error. */ | ||
534 | SDMMC_INFO(drive).initialized = 0; | ||
535 | |||
536 | if(id == SYS_HOTSWAP_INSERTED) | ||
537 | rc = init_drive(drive); | ||
538 | |||
539 | /* unlock card */ | ||
540 | mutex_unlock(&mutex[drive]); | ||
541 | /* Access is now safe */ | ||
542 | break; | ||
543 | #endif /* HAVE_HOTSWAP */ | ||
544 | default: | ||
545 | rc = storage_event_default_handler(id, data, sd_last_disk_activity(), | ||
546 | STORAGE_SD); | ||
547 | break; | ||
548 | } | ||
549 | |||
550 | return rc; | ||
551 | } | ||
552 | #endif /* CONFIG_STORAGE & STORAGE_SD */ | ||
487 | 553 | ||
488 | #if CONFIG_STORAGE & STORAGE_MMC | 554 | #if CONFIG_STORAGE & STORAGE_MMC |
489 | static int init_mmc_drive(int drive) | 555 | static int init_mmc_drive(int drive) |
@@ -573,7 +639,13 @@ static int init_mmc_drive(int drive) | |||
573 | 639 | ||
574 | return 0; | 640 | return 0; |
575 | } | 641 | } |
576 | #endif | 642 | |
643 | int mmc_event(long id, intptr_t data) | ||
644 | { | ||
645 | return storage_event_default_handler(id, data, mmc_last_disk_activity(), | ||
646 | STORAGE_MMC); | ||
647 | } | ||
648 | #endif /* CONFIG_STORAGE & STORAGE_MMC */ | ||
577 | 649 | ||
578 | /* low-level function, don't call directly! */ | 650 | /* low-level function, don't call directly! */ |
579 | static int __xfer_sectors(int drive, unsigned long start, int count, void *buf, bool read) | 651 | static int __xfer_sectors(int drive, unsigned long start, int count, void *buf, bool read) |
@@ -770,98 +842,6 @@ static int init_drive(int drive) | |||
770 | return 0; | 842 | return 0; |
771 | } | 843 | } |
772 | 844 | ||
773 | static void sdmmc_thread(void) NORETURN_ATTR; | ||
774 | static void sdmmc_thread(void) | ||
775 | { | ||
776 | struct queue_event ev; | ||
777 | bool idle_notified = false; | ||
778 | int timeout = 0; | ||
779 | |||
780 | while (1) | ||
781 | { | ||
782 | queue_wait_w_tmo(&sdmmc_queue, &ev, HZ); | ||
783 | |||
784 | switch(ev.id) | ||
785 | { | ||
786 | #if CONFIG_STORAGE & STORAGE_SD | ||
787 | case SYS_HOTSWAP_INSERTED: | ||
788 | case SYS_HOTSWAP_EXTRACTED: | ||
789 | { | ||
790 | int microsd_init = ev.id == SYS_HOTSWAP_INSERTED ? 0 : 1; | ||
791 | |||
792 | /* We now have exclusive control of fat cache and sd. | ||
793 | * Release "by force", ensure file | ||
794 | * descriptors aren't leaked and any busy | ||
795 | * ones are invalid if mounting. */ | ||
796 | for(unsigned sd_drive = 0; sd_drive < _sd_num_drives; sd_drive++) | ||
797 | { | ||
798 | int drive = sd_map[sd_drive]; | ||
799 | /* Skip non-removable drivers */ | ||
800 | if(!sdmmc_removable(drive)) | ||
801 | continue; | ||
802 | |||
803 | disk_unmount(sd_first_drive + sd_drive); | ||
804 | |||
805 | mutex_lock(&mutex[drive]); /* lock-out card activity */ | ||
806 | |||
807 | /* Force card init for new card, re-init for re-inserted one or | ||
808 | * clear if the last attempt to init failed with an error. */ | ||
809 | SDMMC_INFO(sd_map[sd_drive]).initialized = 0; | ||
810 | |||
811 | int rc = -1; | ||
812 | if(ev.id == SYS_HOTSWAP_INSERTED) | ||
813 | { | ||
814 | rc = init_drive(drive); | ||
815 | if(rc < 0) /* initialisation failed */ | ||
816 | panicf("%s init failed : %d", SDMMC_CONF(sd_map[sd_drive]).name, rc); | ||
817 | } | ||
818 | |||
819 | /* unlock card */ | ||
820 | mutex_unlock(&mutex[drive]); | ||
821 | |||
822 | if (rc >= 0) | ||
823 | microsd_init += disk_mount(sd_first_drive + sd_drive); /* 0 if fail */ | ||
824 | } | ||
825 | /* Access is now safe */ | ||
826 | /* | ||
827 | * One or more mounts succeeded, or this was an EXTRACTED event, | ||
828 | * in both cases notify the system about the changed filesystems | ||
829 | */ | ||
830 | if(microsd_init) | ||
831 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
832 | |||
833 | break; | ||
834 | } | ||
835 | #endif | ||
836 | case SYS_TIMEOUT: | ||
837 | #if CONFIG_STORAGE & STORAGE_SD | ||
838 | timeout = MAX(timeout, sd_last_disk_activity()+(3*HZ)); | ||
839 | #endif | ||
840 | #if CONFIG_STORAGE & STORAGE_MMC | ||
841 | timeout = MAX(timeout, mmc_last_disk_activity()+(3*HZ)); | ||
842 | #endif | ||
843 | if(TIME_BEFORE(current_tick, timeout)) | ||
844 | { | ||
845 | idle_notified = false; | ||
846 | } | ||
847 | else | ||
848 | { | ||
849 | if(!idle_notified) | ||
850 | { | ||
851 | call_storage_idle_notifys(false); | ||
852 | idle_notified = true; | ||
853 | } | ||
854 | } | ||
855 | break; | ||
856 | case SYS_USB_CONNECTED: | ||
857 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
858 | /* Wait until the USB cable is extracted again */ | ||
859 | usb_wait_for_disconnect(&sdmmc_queue); | ||
860 | break; | ||
861 | } | ||
862 | } | ||
863 | } | ||
864 | |||
865 | static int sdmmc_init(void) | 845 | static int sdmmc_init(void) |
866 | { | 846 | { |
867 | static int is_initialized = false; | 847 | static int is_initialized = false; |
@@ -871,10 +851,6 @@ static int sdmmc_init(void) | |||
871 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) | 851 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) |
872 | mutex_init(&mutex[drive]); | 852 | mutex_init(&mutex[drive]); |
873 | 853 | ||
874 | queue_init(&sdmmc_queue, true); | ||
875 | create_thread(sdmmc_thread, sdmmc_stack, sizeof(sdmmc_stack), 0, | ||
876 | sdmmc_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
877 | |||
878 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) | 854 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) |
879 | { | 855 | { |
880 | if(sdmmc_removable(drive)) | 856 | if(sdmmc_removable(drive)) |
@@ -1024,10 +1000,6 @@ void mmc_enable(bool on) | |||
1024 | (void) on; | 1000 | (void) on; |
1025 | } | 1001 | } |
1026 | 1002 | ||
1027 | void mmc_sleep(void) | ||
1028 | { | ||
1029 | } | ||
1030 | |||
1031 | void mmc_sleepnow(void) | 1003 | void mmc_sleepnow(void) |
1032 | { | 1004 | { |
1033 | } | 1005 | } |
diff --git a/firmware/target/arm/imx31/ata-target.h b/firmware/target/arm/imx31/ata-target.h index 6893e83198..9363a8579c 100644 --- a/firmware/target/arm/imx31/ata-target.h +++ b/firmware/target/arm/imx31/ata-target.h | |||
@@ -23,10 +23,6 @@ | |||
23 | 23 | ||
24 | #include "config.h" | 24 | #include "config.h" |
25 | 25 | ||
26 | #ifdef BOOTLOADER | ||
27 | #define ATA_DRIVER_CLOSE | ||
28 | #endif | ||
29 | |||
30 | /* Plain C read & write loops */ | 26 | /* Plain C read & write loops */ |
31 | /* They likely won't be used anyway since DMA potentially works for any | 27 | /* They likely won't be used anyway since DMA potentially works for any |
32 | * sector number and alignment. */ | 28 | * sector number and alignment. */ |
diff --git a/firmware/target/arm/pp/ata-sd-pp.c b/firmware/target/arm/pp/ata-sd-pp.c index edb806ab96..fb0a9e150e 100644 --- a/firmware/target/arm/pp/ata-sd-pp.c +++ b/firmware/target/arm/pp/ata-sd-pp.c | |||
@@ -24,16 +24,10 @@ | |||
24 | #ifdef HAVE_HOTSWAP | 24 | #ifdef HAVE_HOTSWAP |
25 | #include "sd-pp-target.h" | 25 | #include "sd-pp-target.h" |
26 | #endif | 26 | #endif |
27 | #include "ata_idle_notify.h" | ||
28 | #include "system.h" | 27 | #include "system.h" |
29 | #include <string.h> | 28 | #include <string.h> |
30 | #include "thread.h" | ||
31 | #include "led.h" | 29 | #include "led.h" |
32 | #include "disk.h" | ||
33 | #include "cpu.h" | 30 | #include "cpu.h" |
34 | #include "panic.h" | ||
35 | #include "usb.h" | ||
36 | #include "sd.h" | ||
37 | #include "storage.h" | 31 | #include "storage.h" |
38 | #include "fs_defines.h" | 32 | #include "fs_defines.h" |
39 | 33 | ||
@@ -151,12 +145,6 @@ | |||
151 | /* for compatibility */ | 145 | /* for compatibility */ |
152 | static long last_disk_activity = -1; | 146 | static long last_disk_activity = -1; |
153 | 147 | ||
154 | /** static, private data **/ | ||
155 | static bool initialized = false; | ||
156 | static unsigned int sd_thread_id = 0; | ||
157 | |||
158 | #define Q_CLOSE 1 | ||
159 | |||
160 | static long next_yield = 0; | 148 | static long next_yield = 0; |
161 | #define MIN_YIELD_PERIOD 1000 | 149 | #define MIN_YIELD_PERIOD 1000 |
162 | 150 | ||
@@ -177,30 +165,28 @@ static struct sd_card_status sd_status[NUM_DRIVES] = | |||
177 | #endif | 165 | #endif |
178 | }; | 166 | }; |
179 | 167 | ||
180 | /* Shoot for around 75% usage */ | 168 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
181 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
182 | static const char sd_thread_name[] = "ata/sd"; | ||
183 | static struct mutex sd_mtx SHAREDBSS_ATTR; | ||
184 | static struct event_queue sd_queue SHAREDBSS_ATTR; | ||
185 | 169 | ||
186 | #ifdef HAVE_HOTSWAP | 170 | #ifdef HAVE_HOTSWAP |
187 | static int sd_first_drive = 0; | 171 | static int sd_first_drive = 0; |
188 | #endif | 172 | #endif |
189 | 173 | ||
190 | /* Posted when card plugged status has changed */ | ||
191 | #define SD_HOTSWAP 1 | ||
192 | /* Actions taken by sd_thread when card status has changed */ | ||
193 | enum sd_thread_actions | ||
194 | { | ||
195 | SDA_NONE = 0x0, | ||
196 | SDA_UNMOUNTED = 0x1, | ||
197 | SDA_MOUNTED = 0x2 | ||
198 | }; | ||
199 | |||
200 | /* Private Functions */ | 174 | /* Private Functions */ |
201 | 175 | ||
202 | static unsigned int check_time[NUM_EC]; | 176 | static unsigned int check_time[NUM_EC]; |
203 | 177 | ||
178 | static inline void enable_controller(bool on) | ||
179 | { | ||
180 | if(on) | ||
181 | { | ||
182 | DEV_EN |= DEV_ATA; /* Enable controller */ | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | DEV_EN &= ~DEV_ATA; /* Disable controller */ | ||
187 | } | ||
188 | } | ||
189 | |||
204 | static inline bool sd_check_timeout(long timeout, int id) | 190 | static inline bool sd_check_timeout(long timeout, int id) |
205 | { | 191 | { |
206 | return !TIME_AFTER(USEC_TIMER, check_time[id] + timeout); | 192 | return !TIME_AFTER(USEC_TIMER, check_time[id] + timeout); |
@@ -876,7 +862,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int incount, | |||
876 | /* TODO: Add DMA support. */ | 862 | /* TODO: Add DMA support. */ |
877 | 863 | ||
878 | mutex_lock(&sd_mtx); | 864 | mutex_lock(&sd_mtx); |
879 | sd_enable(true); | 865 | enable_controller(true); |
880 | led(true); | 866 | led(true); |
881 | 867 | ||
882 | sd_read_retry: | 868 | sd_read_retry: |
@@ -964,7 +950,7 @@ sd_read_retry: | |||
964 | while (1) | 950 | while (1) |
965 | { | 951 | { |
966 | led(false); | 952 | led(false); |
967 | sd_enable(false); | 953 | enable_controller(false); |
968 | mutex_unlock(&sd_mtx); | 954 | mutex_unlock(&sd_mtx); |
969 | 955 | ||
970 | return ret; | 956 | return ret; |
@@ -994,7 +980,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
994 | unsigned int bank; | 980 | unsigned int bank; |
995 | 981 | ||
996 | mutex_lock(&sd_mtx); | 982 | mutex_lock(&sd_mtx); |
997 | sd_enable(true); | 983 | enable_controller(true); |
998 | led(true); | 984 | led(true); |
999 | 985 | ||
1000 | sd_write_retry: | 986 | sd_write_retry: |
@@ -1092,7 +1078,7 @@ sd_write_retry: | |||
1092 | while (1) | 1078 | while (1) |
1093 | { | 1079 | { |
1094 | led(false); | 1080 | led(false); |
1095 | sd_enable(false); | 1081 | enable_controller(false); |
1096 | mutex_unlock(&sd_mtx); | 1082 | mutex_unlock(&sd_mtx); |
1097 | 1083 | ||
1098 | return ret; | 1084 | return ret; |
@@ -1108,182 +1094,79 @@ sd_write_error: | |||
1108 | } | 1094 | } |
1109 | } | 1095 | } |
1110 | 1096 | ||
1111 | #ifndef SD_DRIVER_CLOSE | ||
1112 | static void sd_thread(void) NORETURN_ATTR; | ||
1113 | #endif | ||
1114 | static void sd_thread(void) | ||
1115 | { | ||
1116 | struct queue_event ev; | ||
1117 | bool idle_notified = false; | ||
1118 | |||
1119 | while (1) | ||
1120 | { | ||
1121 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
1122 | |||
1123 | switch ( ev.id ) | ||
1124 | { | ||
1125 | #ifdef HAVE_HOTSWAP | ||
1126 | case SYS_HOTSWAP_INSERTED: | ||
1127 | case SYS_HOTSWAP_EXTRACTED:; | ||
1128 | int success = 1; | ||
1129 | |||
1130 | disk_unmount(sd_first_drive+1); /* release "by force" */ | ||
1131 | |||
1132 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
1133 | |||
1134 | /* Force card init for new card, re-init for re-inserted one or | ||
1135 | * clear if the last attempt to init failed with an error. */ | ||
1136 | card_info[1].initialized = 0; | ||
1137 | sd_status[1].retry = 0; | ||
1138 | |||
1139 | /* Access is now safe */ | ||
1140 | mutex_unlock(&sd_mtx); | ||
1141 | |||
1142 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
1143 | success = disk_mount(sd_first_drive+1); /* 0 if fail */ | ||
1144 | |||
1145 | if (success) | ||
1146 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
1147 | break; | ||
1148 | #endif /* HAVE_HOTSWAP */ | ||
1149 | case SYS_TIMEOUT: | ||
1150 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
1151 | { | ||
1152 | idle_notified = false; | ||
1153 | } | ||
1154 | else | ||
1155 | { | ||
1156 | /* never let a timer wrap confuse us */ | ||
1157 | next_yield = USEC_TIMER; | ||
1158 | |||
1159 | if (!idle_notified) | ||
1160 | { | ||
1161 | call_storage_idle_notifys(false); | ||
1162 | idle_notified = true; | ||
1163 | } | ||
1164 | } | ||
1165 | break; | ||
1166 | case SYS_USB_CONNECTED: | ||
1167 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
1168 | /* Wait until the USB cable is extracted again */ | ||
1169 | usb_wait_for_disconnect(&sd_queue); | ||
1170 | break; | ||
1171 | |||
1172 | #ifdef SD_DRIVER_CLOSE | ||
1173 | case Q_CLOSE: | ||
1174 | return; | ||
1175 | #endif | ||
1176 | } | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1180 | #ifdef SD_DRIVER_CLOSE | ||
1181 | void sd_close(void) | ||
1182 | { | ||
1183 | unsigned int thread_id = sd_thread_id; | ||
1184 | |||
1185 | if (thread_id == 0) | ||
1186 | return; | ||
1187 | |||
1188 | sd_thread_id = 0; | ||
1189 | |||
1190 | queue_post(&sd_queue, Q_CLOSE, 0); | ||
1191 | thread_wait(thread_id); | ||
1192 | } | ||
1193 | #endif /* SD_DRIVER_CLOSE */ | ||
1194 | |||
1195 | void sd_enable(bool on) | 1097 | void sd_enable(bool on) |
1196 | { | 1098 | { |
1197 | if(on) | 1099 | mutex_lock(&sd_mtx); |
1198 | { | 1100 | enable_controller(on); |
1199 | DEV_EN |= DEV_ATA; /* Enable controller */ | 1101 | mutex_unlock(&sd_mtx); |
1200 | } | ||
1201 | else | ||
1202 | { | ||
1203 | DEV_EN &= ~DEV_ATA; /* Disable controller */ | ||
1204 | } | ||
1205 | } | 1102 | } |
1206 | 1103 | ||
1207 | |||
1208 | int sd_init(void) | 1104 | int sd_init(void) |
1209 | { | 1105 | { |
1210 | int ret = 0; | 1106 | int ret = 0; |
1211 | 1107 | ||
1212 | if (!initialized) | 1108 | mutex_init(&sd_mtx); |
1213 | mutex_init(&sd_mtx); | ||
1214 | |||
1215 | mutex_lock(&sd_mtx); | ||
1216 | 1109 | ||
1217 | led(false); | 1110 | led(false); |
1218 | 1111 | ||
1219 | if (!initialized) | 1112 | /* init controller */ |
1220 | { | ||
1221 | initialized = true; | ||
1222 | |||
1223 | /* init controller */ | ||
1224 | #if defined(PHILIPS_SA9200) | 1113 | #if defined(PHILIPS_SA9200) |
1225 | GPIOA_ENABLE = 0x00; | 1114 | GPIOA_ENABLE = 0x00; |
1226 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01); | 1115 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01); |
1227 | #else | 1116 | #else |
1228 | outl(inl(0x70000088) & ~(0x4), 0x70000088); | 1117 | outl(inl(0x70000088) & ~(0x4), 0x70000088); |
1229 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); | 1118 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); |
1230 | GPO32_ENABLE |= 0x4; | 1119 | GPO32_ENABLE |= 0x4; |
1231 | 1120 | ||
1232 | GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5)); | 1121 | GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5)); |
1233 | GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5)); | 1122 | GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5)); |
1234 | GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5)); | 1123 | GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5)); |
1235 | #endif | 1124 | #endif |
1236 | 1125 | ||
1237 | #ifdef HAVE_HOTSWAP | 1126 | #ifdef HAVE_HOTSWAP |
1238 | /* enable card detection port - mask interrupt first */ | 1127 | /* enable card detection port - mask interrupt first */ |
1239 | #ifdef SANSA_E200 | 1128 | #ifdef SANSA_E200 |
1240 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); | 1129 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); |
1241 | 1130 | ||
1242 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80); | 1131 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80); |
1243 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80); | 1132 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80); |
1244 | #elif defined SANSA_C200 | 1133 | #elif defined SANSA_C200 |
1245 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); | 1134 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); |
1246 | 1135 | ||
1247 | GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08); | 1136 | GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08); |
1248 | GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08); | 1137 | GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08); |
1249 | #endif | 1138 | #endif |
1250 | #endif | 1139 | #endif |
1251 | sd_select_device(0); | 1140 | sd_select_device(0); |
1252 | |||
1253 | if (currcard->initialized < 0) | ||
1254 | ret = currcard->initialized; | ||
1255 | 1141 | ||
1256 | queue_init(&sd_queue, true); | 1142 | if (currcard->initialized < 0) |
1257 | sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack), | 1143 | ret = currcard->initialized; |
1258 | 0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
1259 | IF_COP(, CPU)); | ||
1260 | 1144 | ||
1261 | /* enable interupt for the mSD card */ | 1145 | /* enable interupt for the mSD card */ |
1262 | sleep(HZ/10); | 1146 | sleep(HZ/10); |
1263 | #ifdef HAVE_HOTSWAP | 1147 | #ifdef HAVE_HOTSWAP |
1264 | #ifdef SANSA_E200 | 1148 | #ifdef SANSA_E200 |
1265 | CPU_INT_EN = HI_MASK; | 1149 | CPU_INT_EN = HI_MASK; |
1266 | CPU_HI_INT_EN = GPIO0_MASK; | 1150 | CPU_HI_INT_EN = GPIO0_MASK; |
1267 | 1151 | ||
1268 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); | 1152 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); |
1269 | 1153 | ||
1270 | GPIOA_INT_CLR = 0x80; | 1154 | GPIOA_INT_CLR = 0x80; |
1271 | 1155 | ||
1272 | /* enable the card detect interrupt */ | 1156 | /* enable the card detect interrupt */ |
1273 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); | 1157 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); |
1274 | #elif defined SANSA_C200 | 1158 | #elif defined SANSA_C200 |
1275 | CPU_INT_EN = HI_MASK; | 1159 | CPU_INT_EN = HI_MASK; |
1276 | CPU_HI_INT_EN = GPIO2_MASK; | 1160 | CPU_HI_INT_EN = GPIO2_MASK; |
1277 | 1161 | ||
1278 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); | 1162 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); |
1279 | 1163 | ||
1280 | GPIOL_INT_CLR = 0x08; | 1164 | GPIOL_INT_CLR = 0x08; |
1281 | 1165 | ||
1282 | /* enable the card detect interrupt */ | 1166 | /* enable the card detect interrupt */ |
1283 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); | 1167 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); |
1284 | #endif | ||
1285 | #endif | 1168 | #endif |
1286 | } | 1169 | #endif /* HAVE_HOTSWAP */ |
1287 | 1170 | ||
1288 | mutex_unlock(&sd_mtx); | 1171 | mutex_unlock(&sd_mtx); |
1289 | 1172 | ||
@@ -1294,19 +1177,17 @@ tCardInfo *card_get_info_target(int card_no) | |||
1294 | { | 1177 | { |
1295 | return &card_info[card_no]; | 1178 | return &card_info[card_no]; |
1296 | } | 1179 | } |
1180 | |||
1297 | #ifdef HAVE_HOTSWAP | 1181 | #ifdef HAVE_HOTSWAP |
1298 | static int sd1_oneshot_callback(struct timeout *tmo) | 1182 | static int sd1_oneshot_callback(struct timeout *tmo) |
1299 | { | 1183 | { |
1300 | (void)tmo; | ||
1301 | |||
1302 | /* This is called only if the state was stable for 300ms - check state | 1184 | /* This is called only if the state was stable for 300ms - check state |
1303 | * and post appropriate event. */ | 1185 | * and post appropriate event. */ |
1304 | if (card_detect_target()) | 1186 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
1305 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 1187 | SYS_HOTSWAP_EXTRACTED, |
1306 | else | 1188 | sd_first_drive+1); |
1307 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
1308 | |||
1309 | return 0; | 1189 | return 0; |
1190 | (void)tmo; | ||
1310 | } | 1191 | } |
1311 | 1192 | ||
1312 | /* called on insertion/removal interrupt */ | 1193 | /* called on insertion/removal interrupt */ |
@@ -1377,3 +1258,36 @@ int sd_num_drives(int first_drive) | |||
1377 | #endif | 1258 | #endif |
1378 | } | 1259 | } |
1379 | #endif | 1260 | #endif |
1261 | |||
1262 | int sd_event(long id, intptr_t data) | ||
1263 | { | ||
1264 | int rc = 0; | ||
1265 | |||
1266 | switch (id) | ||
1267 | { | ||
1268 | #ifdef HAVE_HOTSWAP | ||
1269 | case SYS_HOTSWAP_INSERTED: | ||
1270 | case SYS_HOTSWAP_EXTRACTED: | ||
1271 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
1272 | |||
1273 | /* Force card init for new card, re-init for re-inserted one or | ||
1274 | * clear if the last attempt to init failed with an error. */ | ||
1275 | card_info[data].initialized = 0; | ||
1276 | sd_status[data].retry = 0; | ||
1277 | |||
1278 | /* Access is now safe */ | ||
1279 | mutex_unlock(&sd_mtx); | ||
1280 | break; | ||
1281 | #endif /* HAVE_HOTSWAP */ | ||
1282 | |||
1283 | case Q_STORAGE_TICK: | ||
1284 | /* never let a timer wrap confuse us */ | ||
1285 | next_yield = USEC_TIMER; | ||
1286 | default: | ||
1287 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
1288 | STORAGE_SD); | ||
1289 | break; | ||
1290 | } | ||
1291 | |||
1292 | return rc; | ||
1293 | } | ||
diff --git a/firmware/target/arm/pp/ata-target.h b/firmware/target/arm/pp/ata-target.h index b888f85b88..a11aeda36d 100644 --- a/firmware/target/arm/pp/ata-target.h +++ b/firmware/target/arm/pp/ata-target.h | |||
@@ -24,10 +24,6 @@ | |||
24 | 24 | ||
25 | #include "config.h" | 25 | #include "config.h" |
26 | 26 | ||
27 | #ifdef HAVE_BOOTLOADER_USB_MODE | ||
28 | #define ATA_DRIVER_CLOSE | ||
29 | #endif | ||
30 | |||
31 | /* primary channel */ | 27 | /* primary channel */ |
32 | #define ATA_DATA (*((volatile unsigned short*)(IDE_BASE + 0x1e0))) | 28 | #define ATA_DATA (*((volatile unsigned short*)(IDE_BASE + 0x1e0))) |
33 | #define ATA_ERROR (*((volatile unsigned char*)(IDE_BASE + 0x1e4))) | 29 | #define ATA_ERROR (*((volatile unsigned char*)(IDE_BASE + 0x1e4))) |
diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c index 6eeff7bae5..2ddfd0cf0a 100644 --- a/firmware/target/arm/rk27xx/sd-rk27xx.c +++ b/firmware/target/arm/rk27xx/sd-rk27xx.c | |||
@@ -34,13 +34,7 @@ | |||
34 | #include <string.h> | 34 | #include <string.h> |
35 | #include "panic.h" | 35 | #include "panic.h" |
36 | #include "stdbool.h" | 36 | #include "stdbool.h" |
37 | #include "ata_idle_notify.h" | 37 | #include "storage.h" |
38 | #include "sd.h" | ||
39 | #include "usb.h" | ||
40 | |||
41 | #ifdef HAVE_HOTSWAP | ||
42 | #include "disk.h" | ||
43 | #endif | ||
44 | 38 | ||
45 | #include "lcd.h" | 39 | #include "lcd.h" |
46 | #include <stdarg.h> | 40 | #include <stdarg.h> |
@@ -57,21 +51,39 @@ static tCardInfo card_info; | |||
57 | /* for compatibility */ | 51 | /* for compatibility */ |
58 | static long last_disk_activity = -1; | 52 | static long last_disk_activity = -1; |
59 | 53 | ||
60 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
61 | static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR; | 54 | static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR; |
62 | 55 | ||
63 | static const char sd_thread_name[] = "ata/sd"; | ||
64 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 56 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
65 | static struct event_queue sd_queue; | ||
66 | #ifndef BOOTLOADER | 57 | #ifndef BOOTLOADER |
67 | bool sd_enabled = false; | 58 | bool sd_enabled = false; |
68 | #endif | 59 | #endif |
69 | 60 | ||
61 | #ifdef CONFIG_STORAGE_MULTI | ||
62 | static int sd_first_drive = 0; | ||
63 | #else | ||
64 | #define sd_first_drive 0 | ||
65 | #endif | ||
66 | |||
70 | static struct semaphore transfer_completion_signal; | 67 | static struct semaphore transfer_completion_signal; |
71 | static struct semaphore command_completion_signal; | 68 | static struct semaphore command_completion_signal; |
72 | static volatile bool retry; | 69 | static volatile bool retry; |
73 | static volatile int cmd_error; | 70 | static volatile int cmd_error; |
74 | 71 | ||
72 | static void enable_controller(bool on) | ||
73 | { | ||
74 | /* enable or disable clock signal for SD module */ | ||
75 | if (on) | ||
76 | { | ||
77 | SCU_CLKCFG &= ~CLKCFG_SD; | ||
78 | led(true); | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | SCU_CLKCFG |= CLKCFG_SD; | ||
83 | led(false); | ||
84 | } | ||
85 | } | ||
86 | |||
75 | /* interrupt handler for SD */ | 87 | /* interrupt handler for SD */ |
76 | void INT_SD(void) | 88 | void INT_SD(void) |
77 | { | 89 | { |
@@ -318,81 +330,6 @@ static int sd_init_card(void) | |||
318 | return 0; | 330 | return 0; |
319 | } | 331 | } |
320 | 332 | ||
321 | static void sd_thread(void) NORETURN_ATTR; | ||
322 | static void sd_thread(void) | ||
323 | { | ||
324 | struct queue_event ev; | ||
325 | bool idle_notified = false; | ||
326 | |||
327 | while (1) | ||
328 | { | ||
329 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
330 | |||
331 | switch ( ev.id ) | ||
332 | { | ||
333 | #ifdef HAVE_HOTSWAP | ||
334 | case SYS_HOTSWAP_INSERTED: | ||
335 | case SYS_HOTSWAP_EXTRACTED:; | ||
336 | int success = 1; | ||
337 | |||
338 | disk_unmount(sd_first_drive); /* release "by force" */ | ||
339 | |||
340 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
341 | |||
342 | /* Force card init for new card, re-init for re-inserted one or | ||
343 | * clear if the last attempt to init failed with an error. */ | ||
344 | card_info.initialized = 0; | ||
345 | |||
346 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
347 | { | ||
348 | success = 0; | ||
349 | sd_enable(true); | ||
350 | int rc = sd_init_card(sd_first_drive); | ||
351 | sd_enable(false); | ||
352 | if (rc >= 0) | ||
353 | success = 2; | ||
354 | else /* initialisation failed */ | ||
355 | panicf("microSD init failed : %d", rc); | ||
356 | } | ||
357 | |||
358 | /* Access is now safe */ | ||
359 | mutex_unlock(&sd_mtx); | ||
360 | |||
361 | if (success > 1) | ||
362 | success = disk_mount(sd_first_drive); /* 0 if fail */ | ||
363 | |||
364 | /* | ||
365 | * Mount succeeded, or this was an EXTRACTED event, | ||
366 | * in both cases notify the system about the changed filesystems | ||
367 | */ | ||
368 | if (success) | ||
369 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
370 | |||
371 | break; | ||
372 | #endif /* HAVE_HOTSWAP */ | ||
373 | |||
374 | case SYS_TIMEOUT: | ||
375 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
376 | { | ||
377 | idle_notified = false; | ||
378 | } | ||
379 | else if (!idle_notified) | ||
380 | { | ||
381 | call_storage_idle_notifys(false); | ||
382 | idle_notified = true; | ||
383 | } | ||
384 | break; | ||
385 | |||
386 | case SYS_USB_CONNECTED: | ||
387 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
388 | /* Wait until the USB cable is extracted again */ | ||
389 | usb_wait_for_disconnect(&sd_queue); | ||
390 | |||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | |||
396 | static void init_controller(void) | 333 | static void init_controller(void) |
397 | { | 334 | { |
398 | /* reset SD module */ | 335 | /* reset SD module */ |
@@ -441,6 +378,7 @@ int sd_init(void) | |||
441 | { | 378 | { |
442 | int ret; | 379 | int ret; |
443 | 380 | ||
381 | mutex_init(&sd_mtx); | ||
444 | semaphore_init(&transfer_completion_signal, 1, 0); | 382 | semaphore_init(&transfer_completion_signal, 1, 0); |
445 | semaphore_init(&command_completion_signal, 1, 0); | 383 | semaphore_init(&command_completion_signal, 1, 0); |
446 | 384 | ||
@@ -450,13 +388,6 @@ int sd_init(void) | |||
450 | if(ret < 0) | 388 | if(ret < 0) |
451 | return ret; | 389 | return ret; |
452 | 390 | ||
453 | /* init mutex */ | ||
454 | mutex_init(&sd_mtx); | ||
455 | |||
456 | queue_init(&sd_queue, true); | ||
457 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
458 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
459 | |||
460 | return 0; | 391 | return 0; |
461 | } | 392 | } |
462 | 393 | ||
@@ -523,7 +454,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
523 | unsigned char *dst; | 454 | unsigned char *dst; |
524 | 455 | ||
525 | mutex_lock(&sd_mtx); | 456 | mutex_lock(&sd_mtx); |
526 | sd_enable(true); | 457 | enable_controller(true); |
527 | 458 | ||
528 | if (count <= 0 || start + count > card_info.numblocks) | 459 | if (count <= 0 || start + count > card_info.numblocks) |
529 | return -1; | 460 | return -1; |
@@ -627,7 +558,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
627 | 558 | ||
628 | } /* while (retry_cnt++ < 20) */ | 559 | } /* while (retry_cnt++ < 20) */ |
629 | 560 | ||
630 | sd_enable(false); | 561 | enable_controller(false); |
631 | mutex_unlock(&sd_mtx); | 562 | mutex_unlock(&sd_mtx); |
632 | 563 | ||
633 | return ret; | 564 | return ret; |
@@ -659,7 +590,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
659 | /* bool card_selected = false; */ | 590 | /* bool card_selected = false; */ |
660 | 591 | ||
661 | mutex_lock(&sd_mtx); | 592 | mutex_lock(&sd_mtx); |
662 | sd_enable(true); | 593 | enable_controller(true); |
663 | 594 | ||
664 | if (count <= 0 || start + count > card_info.numblocks) | 595 | if (count <= 0 || start + count > card_info.numblocks) |
665 | return -1; | 596 | return -1; |
@@ -731,7 +662,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
731 | break; | 662 | break; |
732 | } | 663 | } |
733 | 664 | ||
734 | sd_enable(false); | 665 | enable_controller(false); |
735 | mutex_unlock(&sd_mtx); | 666 | mutex_unlock(&sd_mtx); |
736 | 667 | ||
737 | #ifdef RK27XX_SD_DEBUG | 668 | #ifdef RK27XX_SD_DEBUG |
@@ -746,17 +677,9 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
746 | 677 | ||
747 | void sd_enable(bool on) | 678 | void sd_enable(bool on) |
748 | { | 679 | { |
749 | /* enable or disable clock signal for SD module */ | 680 | mutex_lock(&sd_mtx); |
750 | if (on) | 681 | enable_controller(on); |
751 | { | 682 | mutex_unlock(&sd_mtx); |
752 | SCU_CLKCFG &= ~CLKCFG_SD; | ||
753 | led(true); | ||
754 | } | ||
755 | else | ||
756 | { | ||
757 | SCU_CLKCFG |= CLKCFG_SD; | ||
758 | led(false); | ||
759 | } | ||
760 | } | 683 | } |
761 | 684 | ||
762 | #ifndef BOOTLOADER | 685 | #ifndef BOOTLOADER |
@@ -788,18 +711,13 @@ bool sd_present(IF_MD_NONVOID(int drive)) | |||
788 | 711 | ||
789 | static int sd_oneshot_callback(struct timeout *tmo) | 712 | static int sd_oneshot_callback(struct timeout *tmo) |
790 | { | 713 | { |
791 | (void)tmo; | ||
792 | |||
793 | /* This is called only if the state was stable for 300ms - check state | 714 | /* This is called only if the state was stable for 300ms - check state |
794 | * and post appropriate event. */ | 715 | * and post appropriate event. */ |
795 | if (card_detect_target()) | 716 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
796 | { | 717 | SYS_HOTSWAP_EXTRACTED, |
797 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 718 | sd_first_drive); |
798 | } | ||
799 | else | ||
800 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
801 | |||
802 | return 0; | 719 | return 0; |
720 | (void)tmo; | ||
803 | } | 721 | } |
804 | 722 | ||
805 | /* interrupt handler for SD detect */ | 723 | /* interrupt handler for SD detect */ |
@@ -809,9 +727,42 @@ static int sd_oneshot_callback(struct timeout *tmo) | |||
809 | #ifdef CONFIG_STORAGE_MULTI | 727 | #ifdef CONFIG_STORAGE_MULTI |
810 | int sd_num_drives(int first_drive) | 728 | int sd_num_drives(int first_drive) |
811 | { | 729 | { |
812 | (void)first_drive; | ||
813 | |||
814 | /* we have only one SD drive */ | 730 | /* we have only one SD drive */ |
731 | sd_first_drive = first_drive; | ||
815 | return 1; | 732 | return 1; |
816 | } | 733 | } |
817 | #endif /* CONFIG_STORAGE_MULTI */ | 734 | #endif /* CONFIG_STORAGE_MULTI */ |
735 | |||
736 | int sd_event(long id, intptr_t data) | ||
737 | { | ||
738 | int rc = 0; | ||
739 | |||
740 | switch (id) | ||
741 | { | ||
742 | #ifdef HAVE_HOTSWAP | ||
743 | case SYS_HOTSWAP_INSERTED: | ||
744 | case SYS_HOTSWAP_EXTRACTED: | ||
745 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
746 | |||
747 | /* Force card init for new card, re-init for re-inserted one or | ||
748 | * clear if the last attempt to init failed with an error. */ | ||
749 | card_info.initialized = 0; | ||
750 | |||
751 | if (id == SYS_HOTSWAP_INSERTED) | ||
752 | { | ||
753 | enable_controller(true); | ||
754 | rc = sd_init_card(); | ||
755 | enable_controller(false); | ||
756 | } | ||
757 | |||
758 | mutex_unlock(&sd_mtx); | ||
759 | break; | ||
760 | #endif /* HAVE_HOTSWAP */ | ||
761 | default: | ||
762 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
763 | STORAGE_SD); | ||
764 | break; | ||
765 | } | ||
766 | |||
767 | return rc; | ||
768 | } | ||
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h index 7ca7d77c4f..5403b2418a 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h +++ b/firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h | |||
@@ -21,10 +21,6 @@ | |||
21 | #ifndef ATA_TARGET_H | 21 | #ifndef ATA_TARGET_H |
22 | #define ATA_TARGET_H | 22 | #define ATA_TARGET_H |
23 | 23 | ||
24 | #ifdef BOOTLOADER | ||
25 | #define ATA_DRIVER_CLOSE | ||
26 | #endif | ||
27 | |||
28 | /* Plain C read & write loops */ | 24 | /* Plain C read & write loops */ |
29 | #define PREFER_C_READING | 25 | #define PREFER_C_READING |
30 | #define PREFER_C_WRITING | 26 | #define PREFER_C_WRITING |
diff --git a/firmware/target/arm/s3c2440/sd-s3c2440.c b/firmware/target/arm/s3c2440/sd-s3c2440.c index e8de3ac78d..2ff68aa4ee 100644 --- a/firmware/target/arm/s3c2440/sd-s3c2440.c +++ b/firmware/target/arm/s3c2440/sd-s3c2440.c | |||
@@ -21,11 +21,9 @@ | |||
21 | 21 | ||
22 | //#define SD_DEBUG | 22 | //#define SD_DEBUG |
23 | 23 | ||
24 | #include "sd.h" | ||
25 | #include "system.h" | 24 | #include "system.h" |
26 | #include <string.h> | 25 | #include <string.h> |
27 | #include "gcc_extensions.h" | 26 | #include "gcc_extensions.h" |
28 | #include "thread.h" | ||
29 | #include "panic.h" | 27 | #include "panic.h" |
30 | 28 | ||
31 | #ifdef SD_DEBUG | 29 | #ifdef SD_DEBUG |
@@ -33,8 +31,8 @@ | |||
33 | #endif | 31 | #endif |
34 | #ifdef HAVE_HOTSWAP | 32 | #ifdef HAVE_HOTSWAP |
35 | #include "sdmmc.h" | 33 | #include "sdmmc.h" |
36 | #include "disk.h" | ||
37 | #endif | 34 | #endif |
35 | #include "storage.h" | ||
38 | #include "dma-target.h" | 36 | #include "dma-target.h" |
39 | #include "system-target.h" | 37 | #include "system-target.h" |
40 | #include "led-mini2440.h" | 38 | #include "led-mini2440.h" |
@@ -90,6 +88,12 @@ struct sd_card_status | |||
90 | /* for compatibility */ | 88 | /* for compatibility */ |
91 | static long last_disk_activity = -1; | 89 | static long last_disk_activity = -1; |
92 | 90 | ||
91 | #ifdef CONFIG_STORAGE_MULTI | ||
92 | static int sd_first_drive = 0; | ||
93 | #else | ||
94 | #define sd_first_drive 0 | ||
95 | #endif | ||
96 | |||
93 | static bool initialized = false; | 97 | static bool initialized = false; |
94 | static bool sd_enabled = false; | 98 | static bool sd_enabled = false; |
95 | static long next_yield = 0; | 99 | static long next_yield = 0; |
@@ -109,11 +113,7 @@ static struct sd_card_status sd_status[NUM_CARDS] = | |||
109 | #endif | 113 | #endif |
110 | #endif | 114 | #endif |
111 | 115 | ||
112 | /* Shoot for around 75% usage */ | ||
113 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
114 | static const char sd_thread_name[] = "sd"; | ||
115 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 116 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
116 | static struct event_queue sd_queue; | ||
117 | static struct semaphore transfer_completion_signal; | 117 | static struct semaphore transfer_completion_signal; |
118 | static volatile unsigned int transfer_error[NUM_DRIVES]; | 118 | static volatile unsigned int transfer_error[NUM_DRIVES]; |
119 | /* align on cache line size */ | 119 | /* align on cache line size */ |
@@ -511,17 +511,13 @@ static inline bool card_detect_target(void) | |||
511 | 511 | ||
512 | static int sd1_oneshot_callback(struct timeout *tmo) | 512 | static int sd1_oneshot_callback(struct timeout *tmo) |
513 | { | 513 | { |
514 | (void)tmo; | ||
515 | |||
516 | /* This is called only if the state was stable for 300ms - check state | 514 | /* This is called only if the state was stable for 300ms - check state |
517 | * and post appropriate event. */ | 515 | * and post appropriate event. */ |
518 | if (card_detect_target()) | 516 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
519 | { | 517 | SYS_HOTSWAP_EXTRACTED, |
520 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 518 | sd_first_drive + CARD_NUM_SLOT); |
521 | } | ||
522 | else | ||
523 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
524 | return 0; | 519 | return 0; |
520 | (void)tmo; | ||
525 | } | 521 | } |
526 | 522 | ||
527 | void EINT8_23(void) | 523 | void EINT8_23(void) |
@@ -571,46 +567,6 @@ bool sd_removable(IF_MD_NONVOID(int card_no)) | |||
571 | #endif /* HAVE_HOTSWAP */ | 567 | #endif /* HAVE_HOTSWAP */ |
572 | /*****************************************************************************/ | 568 | /*****************************************************************************/ |
573 | 569 | ||
574 | static void sd_thread(void) NORETURN_ATTR; | ||
575 | static void sd_thread(void) | ||
576 | { | ||
577 | struct queue_event ev; | ||
578 | |||
579 | /* TODO */ | ||
580 | while (1) | ||
581 | { | ||
582 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
583 | switch ( ev.id ) | ||
584 | { | ||
585 | #ifdef HAVE_HOTSWAP | ||
586 | case SYS_HOTSWAP_INSERTED: | ||
587 | case SYS_HOTSWAP_EXTRACTED:; | ||
588 | int success = 1; | ||
589 | |||
590 | disk_unmount(0); /* release "by force" */ | ||
591 | |||
592 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
593 | |||
594 | /* Force card init for new card, re-init for re-inserted one or | ||
595 | * clear if the last attempt to init failed with an error. */ | ||
596 | card_info[0].initialized = 0; | ||
597 | |||
598 | /* Access is now safe */ | ||
599 | mutex_unlock(&sd_mtx); | ||
600 | |||
601 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
602 | success = disk_mount(0); /* 0 if fail */ | ||
603 | |||
604 | /* notify the system about the changed filesystems | ||
605 | */ | ||
606 | if (success) | ||
607 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
608 | break; | ||
609 | #endif /* HAVE_HOTSWAP */ | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | static int sd_wait_for_state(const int card_no, unsigned int state) | 570 | static int sd_wait_for_state(const int card_no, unsigned int state) |
615 | { | 571 | { |
616 | unsigned long response = 0; | 572 | unsigned long response = 0; |
@@ -907,9 +863,6 @@ int sd_init(void) | |||
907 | semaphore_init(&transfer_completion_signal, 1, 0); | 863 | semaphore_init(&transfer_completion_signal, 1, 0); |
908 | /* init mutex */ | 864 | /* init mutex */ |
909 | mutex_init(&sd_mtx); | 865 | mutex_init(&sd_mtx); |
910 | queue_init(&sd_queue, true); | ||
911 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
912 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
913 | 866 | ||
914 | uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]); | 867 | uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]); |
915 | 868 | ||
@@ -950,18 +903,11 @@ tCardInfo *card_get_info_target(int card_no) | |||
950 | int sd_num_drives(int first_drive) | 903 | int sd_num_drives(int first_drive) |
951 | { | 904 | { |
952 | dbgprintf ("sd_num_drv"); | 905 | dbgprintf ("sd_num_drv"); |
953 | #if 0 | ||
954 | /* Store which logical drive number(s) we have been assigned */ | 906 | /* Store which logical drive number(s) we have been assigned */ |
955 | sd_first_drive = first_drive; | 907 | sd_first_drive = first_drive; |
956 | #endif | ||
957 | |||
958 | return NUM_CARDS; | 908 | return NUM_CARDS; |
959 | } | 909 | } |
960 | 910 | ||
961 | void sd_sleepnow(void) | ||
962 | { | ||
963 | } | ||
964 | |||
965 | bool sd_disk_is_active(void) | 911 | bool sd_disk_is_active(void) |
966 | { | 912 | { |
967 | return false; | 913 | return false; |
@@ -980,3 +926,27 @@ int sd_spinup_time(void) | |||
980 | #endif /* CONFIG_STORAGE_MULTI */ | 926 | #endif /* CONFIG_STORAGE_MULTI */ |
981 | /*****************************************************************************/ | 927 | /*****************************************************************************/ |
982 | 928 | ||
929 | int sd_event(long id, intptr_t data) | ||
930 | { | ||
931 | int rc = 0; | ||
932 | |||
933 | switch (id) | ||
934 | { | ||
935 | #ifdef HAVE_HOTSWAP | ||
936 | case SYS_HOTSWAP_INSERTED: | ||
937 | case SYS_HOTSWAP_EXTRACTED: | ||
938 | mutex_lock(&sd_mtx); | ||
939 | /* Force card init for new card, re-init for re-inserted one or | ||
940 | * clear if the last attempt to init failed with an error. */ | ||
941 | card_info[data].initialized = 0; | ||
942 | mutex_unlock(&sd_mtx); | ||
943 | break; | ||
944 | #endif /* HAVE_HOTSWAP */ | ||
945 | default: | ||
946 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
947 | STORAGE_SD); | ||
948 | break; | ||
949 | } | ||
950 | |||
951 | return rc; | ||
952 | } | ||
diff --git a/firmware/target/arm/s5l8700/ata-nand-s5l8700.c b/firmware/target/arm/s5l8700/ata-nand-s5l8700.c index 227f6b703b..7f68b82a0d 100644 --- a/firmware/target/arm/s5l8700/ata-nand-s5l8700.c +++ b/firmware/target/arm/s5l8700/ata-nand-s5l8700.c | |||
@@ -52,7 +52,6 @@ void nand_spindown(int seconds) | |||
52 | 52 | ||
53 | void nand_sleep(void) | 53 | void nand_sleep(void) |
54 | { | 54 | { |
55 | nand_power_down(); | ||
56 | } | 55 | } |
57 | 56 | ||
58 | void nand_sleepnow(void) | 57 | void nand_sleepnow(void) |
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c index 1698dc2b9b..4b74405c1c 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c | |||
@@ -31,8 +31,7 @@ | |||
31 | #include <mmu-arm.h> | 31 | #include <mmu-arm.h> |
32 | #include <string.h> | 32 | #include <string.h> |
33 | #include "led.h" | 33 | #include "led.h" |
34 | #include "ata_idle_notify.h" | 34 | #include "storage.h" |
35 | |||
36 | 35 | ||
37 | #define NAND_CMD_READ 0x00 | 36 | #define NAND_CMD_READ 0x00 |
38 | #define NAND_CMD_PROGCNFRM 0x10 | 37 | #define NAND_CMD_PROGCNFRM 0x10 |
@@ -91,7 +90,6 @@ static int nand_powered = 0; | |||
91 | static int nand_interleaved = 0; | 90 | static int nand_interleaved = 0; |
92 | static int nand_cached = 0; | 91 | static int nand_cached = 0; |
93 | static long nand_last_activity_value = -1; | 92 | static long nand_last_activity_value = -1; |
94 | static long nand_stack[DEFAULT_STACK_SIZE]; | ||
95 | 93 | ||
96 | static struct mutex nand_mtx; | 94 | static struct mutex nand_mtx; |
97 | static struct semaphore nand_complete; | 95 | static struct semaphore nand_complete; |
@@ -359,20 +357,22 @@ void nand_power_up(void) | |||
359 | 357 | ||
360 | void nand_power_down(void) | 358 | void nand_power_down(void) |
361 | { | 359 | { |
362 | if (!nand_powered) return; | ||
363 | mutex_lock(&nand_mtx); | 360 | mutex_lock(&nand_mtx); |
364 | pmu_ldo_power_off(4); | 361 | if (nand_powered) |
365 | PCON2 = 0x11111111; | 362 | { |
366 | PDAT2 = 0; | 363 | pmu_ldo_power_off(4); |
367 | PCON3 = 0x11111111; | 364 | PCON2 = 0x11111111; |
368 | PDAT3 = 0; | 365 | PDAT2 = 0; |
369 | PCON4 = 0x11111111; | 366 | PCON3 = 0x11111111; |
370 | PDAT4 = 0; | 367 | PDAT3 = 0; |
371 | PCON5 = (PCON5 & ~0xF) | 1; | 368 | PCON4 = 0x11111111; |
372 | PUNK5 = 1; | 369 | PDAT4 = 0; |
373 | PWRCONEXT |= 0x40; | 370 | PCON5 = (PCON5 & ~0xF) | 1; |
374 | PWRCON |= 0x100000; | 371 | PUNK5 = 1; |
375 | nand_powered = 0; | 372 | PWRCONEXT |= 0x40; |
373 | PWRCON |= 0x100000; | ||
374 | nand_powered = 0; | ||
375 | } | ||
376 | mutex_unlock(&nand_mtx); | 376 | mutex_unlock(&nand_mtx); |
377 | } | 377 | } |
378 | 378 | ||
@@ -714,20 +714,6 @@ const struct nand_device_info_type* nand_get_device_type(uint32_t bank) | |||
714 | return &nand_deviceinfotable[nand_type[bank]]; | 714 | return &nand_deviceinfotable[nand_type[bank]]; |
715 | } | 715 | } |
716 | 716 | ||
717 | static void nand_thread(void) | ||
718 | { | ||
719 | while (1) | ||
720 | { | ||
721 | if (TIME_AFTER(current_tick, nand_last_activity_value + HZ / 5) | ||
722 | && nand_powered) | ||
723 | { | ||
724 | call_storage_idle_notifys(false); | ||
725 | nand_power_down(); | ||
726 | } | ||
727 | sleep(HZ / 10); | ||
728 | } | ||
729 | } | ||
730 | |||
731 | int nand_device_init(void) | 717 | int nand_device_init(void) |
732 | { | 718 | { |
733 | mutex_init(&nand_mtx); | 719 | mutex_init(&nand_mtx); |
@@ -776,10 +762,30 @@ int nand_device_init(void) | |||
776 | nand_cached = ((nand_deviceinfotable[nand_type[0]].id >> 23) & 1); | 762 | nand_cached = ((nand_deviceinfotable[nand_type[0]].id >> 23) & 1); |
777 | 763 | ||
778 | nand_last_activity_value = current_tick; | 764 | nand_last_activity_value = current_tick; |
779 | create_thread(nand_thread, nand_stack, | ||
780 | sizeof(nand_stack), 0, "nand" | ||
781 | IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
782 | IF_COP(, CPU)); | ||
783 | |||
784 | return 0; | 765 | return 0; |
785 | } | 766 | } |
767 | |||
768 | int nand_event(long id, intptr_t data) | ||
769 | { | ||
770 | int rc = 0; | ||
771 | |||
772 | if (LIKELY(id == Q_STORAGE_TICK)) | ||
773 | { | ||
774 | if (!nand_powered || | ||
775 | TIME_BEFORE(current_tick, nand_last_activity_value + HZ / 5)) | ||
776 | { | ||
777 | STG_EVENT_ASSERT_ACTIVE(STORAGE_NAND); | ||
778 | } | ||
779 | } | ||
780 | else if (id == Q_STORAGE_SLEEPNOW) | ||
781 | { | ||
782 | nand_power_down(); | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | rc = storage_event_default_handler(id, data, nand_last_activity_value, | ||
787 | STORAGE_NAND); | ||
788 | } | ||
789 | |||
790 | return rc; | ||
791 | } | ||
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c index ef39a5cabb..36d119aff3 100644 --- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c | |||
@@ -19,8 +19,6 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "config.h" | 21 | #include "config.h" |
22 | #include "thread.h" | ||
23 | #include "disk.h" | ||
24 | #include "storage.h" | 22 | #include "storage.h" |
25 | #include "timer.h" | 23 | #include "timer.h" |
26 | #include "kernel.h" | 24 | #include "kernel.h" |
@@ -31,8 +29,6 @@ | |||
31 | #include "mmcdefs-target.h" | 29 | #include "mmcdefs-target.h" |
32 | #include "s5l8702.h" | 30 | #include "s5l8702.h" |
33 | #include "led.h" | 31 | #include "led.h" |
34 | #include "ata_idle_notify.h" | ||
35 | #include "disk_cache.h" | ||
36 | 32 | ||
37 | 33 | ||
38 | #ifndef ATA_RETRIES | 34 | #ifndef ATA_RETRIES |
@@ -58,7 +54,6 @@ static struct semaphore ata_wakeup; | |||
58 | static uint32_t ata_dma_flags; | 54 | static uint32_t ata_dma_flags; |
59 | static long ata_last_activity_value = -1; | 55 | static long ata_last_activity_value = -1; |
60 | static long ata_sleep_timeout = 20 * HZ; | 56 | static long ata_sleep_timeout = 20 * HZ; |
61 | static uint32_t ata_stack[(DEFAULT_STACK_SIZE + 0x400) / 4]; | ||
62 | static bool ata_powered; | 57 | static bool ata_powered; |
63 | static const int ata_retries = ATA_RETRIES; | 58 | static const int ata_retries = ATA_RETRIES; |
64 | static const bool ata_error_srst = true; | 59 | static const bool ata_error_srst = true; |
@@ -889,21 +884,6 @@ static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool wr | |||
889 | return 0; | 884 | return 0; |
890 | } | 885 | } |
891 | 886 | ||
892 | static void ata_thread(void) | ||
893 | { | ||
894 | while (true) | ||
895 | { | ||
896 | mutex_lock(&ata_mutex); | ||
897 | if (TIME_AFTER(current_tick, ata_last_activity_value + ata_sleep_timeout) && ata_powered) | ||
898 | { | ||
899 | call_storage_idle_notifys(false); | ||
900 | ata_power_down(); | ||
901 | } | ||
902 | mutex_unlock(&ata_mutex); | ||
903 | sleep(HZ / 2); | ||
904 | } | ||
905 | } | ||
906 | |||
907 | /* API Functions */ | 887 | /* API Functions */ |
908 | int ata_soft_reset(void) | 888 | int ata_soft_reset(void) |
909 | { | 889 | { |
@@ -982,11 +962,6 @@ void ata_spindown(int seconds) | |||
982 | ata_sleep_timeout = seconds * HZ; | 962 | ata_sleep_timeout = seconds * HZ; |
983 | } | 963 | } |
984 | 964 | ||
985 | void ata_sleep(void) | ||
986 | { | ||
987 | ata_last_activity_value = current_tick - ata_sleep_timeout + HZ / 5; | ||
988 | } | ||
989 | |||
990 | void ata_sleepnow(void) | 965 | void ata_sleepnow(void) |
991 | { | 966 | { |
992 | mutex_lock(&ata_mutex); | 967 | mutex_lock(&ata_mutex); |
@@ -994,11 +969,6 @@ void ata_sleepnow(void) | |||
994 | mutex_unlock(&ata_mutex); | 969 | mutex_unlock(&ata_mutex); |
995 | } | 970 | } |
996 | 971 | ||
997 | void ata_close(void) | ||
998 | { | ||
999 | ata_sleepnow(); | ||
1000 | } | ||
1001 | |||
1002 | void ata_spin(void) | 972 | void ata_spin(void) |
1003 | { | 973 | { |
1004 | ata_set_active(); | 974 | ata_set_active(); |
@@ -1034,10 +1004,6 @@ int ata_init(void) | |||
1034 | mutex_unlock(&ata_mutex); | 1004 | mutex_unlock(&ata_mutex); |
1035 | if (IS_ERR(rc)) return rc; | 1005 | if (IS_ERR(rc)) return rc; |
1036 | 1006 | ||
1037 | create_thread(ata_thread, ata_stack, | ||
1038 | sizeof(ata_stack), 0, "ATA idle monitor" | ||
1039 | IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
1040 | IF_COP(, CPU)); | ||
1041 | return 0; | 1007 | return 0; |
1042 | } | 1008 | } |
1043 | 1009 | ||
@@ -1129,3 +1095,38 @@ void INT_MMC(void) | |||
1129 | SDCI_IRQ = irq; | 1095 | SDCI_IRQ = irq; |
1130 | } | 1096 | } |
1131 | 1097 | ||
1098 | int ata_event(long id, intptr_t data) | ||
1099 | { | ||
1100 | int rc = 0; | ||
1101 | |||
1102 | /* GCC does a lousy job culling unreachable cases in the default handler | ||
1103 | if statements are in a switch statement, so we'll do it this way. Only | ||
1104 | the first case is frequently hit anyway. */ | ||
1105 | if (LIKELY(id == Q_STORAGE_TICK)) | ||
1106 | { | ||
1107 | if (!ata_powered || | ||
1108 | TIME_BEFORE(current_tick, ata_last_activity_value + ata_sleep_timeout)) | ||
1109 | { | ||
1110 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); | ||
1111 | } | ||
1112 | } | ||
1113 | else if (id == Q_STORAGE_SLEEPNOW) | ||
1114 | { | ||
1115 | ata_sleepnow(); | ||
1116 | } | ||
1117 | else if (id == Q_STORAGE_SLEEP) | ||
1118 | { | ||
1119 | ata_last_activity_value = current_tick - ata_sleep_timeout + HZ / 5; | ||
1120 | } | ||
1121 | else if (id == SYS_USB_CONNECTED) | ||
1122 | { | ||
1123 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); | ||
1124 | } | ||
1125 | else | ||
1126 | { | ||
1127 | rc = storage_event_default_handler(id, data, ata_last_activity_value, | ||
1128 | STORAGE_ATA); | ||
1129 | } | ||
1130 | |||
1131 | return rc; | ||
1132 | } | ||
diff --git a/firmware/target/arm/tcc780x/sd-tcc780x.c b/firmware/target/arm/tcc780x/sd-tcc780x.c index ba98539157..c80c3b746f 100644 --- a/firmware/target/arm/tcc780x/sd-tcc780x.c +++ b/firmware/target/arm/tcc780x/sd-tcc780x.c | |||
@@ -19,17 +19,13 @@ | |||
19 | * KIND, either express or implied. | 19 | * KIND, either express or implied. |
20 | * | 20 | * |
21 | ****************************************************************************/ | 21 | ****************************************************************************/ |
22 | #include "sd.h" | 22 | #include "config.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include <string.h> | 24 | #include <string.h> |
25 | #include "gcc_extensions.h" | 25 | #include "gcc_extensions.h" |
26 | #include "sdmmc.h" | 26 | #include "sdmmc.h" |
27 | #include "storage.h" | 27 | #include "storage.h" |
28 | #include "led.h" | 28 | #include "led.h" |
29 | #include "thread.h" | ||
30 | #include "disk.h" | ||
31 | #include "ata_idle_notify.h" | ||
32 | #include "usb.h" | ||
33 | 29 | ||
34 | #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP) | 30 | #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP) |
35 | #define CARD_NUM_INTERNAL 0 | 31 | #define CARD_NUM_INTERNAL 0 |
@@ -55,9 +51,6 @@ | |||
55 | /* for compatibility */ | 51 | /* for compatibility */ |
56 | static long last_disk_activity = -1; | 52 | static long last_disk_activity = -1; |
57 | 53 | ||
58 | /** static, private data **/ | ||
59 | static bool initialized = false; | ||
60 | |||
61 | static long next_yield = 0; | 54 | static long next_yield = 0; |
62 | #define MIN_YIELD_PERIOD 1000 | 55 | #define MIN_YIELD_PERIOD 1000 |
63 | 56 | ||
@@ -80,14 +73,13 @@ static struct sd_card_status sd_status[NUM_DRIVES] = | |||
80 | #endif | 73 | #endif |
81 | }; | 74 | }; |
82 | 75 | ||
83 | /* Shoot for around 75% usage */ | ||
84 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
85 | static const char sd_thread_name[] = "sd"; | ||
86 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 76 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
87 | static struct event_queue sd_queue; | ||
88 | 77 | ||
78 | #ifdef CONFIG_STORAGE_MULTI | ||
89 | static int sd_first_drive = 0; | 79 | static int sd_first_drive = 0; |
90 | 80 | #else | |
81 | #define sd_first_drive 0 | ||
82 | #endif | ||
91 | 83 | ||
92 | static bool sd_poll_status(unsigned int trigger, long timeout) | 84 | static bool sd_poll_status(unsigned int trigger, long timeout) |
93 | { | 85 | { |
@@ -216,16 +208,13 @@ static inline bool card_detect_target(void) | |||
216 | 208 | ||
217 | static int sd1_oneshot_callback(struct timeout *tmo) | 209 | static int sd1_oneshot_callback(struct timeout *tmo) |
218 | { | 210 | { |
219 | (void)tmo; | ||
220 | |||
221 | /* This is called only if the state was stable for 300ms - check state | 211 | /* This is called only if the state was stable for 300ms - check state |
222 | * and post appropriate event. */ | 212 | * and post appropriate event. */ |
223 | if (card_detect_target()) | 213 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
224 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 214 | SYS_HOTSWAP_EXTRACTED, |
225 | else | 215 | sd_first_drive + CARD_NUM_SLOT); |
226 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
227 | |||
228 | return 0; | 216 | return 0; |
217 | (void)tmo; | ||
229 | } | 218 | } |
230 | 219 | ||
231 | void EXT0(void) | 220 | void EXT0(void) |
@@ -642,71 +631,6 @@ sd_write_error: | |||
642 | } | 631 | } |
643 | } | 632 | } |
644 | 633 | ||
645 | static void sd_thread(void) NORETURN_ATTR; | ||
646 | static void sd_thread(void) | ||
647 | { | ||
648 | struct queue_event ev; | ||
649 | bool idle_notified = false; | ||
650 | |||
651 | while (1) | ||
652 | { | ||
653 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
654 | |||
655 | switch ( ev.id ) | ||
656 | { | ||
657 | #ifdef HAVE_HOTSWAP | ||
658 | case SYS_HOTSWAP_INSERTED: | ||
659 | case SYS_HOTSWAP_EXTRACTED:; | ||
660 | int success = 1; | ||
661 | |||
662 | /* Release "by force" */ | ||
663 | disk_unmount(sd_first_drive + CARD_NUM_SLOT); | ||
664 | |||
665 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
666 | |||
667 | /* Force card init for new card, re-init for re-inserted one or | ||
668 | * clear if the last attempt to init failed with an error. */ | ||
669 | card_info[CARD_NUM_SLOT].initialized = 0; | ||
670 | sd_status[CARD_NUM_SLOT].retry = 0; | ||
671 | |||
672 | mutex_unlock(&sd_mtx); | ||
673 | |||
674 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
675 | success = disk_mount(sd_first_drive + CARD_NUM_SLOT); | ||
676 | |||
677 | if (success) | ||
678 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
679 | |||
680 | break; | ||
681 | #endif /* HAVE_HOTSWAP */ | ||
682 | |||
683 | case SYS_TIMEOUT: | ||
684 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
685 | { | ||
686 | idle_notified = false; | ||
687 | } | ||
688 | else | ||
689 | { | ||
690 | /* never let a timer wrap confuse us */ | ||
691 | next_yield = USEC_TIMER; | ||
692 | |||
693 | if (!idle_notified) | ||
694 | { | ||
695 | call_storage_idle_notifys(false); | ||
696 | idle_notified = true; | ||
697 | } | ||
698 | } | ||
699 | break; | ||
700 | |||
701 | case SYS_USB_CONNECTED: | ||
702 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
703 | /* Wait until the USB cable is extracted again */ | ||
704 | usb_wait_for_disconnect(&sd_queue); | ||
705 | break; | ||
706 | } | ||
707 | } | ||
708 | } | ||
709 | |||
710 | void sd_enable(bool on) | 634 | void sd_enable(bool on) |
711 | { | 635 | { |
712 | if(on) | 636 | if(on) |
@@ -725,6 +649,7 @@ void sd_enable(bool on) | |||
725 | 649 | ||
726 | int sd_init(void) | 650 | int sd_init(void) |
727 | { | 651 | { |
652 | static bool initialized = false; | ||
728 | int ret = 0; | 653 | int ret = 0; |
729 | 654 | ||
730 | if (!initialized) | 655 | if (!initialized) |
@@ -752,11 +677,6 @@ int sd_init(void) | |||
752 | /* Configure card power(?) GPIO as output */ | 677 | /* Configure card power(?) GPIO as output */ |
753 | GPIOC_DIR |= (1<<24); | 678 | GPIOC_DIR |= (1<<24); |
754 | 679 | ||
755 | queue_init(&sd_queue, true); | ||
756 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
757 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
758 | IF_COP(, CPU)); | ||
759 | |||
760 | sleep(HZ/10); | 680 | sleep(HZ/10); |
761 | 681 | ||
762 | #ifdef HAVE_HOTSWAP | 682 | #ifdef HAVE_HOTSWAP |
@@ -794,10 +714,6 @@ int sd_num_drives(int first_drive) | |||
794 | #endif | 714 | #endif |
795 | } | 715 | } |
796 | 716 | ||
797 | void sd_sleepnow(void) | ||
798 | { | ||
799 | } | ||
800 | |||
801 | bool sd_disk_is_active(void) | 717 | bool sd_disk_is_active(void) |
802 | { | 718 | { |
803 | return false; | 719 | return false; |
@@ -814,3 +730,28 @@ int sd_spinup_time(void) | |||
814 | } | 730 | } |
815 | 731 | ||
816 | #endif /* CONFIG_STORAGE_MULTI */ | 732 | #endif /* CONFIG_STORAGE_MULTI */ |
733 | |||
734 | int sd_event(long id, intptr_t data) | ||
735 | { | ||
736 | int rc = 0; | ||
737 | |||
738 | switch (id) | ||
739 | { | ||
740 | #ifdef HAVE_HOTSWAP | ||
741 | case SYS_HOTSWAP_INSERTED: | ||
742 | case SYS_HOTSWAP_EXTRACTED: | ||
743 | mutex_lock(&sd_mtx); | ||
744 | /* Force card init for new card, re-init for re-inserted one or | ||
745 | * clear if the last attempt to init failed with an error. */ | ||
746 | card_info[data].initialized = 0; | ||
747 | sd_status[data].retry = 0; | ||
748 | mutex_unlock(&sd_mtx); | ||
749 | break; | ||
750 | #endif /* HAVE_HOTSWAP */ | ||
751 | default: | ||
752 | rc = storage_event_default_handler(id, data, last_disk_activity, STORAGE_SD); | ||
753 | break; | ||
754 | } | ||
755 | |||
756 | return rc; | ||
757 | } | ||
diff --git a/firmware/target/arm/tms320dm320/sdmmc-dm320.c b/firmware/target/arm/tms320dm320/sdmmc-dm320.c index a6e261bcfa..8818d645d8 100644 --- a/firmware/target/arm/tms320dm320/sdmmc-dm320.c +++ b/firmware/target/arm/tms320dm320/sdmmc-dm320.c | |||
@@ -19,13 +19,10 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "sd.h" | ||
23 | #include "system.h" | 22 | #include "system.h" |
24 | #include <string.h> | 23 | #include <string.h> |
25 | #include "gcc_extensions.h" | 24 | #include "gcc_extensions.h" |
26 | #include "thread.h" | ||
27 | #include "panic.h" | 25 | #include "panic.h" |
28 | #include "kernel.h" | ||
29 | #include "dma-target.h" | 26 | #include "dma-target.h" |
30 | #include "ata_idle_notify.h" | 27 | #include "ata_idle_notify.h" |
31 | 28 | ||
@@ -42,8 +39,8 @@ | |||
42 | #endif | 39 | #endif |
43 | #endif | 40 | #endif |
44 | #include "sdmmc.h" | 41 | #include "sdmmc.h" |
45 | #include "disk.h" | ||
46 | #include "system-target.h" | 42 | #include "system-target.h" |
43 | #include "storage.h" | ||
47 | 44 | ||
48 | /* The configuration method is not very flexible. */ | 45 | /* The configuration method is not very flexible. */ |
49 | #define CARD_NUM_SLOT 1 | 46 | #define CARD_NUM_SLOT 1 |
@@ -105,7 +102,6 @@ struct sd_card_status | |||
105 | static long last_disk_activity = -1; | 102 | static long last_disk_activity = -1; |
106 | 103 | ||
107 | static bool initialized = false; | 104 | static bool initialized = false; |
108 | static unsigned int sd_thread_id = 0; | ||
109 | 105 | ||
110 | static bool sd_enabled = false; | 106 | static bool sd_enabled = false; |
111 | static long next_yield = 0; | 107 | static long next_yield = 0; |
@@ -122,10 +118,7 @@ static struct sd_card_status sd_status[NUM_CARDS] = | |||
122 | }; | 118 | }; |
123 | 119 | ||
124 | /* Shoot for around 75% usage */ | 120 | /* Shoot for around 75% usage */ |
125 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
126 | static const char sd_thread_name[] = "sd"; | ||
127 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 121 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
128 | static struct event_queue sd_queue; | ||
129 | static volatile unsigned int transfer_error[NUM_DRIVES]; | 122 | static volatile unsigned int transfer_error[NUM_DRIVES]; |
130 | /* align on cache line size */ | 123 | /* align on cache line size */ |
131 | static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE] | 124 | static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE] |
@@ -154,20 +147,16 @@ static void sd_card_mux(int card_no) | |||
154 | #endif | 147 | #endif |
155 | } | 148 | } |
156 | 149 | ||
150 | static inline void enable_controller(bool on) | ||
151 | { | ||
152 | sd_enabled = on; | ||
153 | } | ||
157 | 154 | ||
158 | void sd_enable(bool on) | 155 | void sd_enable(bool on) |
159 | { | 156 | { |
160 | if (sd_enabled == on) | 157 | mutex_lock(&sd_mtx); |
161 | return; /* nothing to do */ | 158 | enable_controller(on); |
162 | 159 | mutex_unlock(&sd_mtx); | |
163 | if (on) | ||
164 | { | ||
165 | sd_enabled = true; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | sd_enabled = false; | ||
170 | } | ||
171 | } | 160 | } |
172 | 161 | ||
173 | /* sets clock rate just like OF does */ | 162 | /* sets clock rate just like OF does */ |
@@ -514,17 +503,13 @@ static inline bool card_detect_target(void) | |||
514 | 503 | ||
515 | static int sd1_oneshot_callback(struct timeout *tmo) | 504 | static int sd1_oneshot_callback(struct timeout *tmo) |
516 | { | 505 | { |
517 | (void)tmo; | ||
518 | |||
519 | /* This is called only if the state was stable for 300ms - check state | 506 | /* This is called only if the state was stable for 300ms - check state |
520 | * and post appropriate event. */ | 507 | * and post appropriate event. */ |
521 | if (card_detect_target()) | 508 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
522 | { | 509 | SYS_HOTSWAP_EXTRACTED, |
523 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 510 | CARD_NUM_SLOT); |
524 | } | ||
525 | else | ||
526 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
527 | return 0; | 511 | return 0; |
512 | (void)tmo; | ||
528 | } | 513 | } |
529 | 514 | ||
530 | #ifdef SANSA_CONNECT | 515 | #ifdef SANSA_CONNECT |
@@ -577,57 +562,6 @@ bool sd_removable(IF_MD_NONVOID(int card_no)) | |||
577 | 562 | ||
578 | #endif /* HAVE_HOTSWAP */ | 563 | #endif /* HAVE_HOTSWAP */ |
579 | 564 | ||
580 | static void sd_thread(void) NORETURN_ATTR; | ||
581 | static void sd_thread(void) | ||
582 | { | ||
583 | struct queue_event ev; | ||
584 | bool idle_notified = false; | ||
585 | |||
586 | while (1) | ||
587 | { | ||
588 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
589 | switch ( ev.id ) | ||
590 | { | ||
591 | #ifdef HAVE_HOTSWAP | ||
592 | case SYS_HOTSWAP_INSERTED: | ||
593 | case SYS_HOTSWAP_EXTRACTED:; | ||
594 | int success = 1; | ||
595 | |||
596 | disk_unmount(0); /* release "by force" */ | ||
597 | |||
598 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
599 | |||
600 | /* Force card init for new card, re-init for re-inserted one or | ||
601 | * clear if the last attempt to init failed with an error. */ | ||
602 | card_info[0].initialized = 0; | ||
603 | |||
604 | mutex_unlock(&sd_mtx); | ||
605 | |||
606 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
607 | success = disk_mount(0); /* 0 if fail */ | ||
608 | |||
609 | /* notify the system about the changed filesystems */ | ||
610 | if (success) | ||
611 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
612 | |||
613 | break; | ||
614 | #endif /* HAVE_HOTSWAP */ | ||
615 | |||
616 | case SYS_TIMEOUT: | ||
617 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
618 | { | ||
619 | idle_notified = false; | ||
620 | } | ||
621 | else if (!idle_notified) | ||
622 | { | ||
623 | call_storage_idle_notifys(false); | ||
624 | idle_notified = true; | ||
625 | } | ||
626 | break; | ||
627 | } | ||
628 | } | ||
629 | } | ||
630 | |||
631 | static int sd_wait_for_state(unsigned int state) | 565 | static int sd_wait_for_state(unsigned int state) |
632 | { | 566 | { |
633 | unsigned long response = 0; | 567 | unsigned long response = 0; |
@@ -671,7 +605,7 @@ static int sd_transfer_sectors(int card_no, unsigned long start, | |||
671 | 605 | ||
672 | dbgprintf("transfer %d %d %d", card_no, start, count); | 606 | dbgprintf("transfer %d %d %d", card_no, start, count); |
673 | mutex_lock(&sd_mtx); | 607 | mutex_lock(&sd_mtx); |
674 | sd_enable(true); | 608 | enable_controller(true); |
675 | 609 | ||
676 | sd_transfer_retry: | 610 | sd_transfer_retry: |
677 | if (card_no == CARD_NUM_SLOT && !card_detect_target()) | 611 | if (card_no == CARD_NUM_SLOT && !card_detect_target()) |
@@ -812,7 +746,7 @@ sd_transfer_retry: | |||
812 | 746 | ||
813 | while (1) | 747 | while (1) |
814 | { | 748 | { |
815 | sd_enable(false); | 749 | enable_controller(false); |
816 | mutex_unlock(&sd_mtx); | 750 | mutex_unlock(&sd_mtx); |
817 | 751 | ||
818 | return ret; | 752 | return ret; |
@@ -860,14 +794,17 @@ int sd_init(void) | |||
860 | { | 794 | { |
861 | int ret = EC_OK; | 795 | int ret = EC_OK; |
862 | 796 | ||
863 | #ifndef BOOTLOADER | 797 | if (!initialized) |
864 | sd_enabled = true; | 798 | { |
865 | sd_enable(false); | 799 | mutex_init(&sd_mtx); |
866 | #endif | 800 | initialized = true; |
867 | mutex_init(&sd_mtx); | 801 | } |
868 | 802 | ||
869 | mutex_lock(&sd_mtx); | 803 | mutex_lock(&sd_mtx); |
870 | initialized = true; | 804 | |
805 | #ifndef BOOTLOADER | ||
806 | enable_controller(false); | ||
807 | #endif | ||
871 | 808 | ||
872 | /* based on linux/drivers/mmc/dm320mmc.c | 809 | /* based on linux/drivers/mmc/dm320mmc.c |
873 | Copyright (C) 2006 ZSI, All Rights Reserved. | 810 | Copyright (C) 2006 ZSI, All Rights Reserved. |
@@ -919,12 +856,6 @@ int sd_init(void) | |||
919 | 856 | ||
920 | /* Disable Memory Card CLK - it is enabled on demand by TMS320DM320 */ | 857 | /* Disable Memory Card CLK - it is enabled on demand by TMS320DM320 */ |
921 | bitclr16(&IO_MMC_MEM_CLK_CONTROL, (1 << 8)); | 858 | bitclr16(&IO_MMC_MEM_CLK_CONTROL, (1 << 8)); |
922 | |||
923 | queue_init(&sd_queue, true); | ||
924 | sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack), | ||
925 | 0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
926 | IF_COP(, CPU)); | ||
927 | |||
928 | mutex_unlock(&sd_mtx); | 859 | mutex_unlock(&sd_mtx); |
929 | 860 | ||
930 | return ret; | 861 | return ret; |
@@ -940,7 +871,27 @@ tCardInfo *card_get_info_target(int card_no) | |||
940 | return &card_info[card_no]; | 871 | return &card_info[card_no]; |
941 | } | 872 | } |
942 | 873 | ||
943 | void sd_sleepnow(void) | 874 | int sd_event(long id, intptr_t data) |
944 | { | 875 | { |
945 | } | 876 | int rc = 0; |
946 | 877 | ||
878 | switch (id) | ||
879 | { | ||
880 | #ifdef HAVE_HOTSWAP | ||
881 | case SYS_HOTSWAP_INSERTED: | ||
882 | case SYS_HOTSWAP_EXTRACTED: | ||
883 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
884 | /* Force card init for new card, re-init for re-inserted one or | ||
885 | * clear if the last attempt to init failed with an error. */ | ||
886 | card_info[data].initialized = 0; | ||
887 | mutex_unlock(&sd_mtx); | ||
888 | break; | ||
889 | #endif /* HAVE_HOTSWAP */ | ||
890 | default: | ||
891 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
892 | STORAGE_SD); | ||
893 | break; | ||
894 | } | ||
895 | |||
896 | return rc; | ||
897 | } | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c index 0e74444cf3..3ddbff0510 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c | |||
@@ -22,32 +22,23 @@ | |||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "gcc_extensions.h" | 23 | #include "gcc_extensions.h" |
24 | #include "jz4740.h" | 24 | #include "jz4740.h" |
25 | #include "ata.h" | ||
26 | #include "ata_idle_notify.h" | ||
27 | #include "ata-sd-target.h" | 25 | #include "ata-sd-target.h" |
28 | #include "disk.h" | ||
29 | #include "led.h" | 26 | #include "led.h" |
30 | #include "sdmmc.h" | 27 | #include "sdmmc.h" |
31 | #include "logf.h" | 28 | #include "logf.h" |
32 | #include "sd.h" | ||
33 | #include "system.h" | ||
34 | #include "kernel.h" | ||
35 | #include "storage.h" | 29 | #include "storage.h" |
36 | #include "string.h" | 30 | #include "string.h" |
37 | #include "usb.h" | ||
38 | 31 | ||
39 | static long last_disk_activity = -1; | 32 | static long last_disk_activity = -1; |
40 | #if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP) | 33 | #if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP) |
41 | static int sd_drive_nr = 0; | 34 | static int sd_drive_nr = 0; |
35 | #else | ||
36 | #define sd_drive_nr 0 | ||
42 | #endif | 37 | #endif |
43 | static tCardInfo card; | 38 | static tCardInfo card; |
44 | 39 | ||
45 | static long sd_stack[(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
46 | static const char sd_thread_name[] = "ata/sd"; | ||
47 | static struct event_queue sd_queue; | ||
48 | static struct mutex sd_mtx; | 40 | static struct mutex sd_mtx; |
49 | static struct semaphore sd_wakeup; | 41 | static struct semaphore sd_wakeup; |
50 | static void sd_thread(void) NORETURN_ATTR; | ||
51 | 42 | ||
52 | static int use_4bit; | 43 | static int use_4bit; |
53 | static int num_6; | 44 | static int num_6; |
@@ -1229,11 +1220,6 @@ int sd_init(void) | |||
1229 | { | 1220 | { |
1230 | semaphore_init(&sd_wakeup, 1, 0); | 1221 | semaphore_init(&sd_wakeup, 1, 0); |
1231 | mutex_init(&sd_mtx); | 1222 | mutex_init(&sd_mtx); |
1232 | queue_init(&sd_queue, true); | ||
1233 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
1234 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
1235 | IF_COP(, CPU)); | ||
1236 | |||
1237 | inited = true; | 1223 | inited = true; |
1238 | } | 1224 | } |
1239 | 1225 | ||
@@ -1265,7 +1251,7 @@ static inline void sd_stop_transfer(void) | |||
1265 | mutex_unlock(&sd_mtx); | 1251 | mutex_unlock(&sd_mtx); |
1266 | } | 1252 | } |
1267 | 1253 | ||
1268 | int sd_read_sectors(IF_MV(int drive,) unsigned long start, int count, void* buf) | 1254 | int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count, void* buf) |
1269 | { | 1255 | { |
1270 | #ifdef HAVE_MULTIVOLUME | 1256 | #ifdef HAVE_MULTIVOLUME |
1271 | (void)drive; | 1257 | (void)drive; |
@@ -1404,7 +1390,7 @@ int sd_soft_reset(void) | |||
1404 | } | 1390 | } |
1405 | 1391 | ||
1406 | #ifdef HAVE_HOTSWAP | 1392 | #ifdef HAVE_HOTSWAP |
1407 | bool sd_removable(IF_MV_NONVOID(int drive)) | 1393 | bool sd_removable(IF_MD_NONVOID(int drive)) |
1408 | { | 1394 | { |
1409 | #ifdef HAVE_MULTIVOLUME | 1395 | #ifdef HAVE_MULTIVOLUME |
1410 | (void)drive; | 1396 | (void)drive; |
@@ -1414,19 +1400,16 @@ bool sd_removable(IF_MV_NONVOID(int drive)) | |||
1414 | 1400 | ||
1415 | static int sd_oneshot_callback(struct timeout *tmo) | 1401 | static int sd_oneshot_callback(struct timeout *tmo) |
1416 | { | 1402 | { |
1417 | (void)tmo; | ||
1418 | int state = card_detect_target(); | 1403 | int state = card_detect_target(); |
1419 | 1404 | ||
1420 | /* This is called only if the state was stable for 300ms - check state | 1405 | /* This is called only if the state was stable for 300ms - check state |
1421 | * and post appropriate event. */ | 1406 | * and post appropriate event. */ |
1422 | if (state) | 1407 | queue_broadcast(state ? SYS_HOTSWAP_INSERTED : SYS_HOTSWAP_EXTRACTED, |
1423 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 1408 | sd_drive_nr); |
1424 | else | ||
1425 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
1426 | 1409 | ||
1427 | sd_gpio_setup_irq(state); | 1410 | sd_gpio_setup_irq(state); |
1428 | |||
1429 | return 0; | 1411 | return 0; |
1412 | (void)tmo; | ||
1430 | } | 1413 | } |
1431 | 1414 | ||
1432 | /* called on insertion/removal interrupt */ | 1415 | /* called on insertion/removal interrupt */ |
@@ -1453,58 +1436,27 @@ int sd_num_drives(int first_drive) | |||
1453 | } | 1436 | } |
1454 | #endif | 1437 | #endif |
1455 | 1438 | ||
1456 | static void sd_thread(void) | 1439 | int sd_event(long id, intptr_t data) |
1457 | { | 1440 | { |
1458 | struct queue_event ev; | 1441 | int rc = 0; |
1459 | bool idle_notified = false; | ||
1460 | 1442 | ||
1461 | while (1) | 1443 | switch (id) |
1462 | { | 1444 | { |
1463 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
1464 | |||
1465 | switch (ev.id) | ||
1466 | { | ||
1467 | #ifdef HAVE_HOTSWAP | 1445 | #ifdef HAVE_HOTSWAP |
1468 | case SYS_HOTSWAP_INSERTED: | 1446 | case SYS_HOTSWAP_INSERTED: |
1469 | case SYS_HOTSWAP_EXTRACTED:; | 1447 | case SYS_HOTSWAP_EXTRACTED: |
1470 | int success = 1; | 1448 | mutex_lock(&sd_mtx); /* lock-out card activity */ |
1471 | 1449 | /* Force card init for new card, re-init for re-inserted one or | |
1472 | disk_unmount(sd_drive_nr); /* release "by force" */ | 1450 | * clear if the last attempt to init failed with an error. */ |
1473 | 1451 | card.initialized = 0; | |
1474 | mutex_lock(&sd_mtx); /* lock-out card activity */ | 1452 | mutex_unlock(&sd_mtx); |
1475 | 1453 | break; | |
1476 | /* Force card init for new card, re-init for re-inserted one or | ||
1477 | * clear if the last attempt to init failed with an error. */ | ||
1478 | card.initialized = 0; | ||
1479 | |||
1480 | mutex_unlock(&sd_mtx); | ||
1481 | |||
1482 | if(ev.id == SYS_HOTSWAP_INSERTED) | ||
1483 | success = disk_mount(sd_drive_nr); /* 0 if fail */ | ||
1484 | |||
1485 | if(success) | ||
1486 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
1487 | |||
1488 | break; | ||
1489 | #endif /* HAVE_HOTSWAP */ | 1454 | #endif /* HAVE_HOTSWAP */ |
1490 | 1455 | default: | |
1491 | case SYS_TIMEOUT: | 1456 | rc = storage_event_default_handler(id, data, last_disk_activity, |
1492 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | 1457 | STORAGE_SD); |
1493 | idle_notified = false; | 1458 | break; |
1494 | else | ||
1495 | { | ||
1496 | if (!idle_notified) | ||
1497 | { | ||
1498 | call_storage_idle_notifys(false); | ||
1499 | idle_notified = true; | ||
1500 | } | ||
1501 | } | ||
1502 | break; | ||
1503 | case SYS_USB_CONNECTED: | ||
1504 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
1505 | /* Wait until the USB cable is extracted again */ | ||
1506 | usb_wait_for_disconnect(&sd_queue); | ||
1507 | break; | ||
1508 | } | ||
1509 | } | 1459 | } |
1460 | |||
1461 | return rc; | ||
1510 | } | 1462 | } |
diff --git a/firmware/target/sh/archos/ondio/ata_mmc.c b/firmware/target/sh/archos/ondio/ata_mmc.c index 5d95a0e789..f252e1c4ce 100644 --- a/firmware/target/sh/archos/ondio/ata_mmc.c +++ b/firmware/target/sh/archos/ondio/ata_mmc.c | |||
@@ -18,27 +18,29 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include <stdbool.h> | 21 | #include "config.h" |
22 | #include "mmc.h" | ||
23 | #include "ata_mmc.h" | 22 | #include "ata_mmc.h" |
24 | #include "sdmmc.h" | 23 | #include "sdmmc.h" |
25 | #include "ata_idle_notify.h" | ||
26 | #include "kernel.h" | 24 | #include "kernel.h" |
27 | #include "thread.h" | ||
28 | #include "led.h" | 25 | #include "led.h" |
29 | #include "sh7034.h" | 26 | #include "sh7034.h" |
30 | #include "system.h" | 27 | #include "system.h" |
31 | #include "debug.h" | 28 | #include "debug.h" |
32 | #include "panic.h" | 29 | #include "panic.h" |
33 | #include "usb.h" | ||
34 | #include "power.h" | 30 | #include "power.h" |
35 | #include "string.h" | 31 | #include "string.h" |
36 | #include "hwcompat.h" | 32 | #include "hwcompat.h" |
37 | #include "adc.h" | 33 | #include "adc.h" |
38 | #include "bitswap.h" | 34 | #include "bitswap.h" |
39 | #include "disk.h" /* for mount/unmount */ | ||
40 | #include "storage.h" | 35 | #include "storage.h" |
41 | 36 | ||
37 | |||
38 | #ifdef HAVE_MULTIDRIVE | ||
39 | #define MMC_NUM_DRIVES 2 | ||
40 | #else | ||
41 | #define MMC_NUM_DRIVES 1 | ||
42 | #endif | ||
43 | |||
42 | #define BLOCK_SIZE 512 /* fixed */ | 44 | #define BLOCK_SIZE 512 /* fixed */ |
43 | 45 | ||
44 | /* Command definitions */ | 46 | /* Command definitions */ |
@@ -90,15 +92,14 @@ static long last_disk_activity = -1; | |||
90 | 92 | ||
91 | /* private variables */ | 93 | /* private variables */ |
92 | 94 | ||
93 | static struct mutex mmc_mutex SHAREDBSS_ATTR; | 95 | #ifdef CONFIG_STORAGE_MULTI |
94 | 96 | static int mmc_first_drive = 0; | |
95 | #ifdef HAVE_HOTSWAP | ||
96 | static long mmc_stack[((DEFAULT_STACK_SIZE*2) + 0x800)/sizeof(long)]; | ||
97 | #else | 97 | #else |
98 | static long mmc_stack[(DEFAULT_STACK_SIZE*2)/sizeof(long)]; | 98 | #define mmc_first_drive 0 |
99 | #endif | 99 | #endif |
100 | static const char mmc_thread_name[] = "mmc"; | 100 | |
101 | static struct event_queue mmc_queue SHAREDBSS_ATTR; | 101 | static struct mutex mmc_mutex SHAREDBSS_ATTR; |
102 | |||
102 | static bool initialized = false; | 103 | static bool initialized = false; |
103 | static bool new_mmc_circuit; | 104 | static bool new_mmc_circuit; |
104 | 105 | ||
@@ -158,6 +159,21 @@ static void mmc_tick(void); | |||
158 | 159 | ||
159 | /* implementation */ | 160 | /* implementation */ |
160 | 161 | ||
162 | static void enable_controller(bool on) | ||
163 | { | ||
164 | PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIO, | ||
165 | * if not modified below */ | ||
166 | if (on) | ||
167 | PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */ | ||
168 | |||
169 | and_b(~0x80, &PADRL); /* assert flash reset */ | ||
170 | sleep(HZ/100); | ||
171 | or_b(0x80, &PADRL); /* de-assert flash reset */ | ||
172 | sleep(HZ/100); | ||
173 | card_info[0].initialized = false; | ||
174 | card_info[1].initialized = false; | ||
175 | } | ||
176 | |||
161 | void mmc_enable_int_flash_clock(bool on) | 177 | void mmc_enable_int_flash_clock(bool on) |
162 | { | 178 | { |
163 | /* Internal flash clock is enabled by setting PA12 high with the new | 179 | /* Internal flash clock is enabled by setting PA12 high with the new |
@@ -763,51 +779,6 @@ bool mmc_disk_is_active(void) | |||
763 | return mutex_test(&mmc_mutex); | 779 | return mutex_test(&mmc_mutex); |
764 | } | 780 | } |
765 | 781 | ||
766 | static void mmc_thread(void) | ||
767 | { | ||
768 | struct queue_event ev; | ||
769 | bool idle_notified = false; | ||
770 | |||
771 | while (1) { | ||
772 | queue_wait_w_tmo(&mmc_queue, &ev, HZ); | ||
773 | switch ( ev.id ) | ||
774 | { | ||
775 | case SYS_USB_CONNECTED: | ||
776 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
777 | /* Wait until the USB cable is extracted again */ | ||
778 | usb_wait_for_disconnect(&mmc_queue); | ||
779 | break; | ||
780 | |||
781 | #ifdef HAVE_HOTSWAP | ||
782 | case SYS_HOTSWAP_INSERTED: | ||
783 | disk_mount(1); /* mount MMC */ | ||
784 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
785 | break; | ||
786 | |||
787 | case SYS_HOTSWAP_EXTRACTED: | ||
788 | disk_unmount(1); /* release "by force" */ | ||
789 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
790 | break; | ||
791 | #endif | ||
792 | |||
793 | default: | ||
794 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
795 | { | ||
796 | idle_notified = false; | ||
797 | } | ||
798 | else | ||
799 | { | ||
800 | if (!idle_notified) | ||
801 | { | ||
802 | call_storage_idle_notifys(false); | ||
803 | idle_notified = true; | ||
804 | } | ||
805 | } | ||
806 | break; | ||
807 | } | ||
808 | } | ||
809 | } | ||
810 | |||
811 | bool mmc_detect(void) | 782 | bool mmc_detect(void) |
812 | { | 783 | { |
813 | return (adc_read(ADC_MMC_SWITCH) < 0x200); | 784 | return (adc_read(ADC_MMC_SWITCH) < 0x200); |
@@ -868,11 +839,11 @@ static void mmc_tick(void) | |||
868 | { | 839 | { |
869 | if (current_status) | 840 | if (current_status) |
870 | { | 841 | { |
871 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 842 | queue_broadcast(SYS_HOTSWAP_INSERTED, mmc_first_drive + 1); |
872 | } | 843 | } |
873 | else | 844 | else |
874 | { | 845 | { |
875 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | 846 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, mmc_first_drive + 1); |
876 | mmc_status = MMC_UNTOUCHED; | 847 | mmc_status = MMC_UNTOUCHED; |
877 | card_info[1].initialized = false; | 848 | card_info[1].initialized = false; |
878 | } | 849 | } |
@@ -882,17 +853,9 @@ static void mmc_tick(void) | |||
882 | 853 | ||
883 | void mmc_enable(bool on) | 854 | void mmc_enable(bool on) |
884 | { | 855 | { |
885 | PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIO, | 856 | mutex_lock(&mmc_mutex); |
886 | * if not modified below */ | 857 | enable_controller(on); |
887 | if (on) | 858 | mutex_unlock(&mmc_mutex); |
888 | PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */ | ||
889 | |||
890 | and_b(~0x80, &PADRL); /* assert flash reset */ | ||
891 | sleep(HZ/100); | ||
892 | or_b(0x80, &PADRL); /* de-assert flash reset */ | ||
893 | sleep(HZ/100); | ||
894 | card_info[0].initialized = false; | ||
895 | card_info[1].initialized = false; | ||
896 | } | 859 | } |
897 | 860 | ||
898 | int mmc_init(void) | 861 | int mmc_init(void) |
@@ -900,10 +863,8 @@ int mmc_init(void) | |||
900 | int rc = 0; | 863 | int rc = 0; |
901 | 864 | ||
902 | if (!initialized) | 865 | if (!initialized) |
903 | { | ||
904 | mutex_init(&mmc_mutex); | 866 | mutex_init(&mmc_mutex); |
905 | queue_init(&mmc_queue, true); | 867 | |
906 | } | ||
907 | mutex_lock(&mmc_mutex); | 868 | mutex_lock(&mmc_mutex); |
908 | led(false); | 869 | led(false); |
909 | 870 | ||
@@ -933,15 +894,10 @@ int mmc_init(void) | |||
933 | IPRE &= 0x0FFF; /* disable SCI1 interrupts for the CPU */ | 894 | IPRE &= 0x0FFF; /* disable SCI1 interrupts for the CPU */ |
934 | 895 | ||
935 | new_mmc_circuit = ((HW_MASK & MMC_CLOCK_POLARITY) != 0); | 896 | new_mmc_circuit = ((HW_MASK & MMC_CLOCK_POLARITY) != 0); |
936 | |||
937 | create_thread(mmc_thread, mmc_stack, | ||
938 | sizeof(mmc_stack), 0, mmc_thread_name | ||
939 | IF_PRIO(, PRIORITY_SYSTEM) | ||
940 | IF_COP(, CPU)); | ||
941 | tick_add_task(mmc_tick); | 897 | tick_add_task(mmc_tick); |
942 | initialized = true; | 898 | initialized = true; |
943 | } | 899 | } |
944 | mmc_enable(true); | 900 | enable_controller(true); |
945 | 901 | ||
946 | mutex_unlock(&mmc_mutex); | 902 | mutex_unlock(&mmc_mutex); |
947 | return rc; | 903 | return rc; |
@@ -998,11 +954,6 @@ bool mmc_present(IF_MD_NONVOID(int drive)) | |||
998 | } | 954 | } |
999 | #endif | 955 | #endif |
1000 | 956 | ||
1001 | |||
1002 | void mmc_sleep(void) | ||
1003 | { | ||
1004 | } | ||
1005 | |||
1006 | void mmc_spin(void) | 957 | void mmc_spin(void) |
1007 | { | 958 | { |
1008 | } | 959 | } |
@@ -1015,13 +966,13 @@ void mmc_spindown(int seconds) | |||
1015 | #ifdef CONFIG_STORAGE_MULTI | 966 | #ifdef CONFIG_STORAGE_MULTI |
1016 | int mmc_num_drives(int first_drive) | 967 | int mmc_num_drives(int first_drive) |
1017 | { | 968 | { |
1018 | /* We don't care which logical drive number(s) we have been assigned */ | 969 | mmc_first_drive = first_drive; |
1019 | (void)first_drive; | 970 | return MMC_NUM_DRIVES; |
1020 | 971 | } | |
1021 | #ifdef HAVE_MULTIDRIVE | 972 | #endif /* CONFIG_STORAGE_MULTI */ |
1022 | return 2; | 973 | |
1023 | #else | 974 | int mmc_event(long id, intptr_t data) |
1024 | return 1; | 975 | { |
1025 | #endif | 976 | return storage_event_default_handler(id, data, last_disk_activity, |
977 | STORAGE_MMC); | ||
1026 | } | 978 | } |
1027 | #endif | ||