summaryrefslogtreecommitdiff
path: root/firmware/storage.c
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/storage.c
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/storage.c')
-rw-r--r--firmware/storage.c383
1 files changed, 299 insertions, 84 deletions
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*/