summaryrefslogtreecommitdiff
path: root/firmware/drivers
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/drivers
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/drivers')
-rw-r--r--firmware/drivers/ata.c493
-rw-r--r--firmware/drivers/ramdisk.c5
2 files changed, 217 insertions, 281 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}