summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-03-15 01:51:54 -0400
committerMichael Sevakis <jethead71@rockbox.org>2017-10-26 14:35:41 -0400
commit1654efc31339972d0e6bd41a499fcffc0a45822e (patch)
tree5fb7f59ab918a3694608bb1138c2c52fb47698c3 /firmware
parent7807934a271e9eb7b045cdcd89ba70fb59a91d69 (diff)
downloadrockbox-1654efc31339972d0e6bd41a499fcffc0a45822e.tar.gz
rockbox-1654efc31339972d0e6bd41a499fcffc0a45822e.zip
Unify storage threads into one
* Editing a bunch of drivers' thread routines in order to implement a new feature is tedious. * No matter the number of storage drivers, they share one thread. No extra threads needed for CONFIG_STORAGE_MULTI. * Each has an event callback called by the storage thread. * A default callback is provided to fake sleeping in order to trigger idle callbacks. It could also do other default processing. Changes to it will be part of driver code without editing each one. * Drivers may sleep and wake as they please as long as they give a low pulse on their storage bit to ask to go into sleep mode. Idle callback is called on its behalf and driver immediately put into sleep mode. * Drivers may indicate they are to continue receiving events in USB mode, otherwise they receve nothing until disconnect (they do receive SYS_USB_DISCONNECTED no matter what). * Rework a few things to keep the callback implementation sane and maintainable. ata.c was dreadful with all those bools; make it a state machine and easier to follow. Remove last_user_activity; it has no purpose that isn't served by keeping the disk active through last_disk_activity instead. * Even-out stack sizes partly because of a lack of a decent place to define them by driver or SoC or whatever; it doesn't seem too critical to do that anyway. Many are simply too large while at least one isn't really adequate. They may be individually overridden if necessary (figure out where). The thread uses the greatest size demanded. Newer file code is much more frugal with stack space. I barely see use crack 50% after idle callbacks (usually mid-40s). Card insert/eject doesn't demand much. * No forcing of idle callbacks. If it isn't necessary for one or more non-disk storage types, it really isn't any more necessary for disk storage. Besides, it makes the whole thing easier to implement. Change-Id: Id30c284d82a8af66e47f2cfe104c52cbd8aa7215
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/ata.c493
-rw-r--r--firmware/drivers/ramdisk.c5
-rw-r--r--firmware/export/ata.h4
-rw-r--r--firmware/export/ata_mmc.h2
-rw-r--r--firmware/export/sd.h2
-rw-r--r--firmware/export/storage.h78
-rw-r--r--firmware/storage.c383
-rw-r--r--firmware/target/arm/as3525/sd-as3525.c276
-rw-r--r--firmware/target/arm/as3525/sd-as3525v2.c188
-rw-r--r--firmware/target/arm/ata-nand-telechips.c6
-rw-r--r--firmware/target/arm/imx233/ata-target.h4
-rw-r--r--firmware/target/arm/imx233/sdmmc-imx233.c190
-rw-r--r--firmware/target/arm/imx31/ata-target.h4
-rw-r--r--firmware/target/arm/pp/ata-sd-pp.c274
-rw-r--r--firmware/target/arm/pp/ata-target.h4
-rw-r--r--firmware/target/arm/rk27xx/sd-rk27xx.c187
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h4
-rw-r--r--firmware/target/arm/s3c2440/sd-s3c2440.c100
-rw-r--r--firmware/target/arm/s5l8700/ata-nand-s5l8700.c1
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c76
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c69
-rw-r--r--firmware/target/arm/tcc780x/sd-tcc780x.c129
-rw-r--r--firmware/target/arm/tms320dm320/sdmmc-dm320.c139
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c96
-rw-r--r--firmware/target/sh/archos/ondio/ata_mmc.c139
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
78static 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
74enum {
75 ATA_BOOT = -1,
76 ATA_OFF,
77 ATA_SLEEPING,
78 ATA_SPINUP,
79 ATA_ON,
80};
81
82static int ata_state = ATA_BOOT;
83
85static struct mutex ata_mtx SHAREDBSS_ATTR; 84static struct mutex ata_mtx SHAREDBSS_ATTR;
86static int ata_device; /* device 0 (master) or 1 (slave) */ 85static int ata_device; /* device 0 (master) or 1 (slave) */
87 86
@@ -90,22 +89,16 @@ static int spinup_time = 0;
90static bool ata_led_enabled = true; 89static bool ata_led_enabled = true;
91static bool ata_led_on = false; 90static bool ata_led_on = false;
92#endif 91#endif
93static bool spinup = false; 92
94static bool sleeping = true;
95#ifdef HAVE_ATA_POWER_OFF
96static bool poweroff = false;
97#endif
98static long sleep_timeout = 5*HZ; 93static long sleep_timeout = 5*HZ;
99#ifdef HAVE_LBA48 94#ifdef HAVE_LBA48
100static bool lba48 = false; /* set for 48 bit addressing */ 95static bool lba48 = false; /* set for 48 bit addressing */
101#endif 96#endif
102static long ata_stack[(DEFAULT_STACK_SIZE*3)/sizeof(long)];
103static const char ata_thread_name[] = "ata";
104static struct event_queue ata_queue SHAREDBSS_ATTR;
105static bool initialized = false;
106 97
107static long last_user_activity = -1;
108static long last_disk_activity = -1; 98static long last_disk_activity = -1;
99#ifdef HAVE_ATA_POWER_OFF
100static long power_off_tick;
101#endif
109 102
110static unsigned long total_sectors; 103static unsigned long total_sectors;
111static int multisectors; /* number of supported multisectors */ 104static int multisectors; /* number of supported multisectors */
@@ -135,6 +128,38 @@ static int perform_soft_reset(void);
135static int set_multiple_mode(int sectors); 128static int set_multiple_mode(int sectors);
136static int set_features(void); 129static int set_features(void);
137 130
131static inline void keep_ata_active(void)
132{
133 last_disk_activity = current_tick;
134}
135
136static inline void schedule_ata_sleep(long from_now)
137{
138 last_disk_activity = current_tick - sleep_timeout + from_now;
139}
140
141static inline bool ata_sleep_timed_out(void)
142{
143 return sleep_timeout &&
144 TIME_AFTER(current_tick, last_disk_activity + sleep_timeout);
145}
146
147static 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
154static 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
139static ICODE_ATTR int wait_for_bsy(void) 164static 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
203static 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
221static 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
178static ICODE_ATTR int wait_for_start_of_transfer(void) 241static 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
515int ata_write_sectors(IF_MD(int drive,) 560int 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
529static int cache_sector(unsigned long sector) 577static int cache_sector(unsigned long sector)
@@ -748,178 +796,26 @@ void ata_spindown(int seconds)
748 796
749bool ata_disk_is_active(void) 797bool ata_disk_is_active(void)
750{ 798{
751 return !sleeping; 799 return ata_state >= ATA_SPINUP;
752}
753
754static 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
781void ata_sleep(void)
782{
783 queue_post(&ata_queue, Q_SLEEP, 0);
784} 800}
785 801
786void ata_sleepnow(void) 802void 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
797void ata_spin(void) 816void ata_spin(void)
798{ 817{
799 last_user_activity = current_tick; 818 keep_ata_active();
800}
801
802static 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
1026int ata_soft_reset(void) 922int 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
1073static int STORAGE_INIT_ATTR master_slave_detect(void) 971static 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(&sector_cache, 0, sizeof(sector_cache)); 1163 memset(&sector_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
1265error:
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
1378void 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)
1393void ata_set_led_enabled(bool enabled) 1271void 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 */
1455void ata_keep_active(void) 1333void 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
1347int 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
162int 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);
175int ata_read_smart(struct ata_smart_values*); 175int 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
24void mmc_enable_int_flash_clock(bool on); 26void mmc_enable_int_flash_clock(bool on);
25bool mmc_detect(void); 27bool mmc_detect(void);
26bool mmc_touched(void); 28bool 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
50enum
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
64static 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)
86int sd_event(long id, intptr_t data);
87#endif
88#if (CONFIG_STORAGE & STORAGE_MMC)
89int mmc_event(long id, intptr_t data);
90#endif
91#if (CONFIG_STORAGE & STORAGE_ATA)
92int ata_event(long id, intptr_t data);
93#endif
94#if (CONFIG_STORAGE & STORAGE_NAND)
95int nand_event(long id, intptr_t data);
96#endif
97#if (CONFIG_STORAGE & STORAGE_RAMDISK)
98int ramdisk_event(long id, intptr_t data);
99#endif
100
49struct storage_info 101struct 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
110int storage_init(void) STORAGE_INIT_ATTR;
111void 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 */
61static inline void stub_storage_sleep(void) {} 116static inline void stub_storage_sleep(void) {}
62static inline void stub_storage_spin(void) {} 117static inline void stub_storage_spin(void) {}
63static inline void stub_storage_spindown(int timeout) { (void)timeout; } 118static inline void stub_storage_spindown(int timeout) { (void)timeout; }
119static 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)
123void storage_sleep(void);
124#else
125static 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
236void storage_enable(bool on); 288void storage_enable(bool on);
237void storage_sleep(void);
238void storage_sleepnow(void); 289void storage_sleepnow(void);
239bool storage_disk_is_active(void); 290bool storage_disk_is_active(void);
240int storage_soft_reset(void); 291int storage_soft_reset(void);
241int storage_init(void) STORAGE_INIT_ATTR;
242int storage_flush(void); 292int storage_flush(void);
243void storage_spin(void); 293void storage_spin(void);
244void storage_spindown(int seconds); 294void 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
32static unsigned int storage_drivers[NUM_DRIVES]; 35static unsigned int storage_drivers[NUM_DRIVES];
33static unsigned int num_drives; 36static 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
36int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count, 66static struct event_queue storage_queue SHAREDBSS_ATTR;
37 void* buf) 67static 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) 69static 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
87static 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
78int 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; 109static 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
150static 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 157static 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
127static unsigned int storage_drivers[NUM_DRIVES]; 183#if (CONFIG_STORAGE & STORAGE_ATA)
128static unsigned int num_drives; 184 case Q_STORAGE_SLEEP:
185 storage_event_send(bdcast, ev.id, 0);
186 break;
187#endif
129 188
130int 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)
239void 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
135int storage_driver_type(int drive) 247#ifdef STORAGE_CLOSE
248void 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; 257static 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
144int storage_init(void) 271int 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
340int 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
209void 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
382int 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
232void 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
431static unsigned int storage_drivers[NUM_DRIVES];
432static unsigned int num_drives;
433
434int storage_num_drives(void)
435{
436 return num_drives;
437}
438
439int 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
448void 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
117static int sd_first_drive = 0;
118#else
119#define sd_first_drive 0
120#endif
121
122/* for compatibility */ 122/* for compatibility */
123static long last_disk_activity = -1; 123static long last_disk_activity = -1;
124 124
125#define MIN_YIELD_PERIOD 5 /* ticks */ 125#define MIN_YIELD_PERIOD 5 /* ticks */
126static long next_yield = 0; 126static long next_yield = 0;
127 127
128static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; 128static struct mutex sd_mtx;
129static const char sd_thread_name[] = "ata/sd";
130static struct mutex sd_mtx;
131static struct event_queue sd_queue;
132bool sd_enabled = false; 129bool 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
148static inline void mci_delay(void) { udelay(1000) ; } 145static inline void mci_delay(void) { udelay(1000) ; }
149 146
147static 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
151static inline bool card_detect_target(void) 201static 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
162static int sd1_oneshot_callback(struct timeout *tmo) 212static 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
178void sd_gpioa_isr(void) 223void 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
438static void sd_thread(void) NORETURN_ATTR;
439static 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
519static void init_pl180_controller(const int drive) 483static 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:
873sd_transfer_error_nodma: 833sd_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
948void sd_enable(bool on) 908void 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
1001tCardInfo *card_get_info_target(int card_no) 915tCardInfo *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
1007int sd_num_drives(int first_drive) 921int 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
928int 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
328static tCardInfo card_info[NUM_DRIVES]; 315static tCardInfo card_info[NUM_DRIVES];
329 316
317#ifdef CONFIG_STORAGE_MULTI
318static int sd_first_drive = 0;
319#else
320#define sd_first_drive 0
321#endif
322
330/* for compatibility */ 323/* for compatibility */
331static long last_disk_activity = -1; 324static long last_disk_activity = -1;
332
333static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
334static const char sd_thread_name[] = "ata/sd";
335static struct mutex sd_mtx SHAREDBSS_ATTR; 325static struct mutex sd_mtx SHAREDBSS_ATTR;
336static struct event_queue sd_queue;
337#ifndef BOOTLOADER 326#ifndef BOOTLOADER
338bool sd_enabled = false; 327bool 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
364static 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
374static inline bool card_detect_target(void) 379static 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
580static void sd_thread(void) NORETURN_ATTR;
581static 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
649static void init_controller(void) 585static 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
926exit: 856exit:
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
953void sd_enable(bool on) 883void 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
984static int sd1_oneshot_callback(struct timeout *tmo) 907static 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
1000void sd_gpioa_isr(void) 918void sd_gpioa_isr(void)
@@ -1012,9 +930,41 @@ void sd_gpioa_isr(void)
1012#ifdef CONFIG_STORAGE_MULTI 930#ifdef CONFIG_STORAGE_MULTI
1013int sd_num_drives(int first_drive) 931int 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
938int 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
1069int 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 */
220static long sdmmc_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
221static const char sdmmc_thread_name[] = "sdmmc";
222static struct event_queue sdmmc_queue;
223#if CONFIG_STORAGE & STORAGE_SD 220#if CONFIG_STORAGE & STORAGE_SD
224static int sd_first_drive; 221static int sd_first_drive;
225static unsigned _sd_num_drives; 222static 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
512int 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
489static int init_mmc_drive(int drive) 555static 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
643int 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! */
579static int __xfer_sectors(int drive, unsigned long start, int count, void *buf, bool read) 651static 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
773static void sdmmc_thread(void) NORETURN_ATTR;
774static 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
865static int sdmmc_init(void) 845static 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
1027void mmc_sleep(void)
1028{
1029}
1030
1031void mmc_sleepnow(void) 1003void 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 */
152static long last_disk_activity = -1; 146static long last_disk_activity = -1;
153 147
154/** static, private data **/
155static bool initialized = false;
156static unsigned int sd_thread_id = 0;
157
158#define Q_CLOSE 1
159
160static long next_yield = 0; 148static 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 */ 168static struct mutex sd_mtx SHAREDBSS_ATTR;
181static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
182static const char sd_thread_name[] = "ata/sd";
183static struct mutex sd_mtx SHAREDBSS_ATTR;
184static struct event_queue sd_queue SHAREDBSS_ATTR;
185 169
186#ifdef HAVE_HOTSWAP 170#ifdef HAVE_HOTSWAP
187static int sd_first_drive = 0; 171static 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 */
193enum 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
202static unsigned int check_time[NUM_EC]; 176static unsigned int check_time[NUM_EC];
203 177
178static 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
204static inline bool sd_check_timeout(long timeout, int id) 190static 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
882sd_read_retry: 868sd_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
1000sd_write_retry: 986sd_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
1112static void sd_thread(void) NORETURN_ATTR;
1113#endif
1114static 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
1181void 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
1195void sd_enable(bool on) 1097void 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
1208int sd_init(void) 1104int 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
1298static int sd1_oneshot_callback(struct timeout *tmo) 1182static 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
1262int 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 */
58static long last_disk_activity = -1; 52static long last_disk_activity = -1;
59 53
60static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
61static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR; 54static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR;
62 55
63static const char sd_thread_name[] = "ata/sd";
64static struct mutex sd_mtx SHAREDBSS_ATTR; 56static struct mutex sd_mtx SHAREDBSS_ATTR;
65static struct event_queue sd_queue;
66#ifndef BOOTLOADER 57#ifndef BOOTLOADER
67bool sd_enabled = false; 58bool sd_enabled = false;
68#endif 59#endif
69 60
61#ifdef CONFIG_STORAGE_MULTI
62static int sd_first_drive = 0;
63#else
64#define sd_first_drive 0
65#endif
66
70static struct semaphore transfer_completion_signal; 67static struct semaphore transfer_completion_signal;
71static struct semaphore command_completion_signal; 68static struct semaphore command_completion_signal;
72static volatile bool retry; 69static volatile bool retry;
73static volatile int cmd_error; 70static volatile int cmd_error;
74 71
72static 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 */
76void INT_SD(void) 88void 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
321static void sd_thread(void) NORETURN_ATTR;
322static 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
396static void init_controller(void) 333static 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
747void sd_enable(bool on) 678void 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
789static int sd_oneshot_callback(struct timeout *tmo) 712static 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
810int sd_num_drives(int first_drive) 728int 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
736int 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 */
91static long last_disk_activity = -1; 89static long last_disk_activity = -1;
92 90
91#ifdef CONFIG_STORAGE_MULTI
92static int sd_first_drive = 0;
93#else
94#define sd_first_drive 0
95#endif
96
93static bool initialized = false; 97static bool initialized = false;
94static bool sd_enabled = false; 98static bool sd_enabled = false;
95static long next_yield = 0; 99static 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 */
113static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
114static const char sd_thread_name[] = "sd";
115static struct mutex sd_mtx SHAREDBSS_ATTR; 116static struct mutex sd_mtx SHAREDBSS_ATTR;
116static struct event_queue sd_queue;
117static struct semaphore transfer_completion_signal; 117static struct semaphore transfer_completion_signal;
118static volatile unsigned int transfer_error[NUM_DRIVES]; 118static 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
512static int sd1_oneshot_callback(struct timeout *tmo) 512static 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
527void EINT8_23(void) 523void 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
574static void sd_thread(void) NORETURN_ATTR;
575static 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
614static int sd_wait_for_state(const int card_no, unsigned int state) 570static 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)
950int sd_num_drives(int first_drive) 903int 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
961void sd_sleepnow(void)
962{
963}
964
965bool sd_disk_is_active(void) 911bool 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
929int 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
53void nand_sleep(void) 53void nand_sleep(void)
54{ 54{
55 nand_power_down();
56} 55}
57 56
58void nand_sleepnow(void) 57void 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;
91static int nand_interleaved = 0; 90static int nand_interleaved = 0;
92static int nand_cached = 0; 91static int nand_cached = 0;
93static long nand_last_activity_value = -1; 92static long nand_last_activity_value = -1;
94static long nand_stack[DEFAULT_STACK_SIZE];
95 93
96static struct mutex nand_mtx; 94static struct mutex nand_mtx;
97static struct semaphore nand_complete; 95static struct semaphore nand_complete;
@@ -359,20 +357,22 @@ void nand_power_up(void)
359 357
360void nand_power_down(void) 358void 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
717static 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
731int nand_device_init(void) 717int 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
768int 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;
58static uint32_t ata_dma_flags; 54static uint32_t ata_dma_flags;
59static long ata_last_activity_value = -1; 55static long ata_last_activity_value = -1;
60static long ata_sleep_timeout = 20 * HZ; 56static long ata_sleep_timeout = 20 * HZ;
61static uint32_t ata_stack[(DEFAULT_STACK_SIZE + 0x400) / 4];
62static bool ata_powered; 57static bool ata_powered;
63static const int ata_retries = ATA_RETRIES; 58static const int ata_retries = ATA_RETRIES;
64static const bool ata_error_srst = true; 59static 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
892static 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 */
908int ata_soft_reset(void) 888int 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
985void ata_sleep(void)
986{
987 ata_last_activity_value = current_tick - ata_sleep_timeout + HZ / 5;
988}
989
990void ata_sleepnow(void) 965void 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
997void ata_close(void)
998{
999 ata_sleepnow();
1000}
1001
1002void ata_spin(void) 972void 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
1098int 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 */
56static long last_disk_activity = -1; 52static long last_disk_activity = -1;
57 53
58/** static, private data **/
59static bool initialized = false;
60
61static long next_yield = 0; 54static 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 */
84static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
85static const char sd_thread_name[] = "sd";
86static struct mutex sd_mtx SHAREDBSS_ATTR; 76static struct mutex sd_mtx SHAREDBSS_ATTR;
87static struct event_queue sd_queue;
88 77
78#ifdef CONFIG_STORAGE_MULTI
89static int sd_first_drive = 0; 79static int sd_first_drive = 0;
90 80#else
81#define sd_first_drive 0
82#endif
91 83
92static bool sd_poll_status(unsigned int trigger, long timeout) 84static bool sd_poll_status(unsigned int trigger, long timeout)
93{ 85{
@@ -216,16 +208,13 @@ static inline bool card_detect_target(void)
216 208
217static int sd1_oneshot_callback(struct timeout *tmo) 209static 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
231void EXT0(void) 220void EXT0(void)
@@ -642,71 +631,6 @@ sd_write_error:
642 } 631 }
643} 632}
644 633
645static void sd_thread(void) NORETURN_ATTR;
646static 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
710void sd_enable(bool on) 634void sd_enable(bool on)
711{ 635{
712 if(on) 636 if(on)
@@ -725,6 +649,7 @@ void sd_enable(bool on)
725 649
726int sd_init(void) 650int 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
797void sd_sleepnow(void)
798{
799}
800
801bool sd_disk_is_active(void) 717bool 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
734int 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
105static long last_disk_activity = -1; 102static long last_disk_activity = -1;
106 103
107static bool initialized = false; 104static bool initialized = false;
108static unsigned int sd_thread_id = 0;
109 105
110static bool sd_enabled = false; 106static bool sd_enabled = false;
111static long next_yield = 0; 107static 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 */
125static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
126static const char sd_thread_name[] = "sd";
127static struct mutex sd_mtx SHAREDBSS_ATTR; 121static struct mutex sd_mtx SHAREDBSS_ATTR;
128static struct event_queue sd_queue;
129static volatile unsigned int transfer_error[NUM_DRIVES]; 122static volatile unsigned int transfer_error[NUM_DRIVES];
130/* align on cache line size */ 123/* align on cache line size */
131static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE] 124static 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
150static inline void enable_controller(bool on)
151{
152 sd_enabled = on;
153}
157 154
158void sd_enable(bool on) 155void 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
515static int sd1_oneshot_callback(struct timeout *tmo) 504static 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
580static void sd_thread(void) NORETURN_ATTR;
581static 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
631static int sd_wait_for_state(unsigned int state) 565static 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
676sd_transfer_retry: 610sd_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
943void sd_sleepnow(void) 874int 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
39static long last_disk_activity = -1; 32static long last_disk_activity = -1;
40#if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP) 33#if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP)
41static int sd_drive_nr = 0; 34static int sd_drive_nr = 0;
35#else
36#define sd_drive_nr 0
42#endif 37#endif
43static tCardInfo card; 38static tCardInfo card;
44 39
45static long sd_stack[(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
46static const char sd_thread_name[] = "ata/sd";
47static struct event_queue sd_queue;
48static struct mutex sd_mtx; 40static struct mutex sd_mtx;
49static struct semaphore sd_wakeup; 41static struct semaphore sd_wakeup;
50static void sd_thread(void) NORETURN_ATTR;
51 42
52static int use_4bit; 43static int use_4bit;
53static int num_6; 44static 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
1268int sd_read_sectors(IF_MV(int drive,) unsigned long start, int count, void* buf) 1254int 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
1407bool sd_removable(IF_MV_NONVOID(int drive)) 1393bool 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
1415static int sd_oneshot_callback(struct timeout *tmo) 1401static 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
1456static void sd_thread(void) 1439int 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
93static struct mutex mmc_mutex SHAREDBSS_ATTR; 95#ifdef CONFIG_STORAGE_MULTI
94 96static int mmc_first_drive = 0;
95#ifdef HAVE_HOTSWAP
96static long mmc_stack[((DEFAULT_STACK_SIZE*2) + 0x800)/sizeof(long)];
97#else 97#else
98static long mmc_stack[(DEFAULT_STACK_SIZE*2)/sizeof(long)]; 98#define mmc_first_drive 0
99#endif 99#endif
100static const char mmc_thread_name[] = "mmc"; 100
101static struct event_queue mmc_queue SHAREDBSS_ATTR; 101static struct mutex mmc_mutex SHAREDBSS_ATTR;
102
102static bool initialized = false; 103static bool initialized = false;
103static bool new_mmc_circuit; 104static bool new_mmc_circuit;
104 105
@@ -158,6 +159,21 @@ static void mmc_tick(void);
158 159
159/* implementation */ 160/* implementation */
160 161
162static 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
161void mmc_enable_int_flash_clock(bool on) 177void 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
766static 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
811bool mmc_detect(void) 782bool 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
883void mmc_enable(bool on) 854void 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
898int mmc_init(void) 861int 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
1002void mmc_sleep(void)
1003{
1004}
1005
1006void mmc_spin(void) 957void 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
1016int mmc_num_drives(int first_drive) 967int 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 974int 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