summaryrefslogtreecommitdiff
path: root/firmware/storage.c
diff options
context:
space:
mode:
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*/