summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2010-04-03 22:02:09 +0000
committerFrank Gevaerts <frank@gevaerts.be>2010-04-03 22:02:09 +0000
commit376d8d577fe94a8dc8742deff5a7524aa1595e1c (patch)
tree4d76e5232d8b513a40f11588d0f6899d47336b49 /firmware
parentba7501513a87433043a217a813c9147d004314a5 (diff)
downloadrockbox-376d8d577fe94a8dc8742deff5a7524aa1595e1c.tar.gz
rockbox-376d8d577fe94a8dc8742deff5a7524aa1595e1c.zip
Add IO priority handling. Currently all IO has equal priority, except the dircache scanning thread which is lower. This fixes the slow boot problem for me, with the added benefit that actual audio playback also starts faster.
Lots of the changes are due to changing storage_(read|write)sectors() from macros to wrapper functions. This means that they have to be called with IF_MD2(drive,) again. Flyspray: FS#11167 Author: Frank Gevaerts git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25459 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/common/dircache.c8
-rw-r--r--firmware/common/disk.c2
-rw-r--r--firmware/drivers/fat.c18
-rw-r--r--firmware/export/config.h4
-rw-r--r--firmware/export/storage.h20
-rw-r--r--firmware/export/thread.h10
-rw-r--r--firmware/storage.c223
-rw-r--r--firmware/thread.c19
-rw-r--r--firmware/usbstack/usb_storage.c8
10 files changed, 216 insertions, 98 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index e4bdca258e..fe97fe2253 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -152,9 +152,7 @@ drivers/sd.c
152#if (CONFIG_STORAGE & STORAGE_RAMDISK) 152#if (CONFIG_STORAGE & STORAGE_RAMDISK)
153drivers/ramdisk.c 153drivers/ramdisk.c
154#endif 154#endif
155#ifdef CONFIG_STORAGE_MULTI
156storage.c 155storage.c
157#endif
158drivers/fat.c 156drivers/fat.c
159#if (CONFIG_STORAGE & STORAGE_MMC) || (CONFIG_STORAGE & STORAGE_SD) 157#if (CONFIG_STORAGE & STORAGE_MMC) || (CONFIG_STORAGE & STORAGE_SD)
160hotswap.c 158hotswap.c
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 9f19ac3d24..8b9be78b35 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -40,6 +40,7 @@
40#include "file.h" 40#include "file.h"
41#include "buffer.h" 41#include "buffer.h"
42#include "dir.h" 42#include "dir.h"
43#include "storage.h"
43#if CONFIG_RTC 44#if CONFIG_RTC
44#include "time.h" 45#include "time.h"
45#include "timefuncs.h" 46#include "timefuncs.h"
@@ -760,6 +761,7 @@ void* dircache_steal_buffer(long *size)
760void dircache_init(void) 761void dircache_init(void)
761{ 762{
762 int i; 763 int i;
764 int thread_id;
763 765
764 dircache_initialized = false; 766 dircache_initialized = false;
765 dircache_initializing = false; 767 dircache_initializing = false;
@@ -771,10 +773,14 @@ void dircache_init(void)
771 } 773 }
772 774
773 queue_init(&dircache_queue, true); 775 queue_init(&dircache_queue, true);
774 create_thread(dircache_thread, dircache_stack, 776 thread_id = create_thread(dircache_thread, dircache_stack,
775 sizeof(dircache_stack), 0, dircache_thread_name 777 sizeof(dircache_stack), 0, dircache_thread_name
776 IF_PRIO(, PRIORITY_BACKGROUND) 778 IF_PRIO(, PRIORITY_BACKGROUND)
777 IF_COP(, CPU)); 779 IF_COP(, CPU));
780#ifdef HAVE_IO_PRIORITY
781 thread_set_io_priority(thread_id,IO_PRIORITY_BACKGROUND);
782#endif
783
778} 784}
779 785
780/** 786/**
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index c4553099ec..f8efe1c88b 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -82,7 +82,7 @@ struct partinfo* disk_init(IF_MD_NONVOID(int drive))
82 (void)drive; 82 (void)drive;
83#endif 83#endif
84 84
85 storage_read_sectors(drive, 0,1, &sector); 85 storage_read_sectors(IF_MD2(drive,) 0,1, &sector);
86 /* check that the boot sector is initialized */ 86 /* check that the boot sector is initialized */
87 if ( (sector[510] != 0x55) || 87 if ( (sector[510] != 0x55) ||
88 (sector[511] != 0xaa)) { 88 (sector[511] != 0xaa)) {
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index ff2bebce92..f93b32f832 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -311,7 +311,7 @@ int fat_mount(IF_MV2(int volume,) IF_MD2(int drive,) long startsector)
311#endif 311#endif
312 312
313 /* Read the sector */ 313 /* Read the sector */
314 rc = storage_read_sectors(drive, startsector,1,buf); 314 rc = storage_read_sectors(IF_MD2(drive,) startsector,1,buf);
315 if(rc) 315 if(rc)
316 { 316 {
317 DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", rc); 317 DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", rc);
@@ -433,7 +433,7 @@ int fat_mount(IF_MV2(int volume,) IF_MD2(int drive,) long startsector)
433#endif /* #ifdef HAVE_FAT16SUPPORT */ 433#endif /* #ifdef HAVE_FAT16SUPPORT */
434 { 434 {
435 /* Read the fsinfo sector */ 435 /* Read the fsinfo sector */
436 rc = storage_read_sectors(drive, 436 rc = storage_read_sectors(IF_MD2(drive,)
437 startsector + fat_bpb->bpb_fsinfo, 1, buf); 437 startsector + fat_bpb->bpb_fsinfo, 1, buf);
438 if (rc < 0) 438 if (rc < 0)
439 { 439 {
@@ -618,7 +618,7 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
618#endif 618#endif
619 619
620 /* Write to the first FAT */ 620 /* Write to the first FAT */
621 rc = storage_write_sectors(fce->fat_vol->drive, 621 rc = storage_write_sectors(IF_MD2(fce->fat_vol->drive,)
622 secnum, 1, 622 secnum, 1,
623 sectorbuf); 623 sectorbuf);
624 if(rc < 0) 624 if(rc < 0)
@@ -639,7 +639,7 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
639#else 639#else
640 secnum += fat_bpbs[0].fatsize; 640 secnum += fat_bpbs[0].fatsize;
641#endif 641#endif
642 rc = storage_write_sectors(fce->fat_vol->drive, 642 rc = storage_write_sectors(IF_MD2(fce->fat_vol->drive,)
643 secnum, 1, sectorbuf); 643 secnum, 1, sectorbuf);
644 if(rc < 0) 644 if(rc < 0)
645 { 645 {
@@ -685,7 +685,7 @@ static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,)
685 /* Load the sector if it is not cached */ 685 /* Load the sector if it is not cached */
686 if(!fce->inuse) 686 if(!fce->inuse)
687 { 687 {
688 rc = storage_read_sectors(fat_bpb->drive, 688 rc = storage_read_sectors(IF_MD2(fat_bpb->drive,)
689 secnum + fat_bpb->startsector,1, 689 secnum + fat_bpb->startsector,1,
690 sectorbuf); 690 sectorbuf);
691 if(rc < 0) 691 if(rc < 0)
@@ -944,7 +944,7 @@ static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb))
944#endif /* #ifdef HAVE_FAT16SUPPORT */ 944#endif /* #ifdef HAVE_FAT16SUPPORT */
945 945
946 /* update fsinfo */ 946 /* update fsinfo */
947 rc = storage_read_sectors(fat_bpb->drive, 947 rc = storage_read_sectors(IF_MD2(fat_bpb->drive,)
948 fat_bpb->startsector + fat_bpb->bpb_fsinfo, 1,fsinfo); 948 fat_bpb->startsector + fat_bpb->bpb_fsinfo, 1,fsinfo);
949 if (rc < 0) 949 if (rc < 0)
950 { 950 {
@@ -957,7 +957,7 @@ static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb))
957 intptr = (long*)&(fsinfo[FSINFO_NEXTFREE]); 957 intptr = (long*)&(fsinfo[FSINFO_NEXTFREE]);
958 *intptr = htole32(fat_bpb->fsinfo.nextfree); 958 *intptr = htole32(fat_bpb->fsinfo.nextfree);
959 959
960 rc = storage_write_sectors(fat_bpb->drive, 960 rc = storage_write_sectors(IF_MD2(fat_bpb->drive,)
961 fat_bpb->startsector + fat_bpb->bpb_fsinfo,1,fsinfo); 961 fat_bpb->startsector + fat_bpb->bpb_fsinfo,1,fsinfo);
962 if (rc < 0) 962 if (rc < 0)
963 { 963 {
@@ -2110,11 +2110,11 @@ static int transfer(IF_MV2(struct bpb* fat_bpb,)
2110 if (start + count > fat_bpb->totalsectors) 2110 if (start + count > fat_bpb->totalsectors)
2111 panicf("Write %ld after data\n", 2111 panicf("Write %ld after data\n",
2112 start + count - fat_bpb->totalsectors); 2112 start + count - fat_bpb->totalsectors);
2113 rc = storage_write_sectors(fat_bpb->drive, 2113 rc = storage_write_sectors(IF_MD2(fat_bpb->drive,)
2114 start + fat_bpb->startsector, count, buf); 2114 start + fat_bpb->startsector, count, buf);
2115 } 2115 }
2116 else 2116 else
2117 rc = storage_read_sectors(fat_bpb->drive, 2117 rc = storage_read_sectors(IF_MD2(fat_bpb->drive,)
2118 start + fat_bpb->startsector, count, buf); 2118 start + fat_bpb->startsector, count, buf);
2119 if (rc < 0) { 2119 if (rc < 0) {
2120 DEBUGF( "transfer() - Couldn't %s sector %lx" 2120 DEBUGF( "transfer() - Couldn't %s sector %lx"
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 9d8dc41111..858d9bf250 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -921,4 +921,8 @@ Lyre prototype 1 */
921#define HAVE_PLUGIN_CHECK_OPEN_CLOSE 921#define HAVE_PLUGIN_CHECK_OPEN_CLOSE
922#endif 922#endif
923 923
924#ifdef HAVE_DIRCACHE
925#define HAVE_IO_PRIORITY
926#endif
927
924#endif /* __CONFIG_H__ */ 928#endif /* __CONFIG_H__ */
diff --git a/firmware/export/storage.h b/firmware/export/storage.h
index 0096e87a8d..e62cf0d902 100644
--- a/firmware/export/storage.h
+++ b/firmware/export/storage.h
@@ -57,6 +57,7 @@ struct storage_info
57 */ 57 */
58 #define storage_num_drives() NUM_DRIVES 58 #define storage_num_drives() NUM_DRIVES
59 #if (CONFIG_STORAGE & STORAGE_ATA) 59 #if (CONFIG_STORAGE & STORAGE_ATA)
60 #define STORAGE_FUNCTION(NAME) (ata_## NAME)
60 #define storage_spindown ata_spindown 61 #define storage_spindown ata_spindown
61 #define storage_sleep ata_sleep 62 #define storage_sleep ata_sleep
62 #define storage_spin ata_spin 63 #define storage_spin ata_spin
@@ -67,8 +68,6 @@ struct storage_info
67 #define storage_soft_reset() ata_soft_reset() 68 #define storage_soft_reset() ata_soft_reset()
68 #define storage_init() ata_init() 69 #define storage_init() ata_init()
69 #define storage_close() ata_close() 70 #define storage_close() ata_close()
70 #define storage_read_sectors(drive, start, count, buf) ata_read_sectors(IF_MD2(drive,) start, count, buf)
71 #define storage_write_sectors(drive, start, count, buf) ata_write_sectors(IF_MD2(drive,) start, count, buf)
72 #ifdef HAVE_STORAGE_FLUSH 71 #ifdef HAVE_STORAGE_FLUSH
73 #define storage_flush() (void)0 72 #define storage_flush() (void)0
74 #endif 73 #endif
@@ -84,6 +83,7 @@ struct storage_info
84 #define storage_present(drive) ata_present(IF_MD(drive)) 83 #define storage_present(drive) ata_present(IF_MD(drive))
85 #endif 84 #endif
86 #elif (CONFIG_STORAGE & STORAGE_SD) 85 #elif (CONFIG_STORAGE & STORAGE_SD)
86 #define STORAGE_FUNCTION(NAME) (sd_## NAME)
87 #define storage_spindown sd_spindown 87 #define storage_spindown sd_spindown
88 #define storage_sleep sd_sleep 88 #define storage_sleep sd_sleep
89 #define storage_spin sd_spin 89 #define storage_spin sd_spin
@@ -93,8 +93,6 @@ struct storage_info
93 #define storage_disk_is_active() 0 93 #define storage_disk_is_active() 0
94 #define storage_soft_reset() (void)0 94 #define storage_soft_reset() (void)0
95 #define storage_init() sd_init() 95 #define storage_init() sd_init()
96 #define storage_read_sectors(drive, start, count, buf) sd_read_sectors(IF_MD2(drive,) start, count, buf)
97 #define storage_write_sectors(drive, start, count, buf) sd_write_sectors(IF_MD2(drive,) start, count, buf)
98 #ifdef HAVE_STORAGE_FLUSH 96 #ifdef HAVE_STORAGE_FLUSH
99 #define storage_flush() (void)0 97 #define storage_flush() (void)0
100 #endif 98 #endif
@@ -110,6 +108,7 @@ struct storage_info
110 #define storage_present(drive) sd_present(IF_MD(drive)) 108 #define storage_present(drive) sd_present(IF_MD(drive))
111 #endif 109 #endif
112 #elif (CONFIG_STORAGE & STORAGE_MMC) 110 #elif (CONFIG_STORAGE & STORAGE_MMC)
111 #define STORAGE_FUNCTION(NAME) (mmc_## NAME)
113 #define storage_spindown mmc_spindown 112 #define storage_spindown mmc_spindown
114 #define storage_sleep mmc_sleep 113 #define storage_sleep mmc_sleep
115 #define storage_spin mmc_spin 114 #define storage_spin mmc_spin
@@ -119,8 +118,6 @@ struct storage_info
119 #define storage_disk_is_active() mmc_disk_is_active() 118 #define storage_disk_is_active() mmc_disk_is_active()
120 #define storage_soft_reset() (void)0 119 #define storage_soft_reset() (void)0
121 #define storage_init() mmc_init() 120 #define storage_init() mmc_init()
122 #define storage_read_sectors(drive, start, count, buf) mmc_read_sectors(IF_MD2(drive,) start, count, buf)
123 #define storage_write_sectors(drive, start, count, buf) mmc_write_sectors(IF_MD2(drive,) start, count, buf)
124 #ifdef HAVE_STORAGE_FLUSH 121 #ifdef HAVE_STORAGE_FLUSH
125 #define storage_flush() (void)0 122 #define storage_flush() (void)0
126 #endif 123 #endif
@@ -136,6 +133,7 @@ struct storage_info
136 #define storage_present(drive) mmc_present(IF_MD(drive)) 133 #define storage_present(drive) mmc_present(IF_MD(drive))
137 #endif 134 #endif
138 #elif (CONFIG_STORAGE & STORAGE_NAND) 135 #elif (CONFIG_STORAGE & STORAGE_NAND)
136 #define STORAGE_FUNCTION(NAME) (nand_## NAME)
139 #define storage_spindown nand_spindown 137 #define storage_spindown nand_spindown
140 #define storage_sleep nand_sleep 138 #define storage_sleep nand_sleep
141 #define storage_spin nand_spin 139 #define storage_spin nand_spin
@@ -145,8 +143,6 @@ struct storage_info
145 #define storage_disk_is_active() 0 143 #define storage_disk_is_active() 0
146 #define storage_soft_reset() (void)0 144 #define storage_soft_reset() (void)0
147 #define storage_init() nand_init() 145 #define storage_init() nand_init()
148 #define storage_read_sectors(drive, start, count, buf) nand_read_sectors(IF_MD2(drive,) start, count, buf)
149 #define storage_write_sectors(drive, start, count, buf) nand_write_sectors(IF_MD2(drive,) start, count, buf)
150 #ifdef HAVE_STORAGE_FLUSH 146 #ifdef HAVE_STORAGE_FLUSH
151 #define storage_flush() nand_flush() 147 #define storage_flush() nand_flush()
152 #endif 148 #endif
@@ -162,6 +158,7 @@ struct storage_info
162 #define storage_present(drive) nand_present(IF_MD(drive)) 158 #define storage_present(drive) nand_present(IF_MD(drive))
163 #endif 159 #endif
164 #elif (CONFIG_STORAGE & STORAGE_RAMDISK) 160 #elif (CONFIG_STORAGE & STORAGE_RAMDISK)
161 #define STORAGE_FUNCTION(NAME) (ramdisk_## NAME)
165 #define storage_spindown ramdisk_spindown 162 #define storage_spindown ramdisk_spindown
166 #define storage_sleep ramdisk_sleep 163 #define storage_sleep ramdisk_sleep
167 #define storage_spin ramdisk_spin 164 #define storage_spin ramdisk_spin
@@ -171,8 +168,6 @@ struct storage_info
171 #define storage_disk_is_active() 0 168 #define storage_disk_is_active() 0
172 #define storage_soft_reset() (void)0 169 #define storage_soft_reset() (void)0
173 #define storage_init() ramdisk_init() 170 #define storage_init() ramdisk_init()
174 #define storage_read_sectors(drive, start, count, buf) ramdisk_read_sectors(IF_MD2(drive,) start, count, buf)
175 #define storage_write_sectors(drive, start, count, buf) ramdisk_write_sectors(IF_MD2(drive,) start, count, buf)
176 #ifdef HAVE_STORAGE_FLUSH 171 #ifdef HAVE_STORAGE_FLUSH
177 #define storage_flush() (void)0 172 #define storage_flush() (void)0
178 #endif 173 #endif
@@ -200,8 +195,6 @@ void storage_sleepnow(void);
200bool storage_disk_is_active(void); 195bool storage_disk_is_active(void);
201int storage_soft_reset(void); 196int storage_soft_reset(void);
202int storage_init(void); 197int storage_init(void);
203int storage_read_sectors(int drive, unsigned long start, int count, void* buf);
204int storage_write_sectors(int drive, unsigned long start, int count, const void* buf);
205int storage_flush(void); 198int storage_flush(void);
206void storage_spin(void); 199void storage_spin(void);
207void storage_spindown(int seconds); 200void storage_spindown(int seconds);
@@ -217,4 +210,7 @@ bool storage_present(int drive);
217#endif 210#endif
218 211
219#endif /* NOT CONFIG_STORAGE_MULTI and NOT SIMULATOR*/ 212#endif /* NOT CONFIG_STORAGE_MULTI and NOT SIMULATOR*/
213
214int storage_read_sectors(IF_MD2(int drive,) unsigned long start, int count, void* buf);
215int storage_write_sectors(IF_MD2(int drive,) unsigned long start, int count, const void* buf);
220#endif 216#endif
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index 2a2a7a8619..a75981dcba 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -58,6 +58,9 @@
58#define NUM_PRIORITIES 32 58#define NUM_PRIORITIES 32
59#define PRIORITY_IDLE 32 /* Priority representative of no tasks */ 59#define PRIORITY_IDLE 32 /* Priority representative of no tasks */
60 60
61#define IO_PRIORITY_IMMEDIATE 0
62#define IO_PRIORITY_BACKGROUND 32
63
61#if CONFIG_CODEC == SWCODEC 64#if CONFIG_CODEC == SWCODEC
62 65
63#ifdef HAVE_RECORDING 66#ifdef HAVE_RECORDING
@@ -294,6 +297,9 @@ struct thread_entry
294 struct corelock waiter_cl; /* Corelock for thread_wait */ 297 struct corelock waiter_cl; /* Corelock for thread_wait */
295 struct corelock slot_cl; /* Corelock to lock thread slot */ 298 struct corelock slot_cl; /* Corelock to lock thread slot */
296#endif 299#endif
300#ifdef HAVE_IO_PRIORITY
301 unsigned char io_priority;
302#endif
297}; 303};
298 304
299/*** Macros for internal use ***/ 305/*** Macros for internal use ***/
@@ -539,6 +545,10 @@ unsigned int wakeup_thread(struct thread_entry **list);
539int thread_set_priority(unsigned int thread_id, int priority); 545int thread_set_priority(unsigned int thread_id, int priority);
540int thread_get_priority(unsigned int thread_id); 546int thread_get_priority(unsigned int thread_id);
541#endif /* HAVE_PRIORITY_SCHEDULING */ 547#endif /* HAVE_PRIORITY_SCHEDULING */
548#ifdef HAVE_IO_PRIORITY
549void thread_set_io_priority(unsigned int thread_id, int io_priority);
550int thread_get_io_priority(unsigned int thread_id);
551#endif /* HAVE_IO_PRIORITY */
542#if NUM_CORES > 1 552#if NUM_CORES > 1
543unsigned int switch_core(unsigned int new_core); 553unsigned int switch_core(unsigned int new_core);
544#endif 554#endif
diff --git a/firmware/storage.c b/firmware/storage.c
index d6700d1148..ceae98fa40 100644
--- a/firmware/storage.c
+++ b/firmware/storage.c
@@ -19,6 +19,9 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "storage.h" 21#include "storage.h"
22#include "kernel.h"
23
24#ifdef CONFIG_STORAGE_MULTI
22 25
23#define DRIVER_MASK 0xff000000 26#define DRIVER_MASK 0xff000000
24#define DRIVER_OFFSET 24 27#define DRIVER_OFFSET 24
@@ -28,116 +31,112 @@
28 31
29static unsigned int storage_drivers[NUM_DRIVES]; 32static unsigned int storage_drivers[NUM_DRIVES];
30static unsigned int num_drives; 33static unsigned int num_drives;
34#endif
31 35
32int storage_num_drives(void)
33{
34 return num_drives;
35}
36 36
37int storage_init(void) 37#ifdef HAVE_IO_PRIORITY
38{
39 int rc=0;
40 int i;
41 num_drives=0;
42
43#if (CONFIG_STORAGE & STORAGE_ATA)
44 if ((rc=ata_init())) return rc;
45
46 int ata_drives = ata_num_drives(num_drives);
47 for (i=0; i<ata_drives; i++)
48 {
49 storage_drivers[num_drives++] =
50 (STORAGE_ATA<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
51 }
52#endif
53 38
54#if (CONFIG_STORAGE & STORAGE_MMC) 39/* Same for flash? */
55 if ((rc=mmc_init())) return rc; 40#define STORAGE_MINIMUM_IDLE_TIME (HZ/10)
56 41#define STORAGE_DELAY_UNIT (HZ/20)
57 int mmc_drives = mmc_num_drives(num_drives);
58 for (i=0; i<mmc_drives ;i++)
59 {
60 storage_drivers[num_drives++] =
61 (STORAGE_MMC<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
62 }
63#endif
64 42
65#if (CONFIG_STORAGE & STORAGE_SD) 43unsigned int storage_last_thread[NUM_DRIVES];
66 if ((rc=sd_init())) return rc; 44unsigned int storage_last_activity[NUM_DRIVES];
67 45
68 int sd_drives = sd_num_drives(num_drives); 46static bool storage_should_wait(int drive, int prio)
69 for (i=0; i<sd_drives; i++) 47{
48 int other_prio = thread_get_io_priority(storage_last_thread[drive]);
49 if(TIME_BEFORE(current_tick,storage_last_activity[drive]+STORAGE_MINIMUM_IDLE_TIME))
70 { 50 {
71 storage_drivers[num_drives++] = 51 if(prio<=other_prio)
72 (STORAGE_SD<<DRIVER_OFFSET) | (i << DRIVE_OFFSET); 52 {
53 /* There is another active thread, but we have lower priority */
54 return false;
55 }
56 else
57 {
58 /* There is another active thread, but it has lower priority */
59 return true;
60 }
73 } 61 }
74#endif 62 else
75
76#if (CONFIG_STORAGE & STORAGE_NAND)
77 if ((rc=nand_init())) return rc;
78
79 int nand_drives = nand_num_drives(num_drives);
80 for (i=0; i<nand_drives; i++)
81 { 63 {
82 storage_drivers[num_drives++] = 64 /* There's nothing going on anyway */
83 (STORAGE_NAND<<DRIVER_OFFSET) | (i << DRIVE_OFFSET); 65 return false;
84 } 66 }
85#endif 67}
86 68
87#if (CONFIG_STORAGE & STORAGE_RAMDISK) 69static void storage_wait_turn(IF_MD_NONVOID(int drive))
88 if ((rc=ramdisk_init())) return rc; 70{
89 71#ifndef HAVE_MULTIDRIVE
90 int ramdisk_drives = ramdisk_num_drives(num_drives); 72 int drive=0;
91 for (i=0; i<ramdisk_drives; i++) 73#endif
74 int my_prio = thread_get_io_priority(thread_get_current());
75 int loops=my_prio;
76 while(storage_should_wait(drive, my_prio) && (loops--)>=0)
92 { 77 {
93 storage_drivers[num_drives++] = 78 sleep(STORAGE_DELAY_UNIT);
94 (STORAGE_RAMDISK<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
95 } 79 }
96#endif
97 80
98 return 0; 81 storage_last_thread[drive] = thread_get_current();
82 storage_last_activity[drive] = current_tick;
99} 83}
84#endif
100 85
101int storage_read_sectors(int drive, unsigned long start, int count, 86int storage_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
102 void* buf) 87 void* buf)
103{ 88{
89#ifdef HAVE_IO_PRIORITY
90 storage_wait_turn(IF_MD(drive));
91#endif
92
93#ifdef CONFIG_STORAGE_MULTI
104 int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; 94 int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
105 int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET; 95 int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
106 96
107 switch (driver) 97 switch (driver)
108 { 98 {
109#if (CONFIG_STORAGE & STORAGE_ATA) 99#if (CONFIG_STORAGE & STORAGE_ATA)
110 case STORAGE_ATA: 100 case STORAGE_ATA:
111 return ata_read_sectors(ldrive,start,count,buf); 101 return ata_read_sectors(IF_MD2(ldrive,) start,count,buf);
112#endif 102#endif
113 103
114#if (CONFIG_STORAGE & STORAGE_MMC) 104#if (CONFIG_STORAGE & STORAGE_MMC)
115 case STORAGE_MMC: 105 case STORAGE_MMC:
116 return mmc_read_sectors(ldrive,start,count,buf); 106 return mmc_read_sectors(IF_MD2(ldrive,) start,count,buf);
117#endif 107#endif
118 108
119#if (CONFIG_STORAGE & STORAGE_SD) 109#if (CONFIG_STORAGE & STORAGE_SD)
120 case STORAGE_SD: 110 case STORAGE_SD:
121 return sd_read_sectors(ldrive,start,count,buf); 111 return sd_read_sectors(IF_MD2(ldrive,) start,count,buf);
122#endif 112#endif
123 113
124#if (CONFIG_STORAGE & STORAGE_NAND) 114#if (CONFIG_STORAGE & STORAGE_NAND)
125 case STORAGE_NAND: 115 case STORAGE_NAND:
126 return nand_read_sectors(ldrive,start,count,buf); 116 return nand_read_sectors(IF_MD2(ldrive,) start,count,buf);
127#endif 117#endif
128 118
129#if (CONFIG_STORAGE & STORAGE_RAMDISK) 119#if (CONFIG_STORAGE & STORAGE_RAMDISK)
130 case STORAGE_RAMDISK: 120 case STORAGE_RAMDISK:
131 return ramdisk_read_sectors(ldrive,start,count,buf); 121 return ramdisk_read_sectors(IF_MD2(ldrive,) start,count,buf);
132#endif 122#endif
133 } 123 }
134 124
135 return -1; 125 return -1;
126#else /* CONFIG_STORAGE_MULTI */
127 return STORAGE_FUNCTION(read_sectors)(IF_MD2(drive,)start,count,buf);
128#endif /* CONFIG_STORAGE_MULTI */
129
136} 130}
137 131
138int storage_write_sectors(int drive, unsigned long start, int count, 132int storage_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
139 const void* buf) 133 const void* buf)
140{ 134{
135#ifdef HAVE_IO_PRIORITY
136 storage_wait_turn(IF_MD(drive));
137#endif
138
139#ifdef CONFIG_STORAGE_MULTI
141 int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; 140 int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
142 int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET; 141 int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
143 142
@@ -145,33 +144,117 @@ int storage_write_sectors(int drive, unsigned long start, int count,
145 { 144 {
146#if (CONFIG_STORAGE & STORAGE_ATA) 145#if (CONFIG_STORAGE & STORAGE_ATA)
147 case STORAGE_ATA: 146 case STORAGE_ATA:
148 return ata_write_sectors(ldrive,start,count,buf); 147 return ata_write_sectors(IF_MD2(ldrive,)start,count,buf);
149#endif 148#endif
150 149
151#if (CONFIG_STORAGE & STORAGE_MMC) 150#if (CONFIG_STORAGE & STORAGE_MMC)
152 case STORAGE_MMC: 151 case STORAGE_MMC:
153 return mmc_write_sectors(ldrive,start,count,buf); 152 return mmc_write_sectors(IF_MD2(ldrive,)start,count,buf);
154#endif 153#endif
155 154
156#if (CONFIG_STORAGE & STORAGE_SD) 155#if (CONFIG_STORAGE & STORAGE_SD)
157 case STORAGE_SD: 156 case STORAGE_SD:
158 return sd_write_sectors(ldrive,start,count,buf); 157 return sd_write_sectors(IF_MD2(ldrive,)start,count,buf);
159#endif 158#endif
160 159
161#if (CONFIG_STORAGE & STORAGE_NAND) 160#if (CONFIG_STORAGE & STORAGE_NAND)
162 case STORAGE_NAND: 161 case STORAGE_NAND:
163 return nand_write_sectors(ldrive,start,count,buf); 162 return nand_write_sectors(IF_MD2(ldrive,)start,count,buf);
164#endif 163#endif
165 164
166#if (CONFIG_STORAGE & STORAGE_RAMDISK) 165#if (CONFIG_STORAGE & STORAGE_RAMDISK)
167 case STORAGE_RAMDISK: 166 case STORAGE_RAMDISK:
168 return ramdisk_write_sectors(ldrive,start,count,buf); 167 return ramdisk_write_sectors(IF_MD2(ldrive,)start,count,buf);
169#endif 168#endif
170 } 169 }
171 170
172 return -1; 171 return -1;
172#else /* CONFIG_STORAGE_MULTI */
173 return STORAGE_FUNCTION(write_sectors)(IF_MD2(drive,)start,count,buf);
174#endif /* CONFIG_STORAGE_MULTI */
175}
176
177#ifdef CONFIG_STORAGE_MULTI
178
179#define DRIVER_MASK 0xff000000
180#define DRIVER_OFFSET 24
181#define DRIVE_MASK 0x00ff0000
182#define DRIVE_OFFSET 16
183#define PARTITION_MASK 0x0000ff00
184
185static unsigned int storage_drivers[NUM_DRIVES];
186static unsigned int num_drives;
187
188int storage_num_drives(void)
189{
190 return num_drives;
191}
192
193int storage_init(void)
194{
195 int rc=0;
196 int i;
197 num_drives=0;
198
199#if (CONFIG_STORAGE & STORAGE_ATA)
200 if ((rc=ata_init())) return rc;
201
202 int ata_drives = ata_num_drives(num_drives);
203 for (i=0; i<ata_drives; i++)
204 {
205 storage_drivers[num_drives++] =
206 (STORAGE_ATA<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
207 }
208#endif
209
210#if (CONFIG_STORAGE & STORAGE_MMC)
211 if ((rc=mmc_init())) return rc;
212
213 int mmc_drives = mmc_num_drives(num_drives);
214 for (i=0; i<mmc_drives ;i++)
215 {
216 storage_drivers[num_drives++] =
217 (STORAGE_MMC<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
218 }
219#endif
220
221#if (CONFIG_STORAGE & STORAGE_SD)
222 if ((rc=sd_init())) return rc;
223
224 int sd_drives = sd_num_drives(num_drives);
225 for (i=0; i<sd_drives; i++)
226 {
227 storage_drivers[num_drives++] =
228 (STORAGE_SD<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
229 }
230#endif
231
232#if (CONFIG_STORAGE & STORAGE_NAND)
233 if ((rc=nand_init())) return rc;
234
235 int nand_drives = nand_num_drives(num_drives);
236 for (i=0; i<nand_drives; i++)
237 {
238 storage_drivers[num_drives++] =
239 (STORAGE_NAND<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
240 }
241#endif
242
243#if (CONFIG_STORAGE & STORAGE_RAMDISK)
244 if ((rc=ramdisk_init())) return rc;
245
246 int ramdisk_drives = ramdisk_num_drives(num_drives);
247 for (i=0; i<ramdisk_drives; i++)
248 {
249 storage_drivers[num_drives++] =
250 (STORAGE_RAMDISK<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
251 }
252#endif
253
254 return 0;
173} 255}
174 256
257
175void storage_enable(bool on) 258void storage_enable(bool on)
176{ 259{
177#if (CONFIG_STORAGE & STORAGE_ATA) 260#if (CONFIG_STORAGE & STORAGE_ATA)
@@ -572,3 +655,5 @@ bool storage_present(int drive)
572 return ret; 655 return ret;
573} 656}
574#endif 657#endif
658
659#endif /*CONFIG_STORAGE_MULTI*/
diff --git a/firmware/thread.c b/firmware/thread.c
index 38933f623e..81ef42a6b0 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -2413,6 +2413,11 @@ unsigned int create_thread(void (*function)(void),
2413 prio_add_entry(&thread->pdist, priority); 2413 prio_add_entry(&thread->pdist, priority);
2414#endif 2414#endif
2415 2415
2416#ifdef HAVE_IO_PRIORITY
2417 /* Default to high (foreground) priority */
2418 thread->io_priority = IO_PRIORITY_IMMEDIATE;
2419#endif
2420
2416#if NUM_CORES > 1 2421#if NUM_CORES > 1
2417 thread->core = core; 2422 thread->core = core;
2418 2423
@@ -2918,6 +2923,20 @@ int thread_get_priority(unsigned int thread_id)
2918} 2923}
2919#endif /* HAVE_PRIORITY_SCHEDULING */ 2924#endif /* HAVE_PRIORITY_SCHEDULING */
2920 2925
2926#ifdef HAVE_IO_PRIORITY
2927int thread_get_io_priority(unsigned int thread_id)
2928{
2929 struct thread_entry *thread = thread_id_entry(thread_id);
2930 return thread->io_priority;
2931}
2932
2933void thread_set_io_priority(unsigned int thread_id,int io_priority)
2934{
2935 struct thread_entry *thread = thread_id_entry(thread_id);
2936 thread->io_priority = io_priority;
2937}
2938#endif
2939
2921/*--------------------------------------------------------------------------- 2940/*---------------------------------------------------------------------------
2922 * Starts a frozen thread - similar semantics to wakeup_thread except that 2941 * Starts a frozen thread - similar semantics to wakeup_thread except that
2923 * the thread is on no scheduler or wakeup queue at all. It exists simply by 2942 * the thread is on no scheduler or wakeup queue at all. It exists simply by
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 4a8f2dc397..647fbd8e5b 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -353,7 +353,7 @@ static bool check_disk_present(IF_MD_NONVOID(int volume))
353 return true; 353 return true;
354#else 354#else
355 unsigned char sector[SECTOR_SIZE]; 355 unsigned char sector[SECTOR_SIZE];
356 return storage_read_sectors(volume,0,1,sector) == 0; 356 return storage_read_sectors(IF_MD2(volume,)0,1,sector) == 0;
357#endif 357#endif
358} 358}
359 359
@@ -537,7 +537,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
537 cur_cmd.data[cur_cmd.data_select], 537 cur_cmd.data[cur_cmd.data_select],
538 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 538 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
539#else 539#else
540 int result = storage_write_sectors(cur_cmd.lun, 540 int result = storage_write_sectors(IF_MD2(cur_cmd.lun,)
541 cur_cmd.sector, 541 cur_cmd.sector,
542 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 542 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
543 cur_cmd.data[cur_cmd.data_select]); 543 cur_cmd.data[cur_cmd.data_select]);
@@ -726,7 +726,7 @@ static void send_and_read_next(void)
726 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 726 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
727 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 727 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
728#else 728#else
729 cur_cmd.last_result = storage_read_sectors(cur_cmd.lun, 729 cur_cmd.last_result = storage_read_sectors(IF_MD2(cur_cmd.lun,)
730 cur_cmd.sector, 730 cur_cmd.sector,
731 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 731 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
732 cur_cmd.data[cur_cmd.data_select]); 732 cur_cmd.data[cur_cmd.data_select]);
@@ -1070,7 +1070,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1070 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 1070 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
1071 MIN(READ_BUFFER_SIZE/SECTOR_SIZE,cur_cmd.count)*SECTOR_SIZE); 1071 MIN(READ_BUFFER_SIZE/SECTOR_SIZE,cur_cmd.count)*SECTOR_SIZE);
1072#else 1072#else
1073 cur_cmd.last_result = storage_read_sectors(cur_cmd.lun, 1073 cur_cmd.last_result = storage_read_sectors(IF_MD2(cur_cmd.lun,)
1074 cur_cmd.sector, 1074 cur_cmd.sector,
1075 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 1075 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
1076 cur_cmd.data[cur_cmd.data_select]); 1076 cur_cmd.data[cur_cmd.data_select]);