summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 @@
****************************************************************************/
#include <stdbool.h>
#include <inttypes.h>
-#include "ata.h"
-#include "kernel.h"
-#include "thread.h"
#include "led.h"
#include "cpu.h"
#include "system.h"
#include "debug.h"
#include "panic.h"
-#include "usb.h"
#include "power.h"
#include "string.h"
-#include "ata_idle_notify.h"
#include "ata-driver.h"
#include "ata-defines.h"
#include "fs_defines.h"
@@ -64,24 +59,28 @@
#define CMD_WRITE_DMA_EXT 0x35
#endif
-/* Should all be < 0x100 (which are reserved for control messages) */
-#define Q_SLEEP 0
-#define Q_CLOSE 1
-
#define READWRITE_TIMEOUT 5*HZ
#ifdef HAVE_ATA_POWER_OFF
#define ATA_POWER_OFF_TIMEOUT 2*HZ
#endif
-#ifdef ATA_DRIVER_CLOSE
-static unsigned int ata_thread_id = 0;
-#endif
-
#if defined(HAVE_USBSTACK)
-#define ALLOW_USB_SPINDOWN
+#define ATA_ACTIVE_IN_USB 1
+#else
+#define ATA_ACTIVE_IN_USB 0
#endif
+enum {
+ ATA_BOOT = -1,
+ ATA_OFF,
+ ATA_SLEEPING,
+ ATA_SPINUP,
+ ATA_ON,
+};
+
+static int ata_state = ATA_BOOT;
+
static struct mutex ata_mtx SHAREDBSS_ATTR;
static int ata_device; /* device 0 (master) or 1 (slave) */
@@ -90,22 +89,16 @@ static int spinup_time = 0;
static bool ata_led_enabled = true;
static bool ata_led_on = false;
#endif
-static bool spinup = false;
-static bool sleeping = true;
-#ifdef HAVE_ATA_POWER_OFF
-static bool poweroff = false;
-#endif
+
static long sleep_timeout = 5*HZ;
#ifdef HAVE_LBA48
static bool lba48 = false; /* set for 48 bit addressing */
#endif
-static long ata_stack[(DEFAULT_STACK_SIZE*3)/sizeof(long)];
-static const char ata_thread_name[] = "ata";
-static struct event_queue ata_queue SHAREDBSS_ATTR;
-static bool initialized = false;
-static long last_user_activity = -1;
static long last_disk_activity = -1;
+#ifdef HAVE_ATA_POWER_OFF
+static long power_off_tick;
+#endif
static unsigned long total_sectors;
static int multisectors; /* number of supported multisectors */
@@ -135,6 +128,38 @@ static int perform_soft_reset(void);
static int set_multiple_mode(int sectors);
static int set_features(void);
+static inline void keep_ata_active(void)
+{
+ last_disk_activity = current_tick;
+}
+
+static inline void schedule_ata_sleep(long from_now)
+{
+ last_disk_activity = current_tick - sleep_timeout + from_now;
+}
+
+static inline bool ata_sleep_timed_out(void)
+{
+ return sleep_timeout &&
+ TIME_AFTER(current_tick, last_disk_activity + sleep_timeout);
+}
+
+static inline void schedule_ata_power_off(void)
+{
+#ifdef HAVE_ATA_POWER_OFF
+ power_off_tick = current_tick + ATA_POWER_OFF_TIMEOUT;
+#endif
+}
+
+static inline bool ata_power_off_timed_out(void)
+{
+#ifdef HAVE_ATA_POWER_OFF
+ return TIME_AFTER(current_tick, power_off_tick);
+#else
+ return false;
+#endif
+}
+
#ifndef ATA_TARGET_POLLING
static ICODE_ATTR int wait_for_bsy(void)
{
@@ -144,7 +169,7 @@ static ICODE_ATTR int wait_for_bsy(void)
{
if (!(ATA_IN8(ATA_STATUS) & STATUS_BSY))
return 1;
- last_disk_activity = current_tick;
+ keep_ata_active();
yield();
} while (TIME_BEFORE(current_tick, timeout));
@@ -164,7 +189,7 @@ static ICODE_ATTR int wait_for_rdy(void)
{
if (ATA_IN8(ATA_ALT_STATUS) & STATUS_RDY)
return 1;
- last_disk_activity = current_tick;
+ keep_ata_active();
yield();
} while (TIME_BEFORE(current_tick, timeout));
@@ -175,6 +200,44 @@ static ICODE_ATTR int wait_for_rdy(void)
#define wait_for_rdy ata_wait_for_rdy
#endif
+static int ata_perform_wakeup(int state)
+{
+ if (state > ATA_OFF) {
+ if (perform_soft_reset()) {
+ return -1;
+ }
+ }
+#ifdef HAVE_ATA_POWER_OFF
+ else {
+ if (ata_power_on()) {
+ return -2;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static int ata_perform_sleep(void)
+{
+ ATA_OUT8(ATA_SELECT, ata_device);
+
+ if(!wait_for_rdy()) {
+ DEBUGF("ata_perform_sleep() - not RDY\n");
+ return -1;
+ }
+
+ ATA_OUT8(ATA_COMMAND, CMD_SLEEP);
+
+ if (!wait_for_rdy())
+ {
+ DEBUGF("ata_perform_sleep() - CMD failed\n");
+ return -2;
+ }
+
+ return 0;
+}
+
static ICODE_ATTR int wait_for_start_of_transfer(void)
{
if (!wait_for_bsy())
@@ -278,42 +341,27 @@ static int ata_transfer_sectors(unsigned long start,
long timeout;
int count;
void* buf;
- long spinup_start;
+ long spinup_start = spinup_start;
#ifdef HAVE_ATA_DMA
bool usedma = false;
#endif
-#ifndef MAX_PHYS_SECTOR_SIZE
- mutex_lock(&ata_mtx);
-#endif
-
if (start + incount > total_sectors) {
ret = -1;
goto error;
}
- last_disk_activity = current_tick;
- spinup_start = current_tick;
+ keep_ata_active();
ata_led(true);
- if ( sleeping ) {
- sleeping = false; /* set this now since it'll be on */
- spinup = true;
-#ifdef HAVE_ATA_POWER_OFF
- if (poweroff) {
- if (ata_power_on()) {
- ret = -2;
- goto error;
- }
- }
- else
-#endif
- {
- if (perform_soft_reset()) {
- ret = -2;
- goto error;
- }
+ if (ata_state < ATA_ON) {
+ spinup_start = current_tick;
+ int state = ata_state;
+ ata_state = ATA_SPINUP;
+ if (ata_perform_wakeup(state)) {
+ ret = -2;
+ goto error;
}
}
@@ -331,7 +379,7 @@ static int ata_transfer_sectors(unsigned long start,
count = incount;
while (TIME_BEFORE(current_tick, timeout)) {
ret = 0;
- last_disk_activity = current_tick;
+ keep_ata_active();
#ifdef HAVE_ATA_DMA
/* If DMA is supported and parameters are ok for DMA, use it */
@@ -395,12 +443,9 @@ static int ata_transfer_sectors(unsigned long start,
goto retry;
}
- if (spinup) {
+ if (ata_state == ATA_SPINUP) {
+ ata_state = ATA_ON;
spinup_time = current_tick - spinup_start;
- spinup = false;
-#ifdef HAVE_ATA_POWER_OFF
- poweroff = false;
-#endif
}
}
else
@@ -426,12 +471,9 @@ static int ata_transfer_sectors(unsigned long start,
goto retry;
}
- if (spinup) {
+ if (ata_state == ATA_SPINUP) {
+ ata_state = ATA_ON;
spinup_time = current_tick - spinup_start;
- spinup = false;
-#ifdef HAVE_ATA_POWER_OFF
- poweroff = false;
-#endif
}
/* read the status register exactly once per loop */
@@ -470,7 +512,7 @@ static int ata_transfer_sectors(unsigned long start,
buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */
count -= sectors;
- last_disk_activity = current_tick;
+ keep_ata_active();
}
}
@@ -490,9 +532,11 @@ static int ata_transfer_sectors(unsigned long start,
error:
ata_led(false);
-#ifndef MAX_PHYS_SECTOR_SIZE
- mutex_unlock(&ata_mtx);
-#endif
+
+ if (ret < 0 && ata_state == ATA_SPINUP) {
+ /* bailed out before updating */
+ ata_state = ATA_ON;
+ }
return ret;
}
@@ -507,11 +551,12 @@ int ata_read_sectors(IF_MD(int drive,)
(void)drive; /* unused for now */
#endif
- return ata_transfer_sectors(start, incount, inbuf, false);
+ mutex_lock(&ata_mtx);
+ int rc = ata_transfer_sectors(start, incount, inbuf, false);
+ mutex_unlock(&ata_mtx);
+ return rc;
}
-#endif
-#ifndef MAX_PHYS_SECTOR_SIZE
int ata_write_sectors(IF_MD(int drive,)
unsigned long start,
int count,
@@ -521,9 +566,12 @@ int ata_write_sectors(IF_MD(int drive,)
(void)drive; /* unused for now */
#endif
- return ata_transfer_sectors(start, count, (void*)buf, true);
+ mutex_lock(&ata_mtx);
+ int rc = ata_transfer_sectors(start, count, (void*)buf, true);
+ mutex_unlock(&ata_mtx);
+ return rc;
}
-#endif
+#endif /* ndef MAX_PHYS_SECTOR_SIZE */
#ifdef MAX_PHYS_SECTOR_SIZE
static int cache_sector(unsigned long sector)
@@ -748,178 +796,26 @@ void ata_spindown(int seconds)
bool ata_disk_is_active(void)
{
- return !sleeping;
-}
-
-static int ata_perform_sleep(void)
-{
- /* guard against calls made with checks of these variables outside
- the mutex that may not be on the ata thread; status may have changed. */
- if (spinup || sleeping) {
- return 0;
- }
-
- ATA_OUT8(ATA_SELECT, ata_device);
-
- if(!wait_for_rdy()) {
- DEBUGF("ata_perform_sleep() - not RDY\n");
- return -1;
- }
-
- ATA_OUT8(ATA_COMMAND, CMD_SLEEP);
-
- if (!wait_for_rdy())
- {
- DEBUGF("ata_perform_sleep() - CMD failed\n");
- return -2;
- }
-
- sleeping = true;
- return 0;
-}
-
-void ata_sleep(void)
-{
- queue_post(&ata_queue, Q_SLEEP, 0);
+ return ata_state >= ATA_SPINUP;
}
void ata_sleepnow(void)
{
- if (!spinup && !sleeping && initialized)
- {
- call_storage_idle_notifys(false);
+ if (ata_state >= ATA_SPINUP) {
mutex_lock(&ata_mtx);
- ata_perform_sleep();
+ if (ata_state == ATA_ON) {
+ if (!ata_perform_sleep()) {
+ ata_state = ATA_SLEEPING;
+ schedule_ata_power_off();
+ }
+ }
mutex_unlock(&ata_mtx);
}
}
void ata_spin(void)
{
- last_user_activity = current_tick;
-}
-
-static void ata_thread(void)
-{
-#ifdef HAVE_ATA_POWER_OFF
- static long last_sleep = 0;
-#endif
- struct queue_event ev;
-#ifdef ALLOW_USB_SPINDOWN
- static bool usb_mode = false;
-#endif
-
- while (1) {
- queue_wait_w_tmo(&ata_queue, &ev, HZ/2);
-
- switch ( ev.id ) {
- case SYS_TIMEOUT:
- if (!spinup && !sleeping)
- {
- if (TIME_AFTER( current_tick,
- last_disk_activity + (HZ*2) ) )
- {
-#ifdef ALLOW_USB_SPINDOWN
- if(!usb_mode)
-#endif
- {
- call_storage_idle_notifys(false);
- }
- }
-
- if ( sleep_timeout &&
- TIME_AFTER( current_tick,
- last_user_activity + sleep_timeout ) &&
- TIME_AFTER( current_tick,
- last_disk_activity + sleep_timeout ) )
- {
-#ifdef ALLOW_USB_SPINDOWN
- if(!usb_mode)
-#endif
- {
- call_storage_idle_notifys(true);
- }
- mutex_lock(&ata_mtx);
- ata_perform_sleep();
-#ifdef HAVE_ATA_POWER_OFF
- last_sleep = current_tick;
-#endif
- mutex_unlock(&ata_mtx);
- }
- }
-
-#ifdef HAVE_ATA_POWER_OFF
- if ( !spinup && sleeping && !poweroff &&
- TIME_AFTER( current_tick, last_sleep + ATA_POWER_OFF_TIMEOUT ))
- {
- mutex_lock(&ata_mtx);
- ide_power_enable(false);
- poweroff = true;
- mutex_unlock(&ata_mtx);
- }
-#endif
- break;
-
-#ifndef USB_NONE
- case SYS_USB_CONNECTED:
- /* Tell the USB thread that we are safe */
- DEBUGF("ata_thread got SYS_USB_CONNECTED\n");
-#ifdef ALLOW_USB_SPINDOWN
- usb_mode = true;
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* There is no need to force ATA power on */
-#else
- mutex_lock(&ata_mtx);
- if (sleeping) {
- ata_led(true);
- sleeping = false; /* set this now since it'll be on */
-
-#ifdef HAVE_ATA_POWER_OFF
- if (poweroff) {
- ata_power_on();
- poweroff = false;
- }
- else
-#endif
- {
- perform_soft_reset();
- }
-
- ata_led(false);
- }
- mutex_unlock(&ata_mtx);
-
- /* Wait until the USB cable is extracted again */
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- usb_wait_for_disconnect(&ata_queue);
-#endif
- break;
-
-#ifdef ALLOW_USB_SPINDOWN
- case SYS_USB_DISCONNECTED:
- /* Tell the USB thread that we are ready again */
- DEBUGF("ata_thread got SYS_USB_DISCONNECTED\n");
- usb_mode = false;
- break;
-#endif
-#endif /* USB_NONE */
-
- case Q_SLEEP:
-#ifdef ALLOW_USB_SPINDOWN
- if(!usb_mode)
-#endif
- {
- call_storage_idle_notifys(false);
- }
- last_disk_activity = current_tick - sleep_timeout + (HZ/2);
- break;
-
-#ifdef ATA_DRIVER_CLOSE
- case Q_CLOSE:
- return;
-#endif
- }
- }
+ keep_ata_active();
}
/* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */
@@ -1025,11 +921,13 @@ static int perform_soft_reset(void)
int ata_soft_reset(void)
{
- int ret;
+ int ret = -6;
mutex_lock(&ata_mtx);
- ret = perform_soft_reset();
+ if (ata_state > ATA_OFF) {
+ ret = perform_soft_reset();
+ }
mutex_unlock(&ata_mtx);
return ret;
@@ -1068,7 +966,7 @@ static int ata_power_on(void)
return 0;
}
-#endif
+#endif /* HAVE_ATA_POWER_OFF */
static int STORAGE_INIT_ATTR master_slave_detect(void)
{
@@ -1250,9 +1148,8 @@ int STORAGE_INIT_ATTR ata_init(void)
int rc = 0;
bool coldstart;
- if ( !initialized ) {
+ if (ata_state == ATA_BOOT) {
mutex_init(&ata_mtx);
- queue_init(&ata_queue, true);
}
mutex_lock(&ata_mtx);
@@ -1261,16 +1158,13 @@ int STORAGE_INIT_ATTR ata_init(void)
coldstart = ata_is_coldstart();
ata_led(false);
ata_device_init();
- sleeping = false;
ata_enable(true);
#ifdef MAX_PHYS_SECTOR_SIZE
memset(&sector_cache, 0, sizeof(sector_cache));
#endif
- if ( !initialized ) {
- /* First call won't have multiple thread contention - this
- * may return at any point without having to unlock */
- mutex_unlock(&ata_mtx);
+ if (ata_state == ATA_BOOT) {
+ ata_state = ATA_OFF;
if (!ide_powered()) /* somebody has switched it off */
{
@@ -1290,14 +1184,17 @@ int STORAGE_INIT_ATTR ata_init(void)
{ /* failed? -> second try, always with hard reset */
DEBUGF("ata: init failed, retrying...\n");
rc = init_and_check(true);
- if (rc)
- return rc;
+ if (rc) {
+ goto error;
+ }
}
rc = identify();
- if (rc)
- return -40 + rc;
+ if (rc) {
+ rc = -40 + rc;
+ goto error;
+ }
multisectors = identify_info[47] & 0xff;
if (multisectors == 0) /* Invalid multisector info, try with 16 */
@@ -1317,15 +1214,20 @@ int STORAGE_INIT_ATTR ata_init(void)
total_sectors = identify_info[100] | (identify_info[101] << 16);
lba48 = true; /* use BigLBA */
}
-#endif
+#endif /* HAVE_LBA48 */
+
rc = freeze_lock();
- if (rc)
- return -50 + rc;
+ if (rc) {
+ rc = -50 + rc;
+ goto error;
+ }
rc = set_features();
- if (rc)
- return -60 + rc;
+ if (rc) {
+ rc = -60 + rc;
+ goto error;
+ }
#ifdef MAX_PHYS_SECTOR_SIZE
/* Find out the physical sector size */
@@ -1351,44 +1253,20 @@ int STORAGE_INIT_ATTR ata_init(void)
if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE))
panicf("Unsupported physical sector size: %d",
phys_sector_mult * SECTOR_SIZE);
-#endif
-
- mutex_lock(&ata_mtx); /* Balance unlock below */
-
- last_disk_activity = current_tick;
-#ifdef ATA_DRIVER_CLOSE
- ata_thread_id =
-#endif
- create_thread(ata_thread, ata_stack,
- sizeof(ata_stack), 0, ata_thread_name
- IF_PRIO(, PRIORITY_USER_INTERFACE)
- IF_COP(, CPU));
- initialized = true;
+#endif /* MAX_PHYS_SECTOR_SIZE */
+ ata_state = ATA_ON;
+ keep_ata_active();
}
rc = set_multiple_mode(multisectors);
if (rc)
rc = -70 + rc;
+error:
mutex_unlock(&ata_mtx);
return rc;
}
-#ifdef ATA_DRIVER_CLOSE
-void ata_close(void)
-{
- unsigned int thread_id = ata_thread_id;
-
- if (thread_id == 0)
- return;
-
- ata_thread_id = 0;
-
- queue_post(&ata_queue, Q_CLOSE, 0);
- thread_wait(thread_id);
-}
-#endif /* ATA_DRIVER_CLOSE */
-
#if (CONFIG_LED == LED_REAL)
void ata_set_led_enabled(bool enabled)
{
@@ -1453,9 +1331,7 @@ int ata_get_dma_mode(void)
/* Needed to allow updating while waiting for DMA to complete */
void ata_keep_active(void)
-{
- last_disk_activity = current_tick;
-}
+ __attribute__((alias("ata_spin")));
#endif
#ifdef CONFIG_STORAGE_MULTI
@@ -1467,3 +1343,58 @@ int ata_num_drives(int first_drive)
return 1;
}
#endif
+
+int ata_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ /* GCC does a lousy job culling unreachable cases in the default handler
+ if statements are in a switch statement, so we'll do it this way. Only
+ the first case is frequently hit anyway. */
+ if (LIKELY(id == Q_STORAGE_TICK)) {
+ /* won't see ATA_BOOT in here */
+ int state = ata_state;
+ if (state != ATA_ON || !ata_sleep_timed_out()) {
+ if (state == ATA_SLEEPING && ata_power_off_timed_out()) {
+ mutex_lock(&ata_mtx);
+ if (ata_state == ATA_SLEEPING) {
+ ide_power_enable(false);
+ ata_state = ATA_OFF;
+ }
+ mutex_unlock(&ata_mtx);
+ }
+ STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA);
+ }
+ }
+ else if (id == Q_STORAGE_SLEEPNOW) {
+ ata_sleepnow();
+ }
+ else if (id == Q_STORAGE_SLEEP) {
+ schedule_ata_sleep(HZ/5);
+ }
+#ifndef USB_NONE
+ else if (id == SYS_USB_CONNECTED) {
+ if (ATA_ACTIVE_IN_USB) {
+ /* There is no need to force ATA power on */
+ STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA);
+ }
+ else {
+ mutex_lock(&ata_mtx);
+ if (ata_state < ATA_ON) {
+ ata_led(true);
+ if (!(rc = ata_perform_wakeup(ata_state))) {
+ ata_state = ATA_ON;
+ }
+ ata_led(false);
+ }
+ mutex_unlock(&ata_mtx);
+ }
+ }
+#endif /* ndef USB_NONE */
+ else {
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_ATA);
+ }
+
+ return rc;
+}
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))
}
#endif
+int ramdisk_event(long id, intptr_t data)
+{
+ return storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_RAMDISK);
+}
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);
int ata_read_smart(struct ata_smart_values*);
#endif
+#ifdef BOOTLOADER
+#define STORAGE_CLOSE
+#endif
+
#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 @@
#ifndef __ATA_MMC_H__
#define __ATA_MMC_H__
+#include <stdbool.h>
+
void mmc_enable_int_flash_clock(bool on);
bool mmc_detect(void);
bool 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 @@
#include "mv.h" /* for HAVE_MULTIDRIVE or not */
#ifdef HAVE_BOOTLOADER_USB_MODE
-#define SD_DRIVER_CLOSE
+#define STORAGE_CLOSE
#endif
#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 @@
#include <stdbool.h>
#include "config.h" /* for HAVE_MULTIDRIVE or not */
#include "mv.h"
+#include <kernel.h>
#if (CONFIG_STORAGE & STORAGE_HOSTFS) || defined(SIMULATOR)
#define HAVE_HOSTFS
@@ -46,6 +47,57 @@
#include "ramdisk.h"
#endif
+enum
+{
+ Q_STORAGE_TICK = 1,
+ Q_STORAGE_SLEEP,
+ Q_STORAGE_SLEEPNOW,
+#ifdef STORAGE_CLOSE
+ Q_STORAGE_CLOSE,
+#endif
+};
+
+#define STG_EVENT_ASSERT_ACTIVE(type) \
+ ({ intptr_t __data = (data); \
+ *((unsigned int *)(__data)) |= (type); })
+
+static FORCE_INLINE int storage_event_default_handler(long id,
+ intptr_t data,
+ long last_activity,
+ unsigned int type)
+{
+ /* fake sleep in order to trigger storage idle sequence */
+ static long slept_at = -1;
+
+ if (id == Q_STORAGE_TICK) {
+ if (last_activity == slept_at ||
+ TIME_BEFORE(current_tick, last_activity + 3*HZ)) {
+ STG_EVENT_ASSERT_ACTIVE(type);
+ }
+ }
+ else if (id == Q_STORAGE_SLEEPNOW) {
+ slept_at = last_activity;
+ }
+
+ return 0;
+}
+
+#if (CONFIG_STORAGE & STORAGE_SD)
+int sd_event(long id, intptr_t data);
+#endif
+#if (CONFIG_STORAGE & STORAGE_MMC)
+int mmc_event(long id, intptr_t data);
+#endif
+#if (CONFIG_STORAGE & STORAGE_ATA)
+int ata_event(long id, intptr_t data);
+#endif
+#if (CONFIG_STORAGE & STORAGE_NAND)
+int nand_event(long id, intptr_t data);
+#endif
+#if (CONFIG_STORAGE & STORAGE_RAMDISK)
+int ramdisk_event(long id, intptr_t data);
+#endif
+
struct storage_info
{
unsigned int sector_size;
@@ -55,13 +107,24 @@ struct storage_info
char *revision;
};
+int storage_init(void) STORAGE_INIT_ATTR;
+void storage_close(void);
+
#ifdef HAVE_HOSTFS
#include "hostfs.h"
/* stubs for the plugin api */
static inline void stub_storage_sleep(void) {}
static inline void stub_storage_spin(void) {}
static inline void stub_storage_spindown(int timeout) { (void)timeout; }
+static inline int stub_storage_event(long id, intptr_t data)
+ { return 0; (void)id; (void)data; }
+#else /* ndef HAVE_HOSTFS */
+#if (CONFIG_STORAGE & STORAGE_ATA)
+void storage_sleep(void);
+#else
+static inline void storage_sleep(void) {}
#endif
+#endif /* HAVE_HOSTFS */
#if !defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOSTFS)
/* storage_spindown, storage_sleep and storage_spin are passed as
@@ -70,6 +133,7 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#define storage_num_drives() NUM_DRIVES
#if defined(HAVE_HOSTFS)
#define STORAGE_FUNCTION(NAME) (stub_## NAME)
+ #define storage_event stub_storage_event
#define storage_spindown stub_storage_spindown
#define storage_sleep stub_storage_sleep
#define storage_spin stub_storage_spin
@@ -97,15 +161,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#elif (CONFIG_STORAGE & STORAGE_ATA)
#define STORAGE_FUNCTION(NAME) (ata_## NAME)
#define storage_spindown ata_spindown
- #define storage_sleep ata_sleep
#define storage_spin ata_spin
#define storage_enable(on) ata_enable(on)
#define storage_sleepnow() ata_sleepnow()
#define storage_disk_is_active() ata_disk_is_active()
#define storage_soft_reset() ata_soft_reset()
- #define storage_init() ata_init()
- #define storage_close() ata_close()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
@@ -124,15 +185,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#elif (CONFIG_STORAGE & STORAGE_SD)
#define STORAGE_FUNCTION(NAME) (sd_## NAME)
#define storage_spindown sd_spindown
- #define storage_sleep sd_sleep
#define storage_spin sd_spin
#define storage_enable(on) sd_enable(on)
#define storage_sleepnow() sd_sleepnow()
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
- #define storage_init() sd_init()
- #define storage_close() sd_close()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
@@ -151,14 +209,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#elif (CONFIG_STORAGE & STORAGE_MMC)
#define STORAGE_FUNCTION(NAME) (mmc_## NAME)
#define storage_spindown mmc_spindown
- #define storage_sleep mmc_sleep
#define storage_spin mmc_spin
#define storage_enable(on) mmc_enable(on)
#define storage_sleepnow() mmc_sleepnow()
#define storage_disk_is_active() mmc_disk_is_active()
#define storage_soft_reset() (void)0
- #define storage_init() mmc_init()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
@@ -177,14 +233,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#elif (CONFIG_STORAGE & STORAGE_NAND)
#define STORAGE_FUNCTION(NAME) (nand_## NAME)
#define storage_spindown nand_spindown
- #define storage_sleep nand_sleep
#define storage_spin nand_spin
#define storage_enable(on) (void)0
#define storage_sleepnow() nand_sleepnow()
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
- #define storage_init() nand_init()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() nand_flush()
#endif
@@ -203,14 +257,12 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#elif (CONFIG_STORAGE & STORAGE_RAMDISK)
#define STORAGE_FUNCTION(NAME) (ramdisk_## NAME)
#define storage_spindown ramdisk_spindown
- #define storage_sleep ramdisk_sleep
#define storage_spin ramdisk_spin
#define storage_enable(on) (void)0
#define storage_sleepnow() ramdisk_sleepnow()
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
- #define storage_init() ramdisk_init()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
@@ -234,11 +286,9 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
/* Multi-driver use normal functions */
void storage_enable(bool on);
-void storage_sleep(void);
void storage_sleepnow(void);
bool storage_disk_is_active(void);
int storage_soft_reset(void);
-int storage_init(void) STORAGE_INIT_ATTR;
int storage_flush(void);
void storage_spin(void);
void 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 @@
****************************************************************************/
#include "storage.h"
#include "kernel.h"
+#include "ata_idle_notify.h"
+#include "usb.h"
+#include "disk.h"
#ifdef CONFIG_STORAGE_MULTI
@@ -31,118 +34,243 @@
static unsigned int storage_drivers[NUM_DRIVES];
static unsigned int num_drives;
+#endif /* CONFIG_STORAGE_MULTI */
+
+/* defaults: override elsewhere target-wise if they must be different */
+#if (CONFIG_STORAGE & STORAGE_ATA)
+ #ifndef ATA_THREAD_STACK_SIZE
+ #define ATA_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
+ #endif
+#endif
+#if (CONFIG_STORAGE & STORAGE_MMC)
+ #ifndef MMC_THREAD_STACK_SIZE
+ #define MMC_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
+ #endif
+#endif
+#if (CONFIG_STORAGE & STORAGE_SD)
+ #ifndef SD_THREAD_STACK_SIZE
+ #define SD_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
+ #endif
+#endif
+#if (CONFIG_STORAGE & STORAGE_NAND)
+ #ifndef NAND_THREAD_STACK_SIZE
+ #define NAND_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
+ #endif
+#endif
+#if (CONFIG_STORAGE & STORAGE_RAMDISK)
+ #ifndef RAMDISK_THREAD_STACK_SIZE
+ #define RAMDISK_THREAD_STACK_SIZE (0) /* not used on its own */
+ #endif
#endif
-int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count,
- void* buf)
-{
-#ifdef CONFIG_STORAGE_MULTI
- int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
- int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
+static struct event_queue storage_queue SHAREDBSS_ATTR;
+static unsigned int storage_thread_id = 0;
- switch (driver)
- {
+static union {
#if (CONFIG_STORAGE & STORAGE_ATA)
- case STORAGE_ATA:
- return ata_read_sectors(IF_MD(ldrive,) start,count,buf);
+ long stk_ata[ATA_THREAD_STACK_SIZE / sizeof (long)];
#endif
-
#if (CONFIG_STORAGE & STORAGE_MMC)
- case STORAGE_MMC:
- return mmc_read_sectors(IF_MD(ldrive,) start,count,buf);
+ long stk_mmc[MMC_THREAD_STACK_SIZE / sizeof (long)];
#endif
-
#if (CONFIG_STORAGE & STORAGE_SD)
- case STORAGE_SD:
- return sd_read_sectors(IF_MD(ldrive,) start,count,buf);
+ long stk_sd[SD_THREAD_STACK_SIZE / sizeof (long)];
#endif
-
#if (CONFIG_STORAGE & STORAGE_NAND)
- case STORAGE_NAND:
- return nand_read_sectors(IF_MD(ldrive,) start,count,buf);
+ long stk_nand[NAND_THREAD_STACK_SIZE / sizeof (long)];
+#endif
+#if (CONFIG_STORAGE & STORAGE_RAMDISK)
+ long stk_ramdisk[RAMDISK_THREAD_STACK_SIZE / sizeof (long)];
#endif
+} storage_thread_stack;
+static const char storage_thread_name[] =
+#if (CONFIG_STORAGE & STORAGE_ATA)
+ "/ata"
+#endif
+#if (CONFIG_STORAGE & STORAGE_MMC)
+ "/mmc"
+#endif
+#if (CONFIG_STORAGE & STORAGE_SD)
+ "/sd"
+#endif
+#if (CONFIG_STORAGE & STORAGE_NAND)
+ "/nand"
+#endif
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
- case STORAGE_RAMDISK:
- return ramdisk_read_sectors(IF_MD(ldrive,) start,count,buf);
+ "/ramdisk"
#endif
- }
-
- return -1;
-#else /* CONFIG_STORAGE_MULTI */
- return STORAGE_FUNCTION(read_sectors)(IF_MD(drive,)start,count,buf);
-#endif /* CONFIG_STORAGE_MULTI */
+ ;
-}
+/* event is targeted to a specific drive */
+#define DRIVE_EVT (1 << STORAGE_NUM_TYPES)
-int storage_write_sectors(IF_MD(int drive,) unsigned long start, int count,
- const void* buf)
-{
#ifdef CONFIG_STORAGE_MULTI
- int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
- int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
-
- switch (driver)
- {
+static int storage_event_send(unsigned int route, long id, intptr_t data)
+{
+ /* most events go to everyone */
+ if (UNLIKELY(route == DRIVE_EVT)) {
+ route = (storage_drivers[data] & DRIVER_MASK) >> DRIVER_OFFSET;
+ data = (storage_drivers[data] & DRIVE_MASK) >> DRIVE_OFFSET;
+ }
+
+ int rc = 0;
+
#if (CONFIG_STORAGE & STORAGE_ATA)
- case STORAGE_ATA:
- return ata_write_sectors(IF_MD(ldrive,)start,count,buf);
+ if (route & STORAGE_ATA) {
+ rc = ata_event(id, data);
+ }
#endif
-
#if (CONFIG_STORAGE & STORAGE_MMC)
- case STORAGE_MMC:
- return mmc_write_sectors(IF_MD(ldrive,)start,count,buf);
+ if (route & STORAGE_MMC) {
+ rc = mmc_event(id, data);
+ }
#endif
-
#if (CONFIG_STORAGE & STORAGE_SD)
- case STORAGE_SD:
- return sd_write_sectors(IF_MD(ldrive,)start,count,buf);
+ if (route & STORAGE_SD) {
+ rc = sd_event(id, data);
+ }
#endif
-
#if (CONFIG_STORAGE & STORAGE_NAND)
- case STORAGE_NAND:
- return nand_write_sectors(IF_MD(ldrive,)start,count,buf);
+ if (route & STORAGE_NAND) {
+ rc = nand_event(id, data);
+ }
#endif
-
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
- case STORAGE_RAMDISK:
- return ramdisk_write_sectors(IF_MD(ldrive,)start,count,buf);
-#endif
+ if (route & STORAGE_RAMDISK) {
+ rc = ramdisk_event(id, data);
}
-
- return -1;
-#else /* CONFIG_STORAGE_MULTI */
- return STORAGE_FUNCTION(write_sectors)(IF_MD(drive,)start,count,buf);
+#endif
+
+ return rc;
+}
#endif /* CONFIG_STORAGE_MULTI */
+
+#ifndef CONFIG_STORAGE_MULTI
+static FORCE_INLINE int storage_event_send(unsigned int route, long id,
+ intptr_t data)
+{
+ return route ? STORAGE_FUNCTION(event)(id, data) : 0;
}
+#endif /* ndef CONFIG_STORAGE_MULTI */
-#ifdef CONFIG_STORAGE_MULTI
+static void NORETURN_ATTR storage_thread(void)
+{
+ unsigned int bdcast = CONFIG_STORAGE;
+ bool usb_mode = false;
+ struct queue_event ev;
-#define DRIVER_MASK 0xff000000
-#define DRIVER_OFFSET 24
-#define DRIVE_MASK 0x00ff0000
-#define DRIVE_OFFSET 16
-#define PARTITION_MASK 0x0000ff00
+ while (1)
+ {
+ queue_wait_w_tmo(&storage_queue, &ev, HZ/2);
+
+ switch (ev.id)
+ {
+ case SYS_TIMEOUT:;
+ /* drivers hold their bit low when they want to
+ sleep and keep it high otherwise */
+ unsigned int trig = 0;
+ storage_event_send(bdcast, Q_STORAGE_TICK, (intptr_t)&trig);
+ trig = bdcast & ~trig;
+ if (trig) {
+ if (!usb_mode) {
+ call_storage_idle_notifys(false);
+ }
+ storage_event_send(trig, Q_STORAGE_SLEEPNOW, 0);
+ }
+ break;
-static unsigned int storage_drivers[NUM_DRIVES];
-static unsigned int num_drives;
+#if (CONFIG_STORAGE & STORAGE_ATA)
+ case Q_STORAGE_SLEEP:
+ storage_event_send(bdcast, ev.id, 0);
+ break;
+#endif
-int storage_num_drives(void)
+#ifdef STORAGE_CLOSE
+ case Q_STORAGE_CLOSE:
+ storage_event_send(CONFIG_STORAGE, ev.id, 0);
+ thread_exit();
+#endif /* STORAGE_CLOSE */
+
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ if (!usb_mode) {
+ int drive = IF_MD_DRV(ev.data);
+ if (!CHECK_DRV(drive)) {
+ break;
+ }
+
+ int umnt = disk_unmount(drive);
+ int mnt = 0;
+ int rci = storage_event_send(DRIVE_EVT, ev.id, drive);
+
+ if (ev.id == SYS_HOTSWAP_INSERTED && !rci) {
+ mnt = disk_mount(drive);
+ }
+
+ if (umnt > 0 || mnt > 0) {
+ /* something was unmounted and/or mounted */
+ queue_broadcast(SYS_FS_CHANGED, drive);
+ }
+ }
+ break;
+#endif /* HAVE_HOTSWAP */
+
+#ifndef USB_NONE
+ case SYS_USB_CONNECTED:
+ case SYS_USB_DISCONNECTED:
+ bdcast = 0;
+ storage_event_send(CONFIG_STORAGE, ev.id, (intptr_t)&bdcast);
+ usb_mode = ev.id == SYS_USB_CONNECTED;
+ if (usb_mode) {
+ usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ }
+ else {
+ bdcast = CONFIG_STORAGE;
+ }
+ break;
+#endif /* ndef USB_NONE */
+ }
+ }
+}
+
+#if (CONFIG_STORAGE & STORAGE_ATA)
+void storage_sleep(void)
{
- return num_drives;
+ if (storage_thread_id) {
+ queue_post(&storage_queue, Q_STORAGE_SLEEP, 0);
+ }
}
+#endif /* (CONFIG_STORAGE & STORAGE_ATA) */
-int storage_driver_type(int drive)
+#ifdef STORAGE_CLOSE
+void storage_close(void)
{
- if ((unsigned int)drive >= num_drives)
- return -1;
+ if (storage_thread_id) {
+ queue_post(&storage_queue, Q_STORAGE_CLOSE, 0);
+ thread_wait(storage_thread_id);
+ }
+}
+#endif /* STORAGE_CLOSE */
- unsigned int bit = (storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
- return bit ? find_first_set_bit(bit) : -1;
+static inline void storage_thread_init(void)
+{
+ if (storage_thread_id) {
+ return;
+ }
+
+ queue_init(&storage_queue, true);
+ storage_thread_id = create_thread(storage_thread, &storage_thread_stack,
+ sizeof (storage_thread_stack),
+ 0, &storage_thread_name[1]
+ IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU));
}
int storage_init(void)
{
+#ifdef CONFIG_STORAGE_MULTI
int rc=0;
int i;
num_drives=0;
@@ -201,54 +329,142 @@ int storage_init(void)
(STORAGE_RAMDISK<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
}
#endif
+#else /* ndef CONFIG_STORAGE_MULTI */
+ STORAGE_FUNCTION(init)();
+#endif /* CONFIG_STORAGE_MULTI */
+ storage_thread_init();
return 0;
}
+int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count,
+ void* buf)
+{
+#ifdef CONFIG_STORAGE_MULTI
+ int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
+ int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
-void storage_enable(bool on)
+ switch (driver)
+ {
+#if (CONFIG_STORAGE & STORAGE_ATA)
+ case STORAGE_ATA:
+ return ata_read_sectors(IF_MD(ldrive,) start,count,buf);
+#endif
+
+#if (CONFIG_STORAGE & STORAGE_MMC)
+ case STORAGE_MMC:
+ return mmc_read_sectors(IF_MD(ldrive,) start,count,buf);
+#endif
+
+#if (CONFIG_STORAGE & STORAGE_SD)
+ case STORAGE_SD:
+ return sd_read_sectors(IF_MD(ldrive,) start,count,buf);
+#endif
+
+#if (CONFIG_STORAGE & STORAGE_NAND)
+ case STORAGE_NAND:
+ return nand_read_sectors(IF_MD(ldrive,) start,count,buf);
+#endif
+
+#if (CONFIG_STORAGE & STORAGE_RAMDISK)
+ case STORAGE_RAMDISK:
+ return ramdisk_read_sectors(IF_MD(ldrive,) start,count,buf);
+#endif
+ }
+
+ return -1;
+#else /* CONFIG_STORAGE_MULTI */
+ return STORAGE_FUNCTION(read_sectors)(IF_MD(drive,)start,count,buf);
+#endif /* CONFIG_STORAGE_MULTI */
+
+}
+
+int storage_write_sectors(IF_MD(int drive,) unsigned long start, int count,
+ const void* buf)
{
+#ifdef CONFIG_STORAGE_MULTI
+ int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
+ int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
+
+ switch (driver)
+ {
#if (CONFIG_STORAGE & STORAGE_ATA)
- ata_enable(on);
+ case STORAGE_ATA:
+ return ata_write_sectors(IF_MD(ldrive,)start,count,buf);
#endif
#if (CONFIG_STORAGE & STORAGE_MMC)
- mmc_enable(on);
+ case STORAGE_MMC:
+ return mmc_write_sectors(IF_MD(ldrive,)start,count,buf);
#endif
#if (CONFIG_STORAGE & STORAGE_SD)
- sd_enable(on);
+ case STORAGE_SD:
+ return sd_write_sectors(IF_MD(ldrive,)start,count,buf);
#endif
#if (CONFIG_STORAGE & STORAGE_NAND)
- nand_enable(on);
+ case STORAGE_NAND:
+ return nand_write_sectors(IF_MD(ldrive,)start,count,buf);
#endif
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
- ramdisk_enable(on);
+ case STORAGE_RAMDISK:
+ return ramdisk_write_sectors(IF_MD(ldrive,)start,count,buf);
#endif
+ }
+
+ return -1;
+#else /* CONFIG_STORAGE_MULTI */
+ return STORAGE_FUNCTION(write_sectors)(IF_MD(drive,)start,count,buf);
+#endif /* CONFIG_STORAGE_MULTI */
}
-void storage_sleep(void)
+#ifdef CONFIG_STORAGE_MULTI
+
+#define DRIVER_MASK 0xff000000
+#define DRIVER_OFFSET 24
+#define DRIVE_MASK 0x00ff0000
+#define DRIVE_OFFSET 16
+#define PARTITION_MASK 0x0000ff00
+
+static unsigned int storage_drivers[NUM_DRIVES];
+static unsigned int num_drives;
+
+int storage_num_drives(void)
+{
+ return num_drives;
+}
+
+int storage_driver_type(int drive)
+{
+ if ((unsigned int)drive >= num_drives)
+ return -1;
+
+ unsigned int bit = (storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
+ return bit ? find_first_set_bit(bit) : -1;
+}
+
+void storage_enable(bool on)
{
#if (CONFIG_STORAGE & STORAGE_ATA)
- ata_sleep();
+ ata_enable(on);
#endif
#if (CONFIG_STORAGE & STORAGE_MMC)
- mmc_sleep();
+ mmc_enable(on);
#endif
#if (CONFIG_STORAGE & STORAGE_SD)
- sd_sleep();
+ sd_enable(on);
#endif
#if (CONFIG_STORAGE & STORAGE_NAND)
- nand_sleep();
+ nand_enable(on);
#endif
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
- ramdisk_sleep();
+ ramdisk_enable(on);
#endif
}
@@ -603,6 +819,5 @@ bool storage_present(int drive)
return false;
}
}
-#endif
-
+#endif /* HAVE_HOTSWAP */
#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 @@
#include "config.h" /* for HAVE_MULTIDRIVE & AMS_OF_SIZE */
#include "fs_defines.h"
-#include "thread.h"
#include "led.h"
#include "sdmmc.h"
#include "system.h"
@@ -39,20 +38,15 @@
#include "dma-target.h" /* DMA request lines */
#include "clock-target.h"
#include "panic.h"
+#include "storage.h"
+
#ifdef HAVE_BUTTON_LIGHT
#include "backlight-target.h"
#endif
-#include "stdbool.h"
-#include "ata_idle_notify.h"
-#include "sd.h"
-#include "usb.h"
+
/*#define LOGF_ENABLE*/
#include "logf.h"
-#ifdef HAVE_HOTSWAP
-#include "disk.h"
-#endif
-
//#define VERIFY_WRITE 1
/* command flags */
@@ -119,16 +113,19 @@ static tCardInfo card_info[NUM_DRIVES];
#define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */
#define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */
+#ifdef CONFIG_STORAGE_MULTI
+static int sd_first_drive = 0;
+#else
+#define sd_first_drive 0
+#endif
+
/* for compatibility */
static long last_disk_activity = -1;
#define MIN_YIELD_PERIOD 5 /* ticks */
static long next_yield = 0;
-static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
-static const char sd_thread_name[] = "ata/sd";
-static struct mutex sd_mtx;
-static struct event_queue sd_queue;
+static struct mutex sd_mtx;
bool sd_enabled = false;
#if defined(HAVE_MULTIDRIVE)
@@ -147,6 +144,59 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0])
static inline void mci_delay(void) { udelay(1000) ; }
+static void enable_controller(bool on)
+{
+
+#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
+ extern int buttonlight_is_on;
+#endif
+
+#if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE)
+ static bool cpu_boosted = false;
+#endif
+
+ if (sd_enabled == on)
+ return; /* nothing to do */
+
+ sd_enabled = on;
+
+ if(on)
+ {
+#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
+ /* buttonlight AMSes need a bit of special handling for the buttonlight
+ * here due to the dual mapping of GPIOD and XPD */
+ bitmod32(&CCU_IO, 1<<2, 3<<2); /* XPD is SD-MCI interface (b3:2 = 01) */
+ if (buttonlight_is_on)
+ GPIOD_DIR &= ~(1<<7);
+ else
+ buttonlight_hw_off();
+#endif
+
+#if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE)
+ if(card_detect_target()) /* If SD card present Boost cpu for voltage */
+ {
+ cpu_boosted = true;
+ cpu_boost(true);
+ }
+#endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */
+ }
+ else
+ {
+#if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE)
+ if(cpu_boosted)
+ {
+ cpu_boost(false);
+ cpu_boosted = false;
+ }
+#endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */
+
+#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
+ bitmod32(&CCU_IO, 0<<2, 3<<2); /* XPD is general purpose IO (b3:2 = 00) */
+ if (buttonlight_is_on)
+ buttonlight_hw_on();
+#endif
+ }
+}
static inline bool card_detect_target(void)
{
@@ -161,18 +211,13 @@ static inline bool card_detect_target(void)
#ifdef HAVE_HOTSWAP
static int sd1_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
-
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (card_detect_target())
- {
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- }
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
-
+ queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED :
+ SYS_HOTSWAP_EXTRACTED,
+ sd_first_drive + SD_SLOT_AS3525);
return 0;
+ (void)tmo;
}
void sd_gpioa_isr(void)
@@ -435,87 +480,6 @@ static int sd_init_card(const int drive)
return 0;
}
-static void sd_thread(void) NORETURN_ATTR;
-static void sd_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
-
- while (1)
- {
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
-
- switch ( ev.id )
- {
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- disk_unmount(SD_SLOT_AS3525); /* release "by force" */
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card_info[SD_SLOT_AS3525].initialized = 0;
-
- if (ev.id == SYS_HOTSWAP_INSERTED)
- {
- success = 0;
- sd_enable(true);
- init_pl180_controller(SD_SLOT_AS3525);
- int rc = sd_init_card(SD_SLOT_AS3525);
- sd_enable(false);
- if (rc >= 0)
- success = 2;
- else /* initialisation failed */
- panicf("microSD init failed : %d", rc);
- }
-
- mutex_unlock(&sd_mtx);
-
- if (success > 1)
- success = disk_mount(SD_SLOT_AS3525); /* 0 if fail */
-
- /*
- * Mount succeeded, or this was an EXTRACTED event,
- * in both cases notify the system about the changed filesystems
- */
- if (success)
- queue_broadcast(SYS_FS_CHANGED, 0);
-
- break;
-#endif /* HAVE_HOTSWAP */
-
- case SYS_TIMEOUT:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- {
- idle_notified = false;
- }
- else
- {
- /* never let a timer wrap confuse us */
- next_yield = current_tick;
-
- if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- }
- break;
-
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&sd_queue);
-
- break;
- }
- }
-}
-
static void init_pl180_controller(const int drive)
{
MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0;
@@ -576,12 +540,8 @@ int sd_init(void)
/* init mutex */
mutex_init(&sd_mtx);
- queue_init(&sd_queue, true);
- create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
- sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
-
- sd_enabled = true;
- sd_enable(false);
+ sd_enabled = true; /* force action on next call */
+ enable_controller(false);
return 0;
}
@@ -698,7 +658,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
unsigned long response;
bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1));
- sd_enable(true);
+ enable_controller(true);
led(true);
if (card_info[drive].initialized <= 0)
@@ -873,7 +833,7 @@ sd_transfer_error:
sd_transfer_error_nodma:
led(false);
- sd_enable(false);
+ enable_controller(false);
if (ret) /* error */
card_info[drive].initialized = 0;
@@ -947,55 +907,9 @@ long sd_last_disk_activity(void)
void sd_enable(bool on)
{
-#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
- extern int buttonlight_is_on;
-#endif
-
-#if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE)
- static bool cpu_boosted = false;
-#endif
-
- if (sd_enabled == on)
- return; /* nothing to do */
-
- sd_enabled = on;
-
- if(on)
- {
-#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
- /* buttonlight AMSes need a bit of special handling for the buttonlight
- * here due to the dual mapping of GPIOD and XPD */
- bitmod32(&CCU_IO, 1<<2, 3<<2); /* XPD is SD-MCI interface (b3:2 = 01) */
- if (buttonlight_is_on)
- GPIOD_DIR &= ~(1<<7);
- else
- buttonlight_hw_off();
-#endif
-
-#if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE)
- if(card_detect_target()) /* If SD card present Boost cpu for voltage */
- {
- cpu_boosted = true;
- cpu_boost(true);
- }
-#endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */
- }
- else
- {
-#if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE)
- if(cpu_boosted)
- {
- cpu_boost(false);
- cpu_boosted = false;
- }
-#endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */
-
-#if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE)
- bitmod32(&CCU_IO, 0<<2, 3<<2); /* XPD is general purpose IO (b3:2 = 00) */
- if (buttonlight_is_on)
- buttonlight_hw_on();
-#endif
- }
+ mutex_lock(&sd_mtx);
+ enable_controller(on);
+ mutex_unlock(&sd_mtx);
}
tCardInfo *card_get_info_target(int card_no)
@@ -1006,9 +920,45 @@ tCardInfo *card_get_info_target(int card_no)
#ifdef CONFIG_STORAGE_MULTI
int sd_num_drives(int first_drive)
{
- /* We don't care which logical drive number(s) we have been assigned */
- (void)first_drive;
-
+ sd_first_drive = first_drive;
return NUM_DRIVES;
}
#endif /* CONFIG_STORAGE_MULTI */
+
+int sd_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx); /* lock-out card activity */
+
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info[data].initialized = 0;
+
+ if (id == SYS_HOTSWAP_INSERTED)
+ {
+ enable_controller(true);
+ init_pl180_controller(data);
+ rc = sd_init_card(data);
+ enable_controller(false);
+ }
+
+ mutex_unlock(&sd_mtx);
+ break;
+#endif /* HAVE_HOTSWAP */
+ case Q_STORAGE_TICK:
+ /* never let a timer wrap confuse us */
+ next_yield = current_tick;
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
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 @@
#include "config.h" /* for HAVE_MULTIVOLUME */
#include "fs_defines.h"
-#include "thread.h"
#include "gcc_extensions.h"
#include "led.h"
#include "sdmmc.h"
@@ -36,19 +35,7 @@
#include "pl081.h" /* DMA controller */
#include "dma-target.h" /* DMA request lines */
#include "clock-target.h"
-#include "panic.h"
-#include "stdbool.h"
-#include "ata_idle_notify.h"
-#include "sd.h"
-#include "usb.h"
-
-#ifdef HAVE_HOTSWAP
-#include "disk.h"
-#endif
-
-#include "lcd.h"
-#include <stdarg.h>
-#include "sysfont.h"
+#include "storage.h"
#define INTERNAL_AS3525 0 /* embedded SD card */
#define SD_SLOT_AS3525 1 /* SD slot if present */
@@ -327,13 +314,15 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0])
static tCardInfo card_info[NUM_DRIVES];
+#ifdef CONFIG_STORAGE_MULTI
+static int sd_first_drive = 0;
+#else
+#define sd_first_drive 0
+#endif
+
/* for compatibility */
static long last_disk_activity = -1;
-
-static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
-static const char sd_thread_name[] = "ata/sd";
static struct mutex sd_mtx SHAREDBSS_ATTR;
-static struct event_queue sd_queue;
#ifndef BOOTLOADER
bool sd_enabled = false;
#endif
@@ -371,6 +360,22 @@ void INT_NAND(void)
MCI_CTRL |= INT_ENABLE;
}
+#ifndef BOOTLOADER
+static void enable_controller(bool on)
+{
+ if (on)
+ {
+ bitset32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE);
+ CGU_SDSLOT |= (1<<7); /* interface enable */
+ }
+ else
+ {
+ CGU_SDSLOT &= ~(1<<7); /* interface enable */
+ bitclr32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE);
+ }
+}
+#endif /* BOOTLOADER */
+
static inline bool card_detect_target(void)
{
#if defined(HAVE_MULTIDRIVE)
@@ -577,75 +582,6 @@ static int sd_init_card(const int drive)
return 0;
}
-static void sd_thread(void) NORETURN_ATTR;
-static void sd_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
-
- while (1)
- {
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
-
- switch ( ev.id )
- {
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- disk_unmount(SD_SLOT_AS3525); /* release "by force" */
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card_info[SD_SLOT_AS3525].initialized = 0;
-
- if (ev.id == SYS_HOTSWAP_INSERTED)
- {
- sd_enable(true);
- success = sd_init_card(SD_SLOT_AS3525) == 0 ? 2 : 0;
- sd_enable(false);
- }
-
- mutex_unlock(&sd_mtx);
-
- if (success > 1)
- success = disk_mount(SD_SLOT_AS3525); /* 0 if fail */
-
- /*
- * Mount succeeded, or this was an EXTRACTED event,
- * in both cases notify the system about the changed filesystems
- */
- if (success)
- queue_broadcast(SYS_FS_CHANGED, 0);
-
- break;
-#endif /* HAVE_HOTSWAP */
-
- case SYS_TIMEOUT:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- {
- idle_notified = false;
- }
- else if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- break;
-
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&sd_queue);
-
- break;
- }
- }
-}
-
static void init_controller(void)
{
int hcon_numcards = ((MCI_HCON>>1) & 0x1F) + 1;
@@ -706,6 +642,7 @@ int sd_init(void)
| (AS3525_SDSLOT_DIV << 2)
| 1; /* clock source = PLLA */
+ mutex_init(&sd_mtx);
semaphore_init(&transfer_completion_signal, 1, 0);
semaphore_init(&command_completion_signal, 1, 0);
@@ -737,16 +674,9 @@ int sd_init(void)
if(ret < 0)
return ret;
- /* init mutex */
- mutex_init(&sd_mtx);
-
- queue_init(&sd_queue, true);
- create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
- sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
-
#ifndef BOOTLOADER
sd_enabled = true;
- sd_enable(false);
+ enable_controller(false);
#endif
return 0;
}
@@ -767,7 +697,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start,
mutex_lock(&sd_mtx);
#ifndef BOOTLOADER
- sd_enable(true);
+ enable_controller(true);
led(true);
#endif
@@ -925,7 +855,7 @@ retry_with_reinit:
exit:
#ifndef BOOTLOADER
- sd_enable(false);
+ enable_controller(false);
led(false);
#endif
mutex_unlock(&sd_mtx);
@@ -952,16 +882,9 @@ long sd_last_disk_activity(void)
void sd_enable(bool on)
{
- if (on)
- {
- bitset32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE);
- CGU_SDSLOT |= (1<<7); /* interface enable */
- }
- else
- {
- CGU_SDSLOT &= ~(1<<7); /* interface enable */
- bitclr32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE);
- }
+ mutex_lock(&sd_mtx);
+ enable_controller(on);
+ mutex_unlock(&sd_mtx);
}
#endif /* BOOTLOADER */
@@ -983,18 +906,13 @@ bool sd_present(IF_MD_NONVOID(int drive))
static int sd1_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
-
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (card_detect_target())
- {
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- }
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
-
+ queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED :
+ SYS_HOTSWAP_EXTRACTED,
+ sd_first_drive + SD_SLOT_AS3525);
return 0;
+ (void)tmo;
}
void sd_gpioa_isr(void)
@@ -1012,9 +930,41 @@ void sd_gpioa_isr(void)
#ifdef CONFIG_STORAGE_MULTI
int sd_num_drives(int first_drive)
{
- /* We don't care which logical drive number(s) we have been assigned */
- (void)first_drive;
-
+ sd_first_drive = first_drive;
return NUM_DRIVES;
}
#endif /* CONFIG_STORAGE_MULTI */
+
+int sd_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx); /* lock-out card activity */
+
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info[data].initialized = 0;
+
+ if (id == SYS_HOTSWAP_INSERTED)
+ {
+ enable_controller(true);
+ rc = sd_init_card(data);
+ enable_controller(false);
+ }
+
+ mutex_unlock(&sd_mtx);
+ break;
+#endif /* HAVE_HOTSWAP */
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
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)
}
#endif /* CONFIG_STORAGE_MULTI */
+
+int nand_event(long id, intptr_t data)
+{
+ return storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_NAND);
+}
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 @@
#include "config.h"
-#ifdef BOOTLOADER
-#define ATA_DRIVER_CLOSE
-#endif
-
#ifdef HAVE_ATA_DMA
/* FIXME does this chips does MWDMA ? */
#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];
#define SDMMC_STATUS(drive) sdmmc_status[drive]
/* sd only */
-static long sdmmc_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
-static const char sdmmc_thread_name[] = "sdmmc";
-static struct event_queue sdmmc_queue;
#if CONFIG_STORAGE & STORAGE_SD
static int sd_first_drive;
static unsigned _sd_num_drives;
@@ -260,10 +257,38 @@ static void sdmmc_detect_callback(int ssp)
{
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if(imx233_ssp_sdmmc_detect(ssp))
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
+ long evid = imx233_ssp_sdmmc_detect(ssp) ?
+ SYS_HOTSWAP_INSERTED : SYS_HOTSWAP_EXTRACTED;
+
+ /* Have to reverse lookup the ssp */
+ for (unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++)
+ {
+ if (SDMMC_SSP(drive) != ssp)
+ continue;
+
+ int first_drive, *map;
+ switch (SDMMC_MODE(drive))
+ {
+#if (CONFIG_STORAGE & STORAGE_MMC)
+ case MMC_MODE:
+ first_drive = mmc_first_drive;
+ map = mmc_map;
+ break;
+#endif
+#if (CONFIG_STORAGE & STORAGE_SD)
+ case SD_MODE:
+ first_drive = sd_first_drive;
+ map = sd_map;
+ break;
+#endif
+ default:
+ continue;
+ }
+
+ /* message requires logical drive number as data */
+ queue_broadcast(evid, first_drive + map[drive]);
+ }
+
imx233_ssp_sdmmc_setup_detect(ssp, true, sdmmc_detect_callback, false,
imx233_ssp_sdmmc_is_detect_inverted(ssp));
}
@@ -483,7 +508,48 @@ static int init_sd_card(int drive)
return 0;
}
-#endif
+
+int sd_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:;
+ const int drive = sd_map[data];
+
+ /* Skip non-removable drivers */
+ if(!sdmmc_removable(drive))
+ {
+ rc = -1;
+ break;
+ }
+
+ mutex_lock(&mutex[drive]); /* lock-out card activity */
+
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ SDMMC_INFO(drive).initialized = 0;
+
+ if(id == SYS_HOTSWAP_INSERTED)
+ rc = init_drive(drive);
+
+ /* unlock card */
+ mutex_unlock(&mutex[drive]);
+ /* Access is now safe */
+ break;
+#endif /* HAVE_HOTSWAP */
+ default:
+ rc = storage_event_default_handler(id, data, sd_last_disk_activity(),
+ STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
+#endif /* CONFIG_STORAGE & STORAGE_SD */
#if CONFIG_STORAGE & STORAGE_MMC
static int init_mmc_drive(int drive)
@@ -573,7 +639,13 @@ static int init_mmc_drive(int drive)
return 0;
}
-#endif
+
+int mmc_event(long id, intptr_t data)
+{
+ return storage_event_default_handler(id, data, mmc_last_disk_activity(),
+ STORAGE_MMC);
+}
+#endif /* CONFIG_STORAGE & STORAGE_MMC */
/* low-level function, don't call directly! */
static int __xfer_sectors(int drive, unsigned long start, int count, void *buf, bool read)
@@ -770,98 +842,6 @@ static int init_drive(int drive)
return 0;
}
-static void sdmmc_thread(void) NORETURN_ATTR;
-static void sdmmc_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
- int timeout = 0;
-
- while (1)
- {
- queue_wait_w_tmo(&sdmmc_queue, &ev, HZ);
-
- switch(ev.id)
- {
-#if CONFIG_STORAGE & STORAGE_SD
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:
- {
- int microsd_init = ev.id == SYS_HOTSWAP_INSERTED ? 0 : 1;
-
- /* We now have exclusive control of fat cache and sd.
- * Release "by force", ensure file
- * descriptors aren't leaked and any busy
- * ones are invalid if mounting. */
- for(unsigned sd_drive = 0; sd_drive < _sd_num_drives; sd_drive++)
- {
- int drive = sd_map[sd_drive];
- /* Skip non-removable drivers */
- if(!sdmmc_removable(drive))
- continue;
-
- disk_unmount(sd_first_drive + sd_drive);
-
- mutex_lock(&mutex[drive]); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- SDMMC_INFO(sd_map[sd_drive]).initialized = 0;
-
- int rc = -1;
- if(ev.id == SYS_HOTSWAP_INSERTED)
- {
- rc = init_drive(drive);
- if(rc < 0) /* initialisation failed */
- panicf("%s init failed : %d", SDMMC_CONF(sd_map[sd_drive]).name, rc);
- }
-
- /* unlock card */
- mutex_unlock(&mutex[drive]);
-
- if (rc >= 0)
- microsd_init += disk_mount(sd_first_drive + sd_drive); /* 0 if fail */
- }
- /* Access is now safe */
- /*
- * One or more mounts succeeded, or this was an EXTRACTED event,
- * in both cases notify the system about the changed filesystems
- */
- if(microsd_init)
- queue_broadcast(SYS_FS_CHANGED, 0);
-
- break;
- }
-#endif
- case SYS_TIMEOUT:
-#if CONFIG_STORAGE & STORAGE_SD
- timeout = MAX(timeout, sd_last_disk_activity()+(3*HZ));
-#endif
-#if CONFIG_STORAGE & STORAGE_MMC
- timeout = MAX(timeout, mmc_last_disk_activity()+(3*HZ));
-#endif
- if(TIME_BEFORE(current_tick, timeout))
- {
- idle_notified = false;
- }
- else
- {
- if(!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- }
- break;
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&sdmmc_queue);
- break;
- }
- }
-}
-
static int sdmmc_init(void)
{
static int is_initialized = false;
@@ -871,10 +851,6 @@ static int sdmmc_init(void)
for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++)
mutex_init(&mutex[drive]);
- queue_init(&sdmmc_queue, true);
- create_thread(sdmmc_thread, sdmmc_stack, sizeof(sdmmc_stack), 0,
- sdmmc_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
-
for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++)
{
if(sdmmc_removable(drive))
@@ -1024,10 +1000,6 @@ void mmc_enable(bool on)
(void) on;
}
-void mmc_sleep(void)
-{
-}
-
void mmc_sleepnow(void)
{
}
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 @@
#include "config.h"
-#ifdef BOOTLOADER
-#define ATA_DRIVER_CLOSE
-#endif
-
/* Plain C read & write loops */
/* They likely won't be used anyway since DMA potentially works for any
* 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 @@
#ifdef HAVE_HOTSWAP
#include "sd-pp-target.h"
#endif
-#include "ata_idle_notify.h"
#include "system.h"
#include <string.h>
-#include "thread.h"
#include "led.h"
-#include "disk.h"
#include "cpu.h"
-#include "panic.h"
-#include "usb.h"
-#include "sd.h"
#include "storage.h"
#include "fs_defines.h"
@@ -151,12 +145,6 @@
/* for compatibility */
static long last_disk_activity = -1;
-/** static, private data **/
-static bool initialized = false;
-static unsigned int sd_thread_id = 0;
-
-#define Q_CLOSE 1
-
static long next_yield = 0;
#define MIN_YIELD_PERIOD 1000
@@ -177,30 +165,28 @@ static struct sd_card_status sd_status[NUM_DRIVES] =
#endif
};
-/* Shoot for around 75% usage */
-static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
-static const char sd_thread_name[] = "ata/sd";
-static struct mutex sd_mtx SHAREDBSS_ATTR;
-static struct event_queue sd_queue SHAREDBSS_ATTR;
+static struct mutex sd_mtx SHAREDBSS_ATTR;
#ifdef HAVE_HOTSWAP
static int sd_first_drive = 0;
#endif
-/* Posted when card plugged status has changed */
-#define SD_HOTSWAP 1
-/* Actions taken by sd_thread when card status has changed */
-enum sd_thread_actions
-{
- SDA_NONE = 0x0,
- SDA_UNMOUNTED = 0x1,
- SDA_MOUNTED = 0x2
-};
-
/* Private Functions */
static unsigned int check_time[NUM_EC];
+static inline void enable_controller(bool on)
+{
+ if(on)
+ {
+ DEV_EN |= DEV_ATA; /* Enable controller */
+ }
+ else
+ {
+ DEV_EN &= ~DEV_ATA; /* Disable controller */
+ }
+}
+
static inline bool sd_check_timeout(long timeout, int id)
{
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,
/* TODO: Add DMA support. */
mutex_lock(&sd_mtx);
- sd_enable(true);
+ enable_controller(true);
led(true);
sd_read_retry:
@@ -964,7 +950,7 @@ sd_read_retry:
while (1)
{
led(false);
- sd_enable(false);
+ enable_controller(false);
mutex_unlock(&sd_mtx);
return ret;
@@ -994,7 +980,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count,
unsigned int bank;
mutex_lock(&sd_mtx);
- sd_enable(true);
+ enable_controller(true);
led(true);
sd_write_retry:
@@ -1092,7 +1078,7 @@ sd_write_retry:
while (1)
{
led(false);
- sd_enable(false);
+ enable_controller(false);
mutex_unlock(&sd_mtx);
return ret;
@@ -1108,182 +1094,79 @@ sd_write_error:
}
}
-#ifndef SD_DRIVER_CLOSE
-static void sd_thread(void) NORETURN_ATTR;
-#endif
-static void sd_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
-
- while (1)
- {
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
-
- switch ( ev.id )
- {
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- disk_unmount(sd_first_drive+1); /* release "by force" */
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card_info[1].initialized = 0;
- sd_status[1].retry = 0;
-
- /* Access is now safe */
- mutex_unlock(&sd_mtx);
-
- if (ev.id == SYS_HOTSWAP_INSERTED)
- success = disk_mount(sd_first_drive+1); /* 0 if fail */
-
- if (success)
- queue_broadcast(SYS_FS_CHANGED, 0);
- break;
-#endif /* HAVE_HOTSWAP */
- case SYS_TIMEOUT:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- {
- idle_notified = false;
- }
- else
- {
- /* never let a timer wrap confuse us */
- next_yield = USEC_TIMER;
-
- if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- }
- break;
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&sd_queue);
- break;
-
-#ifdef SD_DRIVER_CLOSE
- case Q_CLOSE:
- return;
-#endif
- }
- }
-}
-
-#ifdef SD_DRIVER_CLOSE
-void sd_close(void)
-{
- unsigned int thread_id = sd_thread_id;
-
- if (thread_id == 0)
- return;
-
- sd_thread_id = 0;
-
- queue_post(&sd_queue, Q_CLOSE, 0);
- thread_wait(thread_id);
-}
-#endif /* SD_DRIVER_CLOSE */
-
void sd_enable(bool on)
{
- if(on)
- {
- DEV_EN |= DEV_ATA; /* Enable controller */
- }
- else
- {
- DEV_EN &= ~DEV_ATA; /* Disable controller */
- }
+ mutex_lock(&sd_mtx);
+ enable_controller(on);
+ mutex_unlock(&sd_mtx);
}
-
int sd_init(void)
{
int ret = 0;
- if (!initialized)
- mutex_init(&sd_mtx);
-
- mutex_lock(&sd_mtx);
+ mutex_init(&sd_mtx);
led(false);
- if (!initialized)
- {
- initialized = true;
-
- /* init controller */
+ /* init controller */
#if defined(PHILIPS_SA9200)
- GPIOA_ENABLE = 0x00;
- GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01);
+ GPIOA_ENABLE = 0x00;
+ GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01);
#else
- outl(inl(0x70000088) & ~(0x4), 0x70000088);
- outl(inl(0x7000008c) & ~(0x4), 0x7000008c);
- GPO32_ENABLE |= 0x4;
+ outl(inl(0x70000088) & ~(0x4), 0x70000088);
+ outl(inl(0x7000008c) & ~(0x4), 0x7000008c);
+ GPO32_ENABLE |= 0x4;
- GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5));
- GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5));
- GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5));
+ GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5));
+ GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5));
+ GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5));
#endif
#ifdef HAVE_HOTSWAP
- /* enable card detection port - mask interrupt first */
+ /* enable card detection port - mask interrupt first */
#ifdef SANSA_E200
- GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80);
+ GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80);
- GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80);
- GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80);
+ GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80);
+ GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80);
#elif defined SANSA_C200
- GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08);
+ GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08);
- GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08);
- GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08);
+ GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08);
+ GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08);
#endif
#endif
- sd_select_device(0);
-
- if (currcard->initialized < 0)
- ret = currcard->initialized;
+ sd_select_device(0);
- queue_init(&sd_queue, true);
- sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack),
- 0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
- IF_COP(, CPU));
+ if (currcard->initialized < 0)
+ ret = currcard->initialized;
- /* enable interupt for the mSD card */
- sleep(HZ/10);
+ /* enable interupt for the mSD card */
+ sleep(HZ/10);
#ifdef HAVE_HOTSWAP
#ifdef SANSA_E200
- CPU_INT_EN = HI_MASK;
- CPU_HI_INT_EN = GPIO0_MASK;
+ CPU_INT_EN = HI_MASK;
+ CPU_HI_INT_EN = GPIO0_MASK;
- GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80);
+ GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80);
- GPIOA_INT_CLR = 0x80;
+ GPIOA_INT_CLR = 0x80;
- /* enable the card detect interrupt */
- GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
+ /* enable the card detect interrupt */
+ GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
#elif defined SANSA_C200
- CPU_INT_EN = HI_MASK;
- CPU_HI_INT_EN = GPIO2_MASK;
+ CPU_INT_EN = HI_MASK;
+ CPU_HI_INT_EN = GPIO2_MASK;
- GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08);
+ GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08);
- GPIOL_INT_CLR = 0x08;
-
- /* enable the card detect interrupt */
- GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
-#endif
+ GPIOL_INT_CLR = 0x08;
+
+ /* enable the card detect interrupt */
+ GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
#endif
- }
+#endif /* HAVE_HOTSWAP */
mutex_unlock(&sd_mtx);
@@ -1294,19 +1177,17 @@ tCardInfo *card_get_info_target(int card_no)
{
return &card_info[card_no];
}
+
#ifdef HAVE_HOTSWAP
static int sd1_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
-
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (card_detect_target())
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
-
+ queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED :
+ SYS_HOTSWAP_EXTRACTED,
+ sd_first_drive+1);
return 0;
+ (void)tmo;
}
/* called on insertion/removal interrupt */
@@ -1377,3 +1258,36 @@ int sd_num_drives(int first_drive)
#endif
}
#endif
+
+int sd_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx); /* lock-out card activity */
+
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info[data].initialized = 0;
+ sd_status[data].retry = 0;
+
+ /* Access is now safe */
+ mutex_unlock(&sd_mtx);
+ break;
+#endif /* HAVE_HOTSWAP */
+
+ case Q_STORAGE_TICK:
+ /* never let a timer wrap confuse us */
+ next_yield = USEC_TIMER;
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
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 @@
#include "config.h"
-#ifdef HAVE_BOOTLOADER_USB_MODE
-#define ATA_DRIVER_CLOSE
-#endif
-
/* primary channel */
#define ATA_DATA (*((volatile unsigned short*)(IDE_BASE + 0x1e0)))
#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 @@
#include <string.h>
#include "panic.h"
#include "stdbool.h"
-#include "ata_idle_notify.h"
-#include "sd.h"
-#include "usb.h"
-
-#ifdef HAVE_HOTSWAP
-#include "disk.h"
-#endif
+#include "storage.h"
#include "lcd.h"
#include <stdarg.h>
@@ -57,21 +51,39 @@ static tCardInfo card_info;
/* for compatibility */
static long last_disk_activity = -1;
-static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
static unsigned char aligned_buf[512] STORAGE_ALIGN_ATTR;
-static const char sd_thread_name[] = "ata/sd";
static struct mutex sd_mtx SHAREDBSS_ATTR;
-static struct event_queue sd_queue;
#ifndef BOOTLOADER
bool sd_enabled = false;
#endif
+#ifdef CONFIG_STORAGE_MULTI
+static int sd_first_drive = 0;
+#else
+#define sd_first_drive 0
+#endif
+
static struct semaphore transfer_completion_signal;
static struct semaphore command_completion_signal;
static volatile bool retry;
static volatile int cmd_error;
+static void enable_controller(bool on)
+{
+ /* enable or disable clock signal for SD module */
+ if (on)
+ {
+ SCU_CLKCFG &= ~CLKCFG_SD;
+ led(true);
+ }
+ else
+ {
+ SCU_CLKCFG |= CLKCFG_SD;
+ led(false);
+ }
+}
+
/* interrupt handler for SD */
void INT_SD(void)
{
@@ -318,81 +330,6 @@ static int sd_init_card(void)
return 0;
}
-static void sd_thread(void) NORETURN_ATTR;
-static void sd_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
-
- while (1)
- {
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
-
- switch ( ev.id )
- {
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- disk_unmount(sd_first_drive); /* release "by force" */
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card_info.initialized = 0;
-
- if (ev.id == SYS_HOTSWAP_INSERTED)
- {
- success = 0;
- sd_enable(true);
- int rc = sd_init_card(sd_first_drive);
- sd_enable(false);
- if (rc >= 0)
- success = 2;
- else /* initialisation failed */
- panicf("microSD init failed : %d", rc);
- }
-
- /* Access is now safe */
- mutex_unlock(&sd_mtx);
-
- if (success > 1)
- success = disk_mount(sd_first_drive); /* 0 if fail */
-
- /*
- * Mount succeeded, or this was an EXTRACTED event,
- * in both cases notify the system about the changed filesystems
- */
- if (success)
- queue_broadcast(SYS_FS_CHANGED, 0);
-
- break;
-#endif /* HAVE_HOTSWAP */
-
- case SYS_TIMEOUT:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- {
- idle_notified = false;
- }
- else if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- break;
-
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&sd_queue);
-
- break;
- }
- }
-}
-
static void init_controller(void)
{
/* reset SD module */
@@ -441,6 +378,7 @@ int sd_init(void)
{
int ret;
+ mutex_init(&sd_mtx);
semaphore_init(&transfer_completion_signal, 1, 0);
semaphore_init(&command_completion_signal, 1, 0);
@@ -450,13 +388,6 @@ int sd_init(void)
if(ret < 0)
return ret;
- /* init mutex */
- mutex_init(&sd_mtx);
-
- queue_init(&sd_queue, true);
- create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
- sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
-
return 0;
}
@@ -523,7 +454,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count,
unsigned char *dst;
mutex_lock(&sd_mtx);
- sd_enable(true);
+ enable_controller(true);
if (count <= 0 || start + count > card_info.numblocks)
return -1;
@@ -627,7 +558,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count,
} /* while (retry_cnt++ < 20) */
- sd_enable(false);
+ enable_controller(false);
mutex_unlock(&sd_mtx);
return ret;
@@ -659,7 +590,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count,
/* bool card_selected = false; */
mutex_lock(&sd_mtx);
- sd_enable(true);
+ enable_controller(true);
if (count <= 0 || start + count > card_info.numblocks)
return -1;
@@ -731,7 +662,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count,
break;
}
- sd_enable(false);
+ enable_controller(false);
mutex_unlock(&sd_mtx);
#ifdef RK27XX_SD_DEBUG
@@ -746,17 +677,9 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count,
void sd_enable(bool on)
{
- /* enable or disable clock signal for SD module */
- if (on)
- {
- SCU_CLKCFG &= ~CLKCFG_SD;
- led(true);
- }
- else
- {
- SCU_CLKCFG |= CLKCFG_SD;
- led(false);
- }
+ mutex_lock(&sd_mtx);
+ enable_controller(on);
+ mutex_unlock(&sd_mtx);
}
#ifndef BOOTLOADER
@@ -788,18 +711,13 @@ bool sd_present(IF_MD_NONVOID(int drive))
static int sd_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
-
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (card_detect_target())
- {
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- }
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
-
+ queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED :
+ SYS_HOTSWAP_EXTRACTED,
+ sd_first_drive);
return 0;
+ (void)tmo;
}
/* interrupt handler for SD detect */
@@ -809,9 +727,42 @@ static int sd_oneshot_callback(struct timeout *tmo)
#ifdef CONFIG_STORAGE_MULTI
int sd_num_drives(int first_drive)
{
- (void)first_drive;
-
/* we have only one SD drive */
+ sd_first_drive = first_drive;
return 1;
}
#endif /* CONFIG_STORAGE_MULTI */
+
+int sd_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx); /* lock-out card activity */
+
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info.initialized = 0;
+
+ if (id == SYS_HOTSWAP_INSERTED)
+ {
+ enable_controller(true);
+ rc = sd_init_card();
+ enable_controller(false);
+ }
+
+ mutex_unlock(&sd_mtx);
+ break;
+#endif /* HAVE_HOTSWAP */
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
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 @@
#ifndef ATA_TARGET_H
#define ATA_TARGET_H
-#ifdef BOOTLOADER
-#define ATA_DRIVER_CLOSE
-#endif
-
/* Plain C read & write loops */
#define PREFER_C_READING
#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 @@
//#define SD_DEBUG
-#include "sd.h"
#include "system.h"
#include <string.h>
#include "gcc_extensions.h"
-#include "thread.h"
#include "panic.h"
#ifdef SD_DEBUG
@@ -33,8 +31,8 @@
#endif
#ifdef HAVE_HOTSWAP
#include "sdmmc.h"
-#include "disk.h"
#endif
+#include "storage.h"
#include "dma-target.h"
#include "system-target.h"
#include "led-mini2440.h"
@@ -90,6 +88,12 @@ struct sd_card_status
/* for compatibility */
static long last_disk_activity = -1;
+#ifdef CONFIG_STORAGE_MULTI
+static int sd_first_drive = 0;
+#else
+#define sd_first_drive 0
+#endif
+
static bool initialized = false;
static bool sd_enabled = false;
static long next_yield = 0;
@@ -109,11 +113,7 @@ static struct sd_card_status sd_status[NUM_CARDS] =
#endif
#endif
-/* Shoot for around 75% usage */
-static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
-static const char sd_thread_name[] = "sd";
static struct mutex sd_mtx SHAREDBSS_ATTR;
-static struct event_queue sd_queue;
static struct semaphore transfer_completion_signal;
static volatile unsigned int transfer_error[NUM_DRIVES];
/* align on cache line size */
@@ -511,17 +511,13 @@ static inline bool card_detect_target(void)
static int sd1_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
-
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (card_detect_target())
- {
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- }
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
+ queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED :
+ SYS_HOTSWAP_EXTRACTED,
+ sd_first_drive + CARD_NUM_SLOT);
return 0;
+ (void)tmo;
}
void EINT8_23(void)
@@ -571,46 +567,6 @@ bool sd_removable(IF_MD_NONVOID(int card_no))
#endif /* HAVE_HOTSWAP */
/*****************************************************************************/
-static void sd_thread(void) NORETURN_ATTR;
-static void sd_thread(void)
-{
- struct queue_event ev;
-
- /* TODO */
- while (1)
- {
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
- switch ( ev.id )
- {
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- disk_unmount(0); /* release "by force" */
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card_info[0].initialized = 0;
-
- /* Access is now safe */
- mutex_unlock(&sd_mtx);
-
- if (ev.id == SYS_HOTSWAP_INSERTED)
- success = disk_mount(0); /* 0 if fail */
-
- /* notify the system about the changed filesystems
- */
- if (success)
- queue_broadcast(SYS_FS_CHANGED, 0);
- break;
-#endif /* HAVE_HOTSWAP */
- }
- }
-}
-
static int sd_wait_for_state(const int card_no, unsigned int state)
{
unsigned long response = 0;
@@ -907,9 +863,6 @@ int sd_init(void)
semaphore_init(&transfer_completion_signal, 1, 0);
/* init mutex */
mutex_init(&sd_mtx);
- queue_init(&sd_queue, true);
- create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
- sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]);
@@ -950,18 +903,11 @@ tCardInfo *card_get_info_target(int card_no)
int sd_num_drives(int first_drive)
{
dbgprintf ("sd_num_drv");
-#if 0
/* Store which logical drive number(s) we have been assigned */
sd_first_drive = first_drive;
-#endif
-
return NUM_CARDS;
}
-void sd_sleepnow(void)
-{
-}
-
bool sd_disk_is_active(void)
{
return false;
@@ -980,3 +926,27 @@ int sd_spinup_time(void)
#endif /* CONFIG_STORAGE_MULTI */
/*****************************************************************************/
+int sd_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx);
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info[data].initialized = 0;
+ mutex_unlock(&sd_mtx);
+ break;
+#endif /* HAVE_HOTSWAP */
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
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)
void nand_sleep(void)
{
- nand_power_down();
}
void 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 @@
#include <mmu-arm.h>
#include <string.h>
#include "led.h"
-#include "ata_idle_notify.h"
-
+#include "storage.h"
#define NAND_CMD_READ 0x00
#define NAND_CMD_PROGCNFRM 0x10
@@ -91,7 +90,6 @@ static int nand_powered = 0;
static int nand_interleaved = 0;
static int nand_cached = 0;
static long nand_last_activity_value = -1;
-static long nand_stack[DEFAULT_STACK_SIZE];
static struct mutex nand_mtx;
static struct semaphore nand_complete;
@@ -359,20 +357,22 @@ void nand_power_up(void)
void nand_power_down(void)
{
- if (!nand_powered) return;
mutex_lock(&nand_mtx);
- pmu_ldo_power_off(4);
- PCON2 = 0x11111111;
- PDAT2 = 0;
- PCON3 = 0x11111111;
- PDAT3 = 0;
- PCON4 = 0x11111111;
- PDAT4 = 0;
- PCON5 = (PCON5 & ~0xF) | 1;
- PUNK5 = 1;
- PWRCONEXT |= 0x40;
- PWRCON |= 0x100000;
- nand_powered = 0;
+ if (nand_powered)
+ {
+ pmu_ldo_power_off(4);
+ PCON2 = 0x11111111;
+ PDAT2 = 0;
+ PCON3 = 0x11111111;
+ PDAT3 = 0;
+ PCON4 = 0x11111111;
+ PDAT4 = 0;
+ PCON5 = (PCON5 & ~0xF) | 1;
+ PUNK5 = 1;
+ PWRCONEXT |= 0x40;
+ PWRCON |= 0x100000;
+ nand_powered = 0;
+ }
mutex_unlock(&nand_mtx);
}
@@ -714,20 +714,6 @@ const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
return &nand_deviceinfotable[nand_type[bank]];
}
-static void nand_thread(void)
-{
- while (1)
- {
- if (TIME_AFTER(current_tick, nand_last_activity_value + HZ / 5)
- && nand_powered)
- {
- call_storage_idle_notifys(false);
- nand_power_down();
- }
- sleep(HZ / 10);
- }
-}
-
int nand_device_init(void)
{
mutex_init(&nand_mtx);
@@ -776,10 +762,30 @@ int nand_device_init(void)
nand_cached = ((nand_deviceinfotable[nand_type[0]].id >> 23) & 1);
nand_last_activity_value = current_tick;
- create_thread(nand_thread, nand_stack,
- sizeof(nand_stack), 0, "nand"
- IF_PRIO(, PRIORITY_USER_INTERFACE)
- IF_COP(, CPU));
-
return 0;
}
+
+int nand_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ if (LIKELY(id == Q_STORAGE_TICK))
+ {
+ if (!nand_powered ||
+ TIME_BEFORE(current_tick, nand_last_activity_value + HZ / 5))
+ {
+ STG_EVENT_ASSERT_ACTIVE(STORAGE_NAND);
+ }
+ }
+ else if (id == Q_STORAGE_SLEEPNOW)
+ {
+ nand_power_down();
+ }
+ else
+ {
+ rc = storage_event_default_handler(id, data, nand_last_activity_value,
+ STORAGE_NAND);
+ }
+
+ return rc;
+}
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 @@
*
****************************************************************************/
#include "config.h"
-#include "thread.h"
-#include "disk.h"
#include "storage.h"
#include "timer.h"
#include "kernel.h"
@@ -31,8 +29,6 @@
#include "mmcdefs-target.h"
#include "s5l8702.h"
#include "led.h"
-#include "ata_idle_notify.h"
-#include "disk_cache.h"
#ifndef ATA_RETRIES
@@ -58,7 +54,6 @@ static struct semaphore ata_wakeup;
static uint32_t ata_dma_flags;
static long ata_last_activity_value = -1;
static long ata_sleep_timeout = 20 * HZ;
-static uint32_t ata_stack[(DEFAULT_STACK_SIZE + 0x400) / 4];
static bool ata_powered;
static const int ata_retries = ATA_RETRIES;
static 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
return 0;
}
-static void ata_thread(void)
-{
- while (true)
- {
- mutex_lock(&ata_mutex);
- if (TIME_AFTER(current_tick, ata_last_activity_value + ata_sleep_timeout) && ata_powered)
- {
- call_storage_idle_notifys(false);
- ata_power_down();
- }
- mutex_unlock(&ata_mutex);
- sleep(HZ / 2);
- }
-}
-
/* API Functions */
int ata_soft_reset(void)
{
@@ -982,11 +962,6 @@ void ata_spindown(int seconds)
ata_sleep_timeout = seconds * HZ;
}
-void ata_sleep(void)
-{
- ata_last_activity_value = current_tick - ata_sleep_timeout + HZ / 5;
-}
-
void ata_sleepnow(void)
{
mutex_lock(&ata_mutex);
@@ -994,11 +969,6 @@ void ata_sleepnow(void)
mutex_unlock(&ata_mutex);
}
-void ata_close(void)
-{
- ata_sleepnow();
-}
-
void ata_spin(void)
{
ata_set_active();
@@ -1034,10 +1004,6 @@ int ata_init(void)
mutex_unlock(&ata_mutex);
if (IS_ERR(rc)) return rc;
- create_thread(ata_thread, ata_stack,
- sizeof(ata_stack), 0, "ATA idle monitor"
- IF_PRIO(, PRIORITY_USER_INTERFACE)
- IF_COP(, CPU));
return 0;
}
@@ -1129,3 +1095,38 @@ void INT_MMC(void)
SDCI_IRQ = irq;
}
+int ata_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ /* GCC does a lousy job culling unreachable cases in the default handler
+ if statements are in a switch statement, so we'll do it this way. Only
+ the first case is frequently hit anyway. */
+ if (LIKELY(id == Q_STORAGE_TICK))
+ {
+ if (!ata_powered ||
+ TIME_BEFORE(current_tick, ata_last_activity_value + ata_sleep_timeout))
+ {
+ STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA);
+ }
+ }
+ else if (id == Q_STORAGE_SLEEPNOW)
+ {
+ ata_sleepnow();
+ }
+ else if (id == Q_STORAGE_SLEEP)
+ {
+ ata_last_activity_value = current_tick - ata_sleep_timeout + HZ / 5;
+ }
+ else if (id == SYS_USB_CONNECTED)
+ {
+ STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA);
+ }
+ else
+ {
+ rc = storage_event_default_handler(id, data, ata_last_activity_value,
+ STORAGE_ATA);
+ }
+
+ return rc;
+}
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 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include "sd.h"
+#include "config.h"
#include "system.h"
#include <string.h>
#include "gcc_extensions.h"
#include "sdmmc.h"
#include "storage.h"
#include "led.h"
-#include "thread.h"
-#include "disk.h"
-#include "ata_idle_notify.h"
-#include "usb.h"
#if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP)
#define CARD_NUM_INTERNAL 0
@@ -55,9 +51,6 @@
/* for compatibility */
static long last_disk_activity = -1;
-/** static, private data **/
-static bool initialized = false;
-
static long next_yield = 0;
#define MIN_YIELD_PERIOD 1000
@@ -80,14 +73,13 @@ static struct sd_card_status sd_status[NUM_DRIVES] =
#endif
};
-/* Shoot for around 75% usage */
-static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
-static const char sd_thread_name[] = "sd";
static struct mutex sd_mtx SHAREDBSS_ATTR;
-static struct event_queue sd_queue;
+#ifdef CONFIG_STORAGE_MULTI
static int sd_first_drive = 0;
-
+#else
+#define sd_first_drive 0
+#endif
static bool sd_poll_status(unsigned int trigger, long timeout)
{
@@ -216,16 +208,13 @@ static inline bool card_detect_target(void)
static int sd1_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
-
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (card_detect_target())
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
-
+ queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED :
+ SYS_HOTSWAP_EXTRACTED,
+ sd_first_drive + CARD_NUM_SLOT);
return 0;
+ (void)tmo;
}
void EXT0(void)
@@ -642,71 +631,6 @@ sd_write_error:
}
}
-static void sd_thread(void) NORETURN_ATTR;
-static void sd_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
-
- while (1)
- {
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
-
- switch ( ev.id )
- {
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- /* Release "by force" */
- disk_unmount(sd_first_drive + CARD_NUM_SLOT);
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card_info[CARD_NUM_SLOT].initialized = 0;
- sd_status[CARD_NUM_SLOT].retry = 0;
-
- mutex_unlock(&sd_mtx);
-
- if (ev.id == SYS_HOTSWAP_INSERTED)
- success = disk_mount(sd_first_drive + CARD_NUM_SLOT);
-
- if (success)
- queue_broadcast(SYS_FS_CHANGED, 0);
-
- break;
-#endif /* HAVE_HOTSWAP */
-
- case SYS_TIMEOUT:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- {
- idle_notified = false;
- }
- else
- {
- /* never let a timer wrap confuse us */
- next_yield = USEC_TIMER;
-
- if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- }
- break;
-
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&sd_queue);
- break;
- }
- }
-}
-
void sd_enable(bool on)
{
if(on)
@@ -725,6 +649,7 @@ void sd_enable(bool on)
int sd_init(void)
{
+ static bool initialized = false;
int ret = 0;
if (!initialized)
@@ -752,11 +677,6 @@ int sd_init(void)
/* Configure card power(?) GPIO as output */
GPIOC_DIR |= (1<<24);
- queue_init(&sd_queue, true);
- create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
- sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
- IF_COP(, CPU));
-
sleep(HZ/10);
#ifdef HAVE_HOTSWAP
@@ -794,10 +714,6 @@ int sd_num_drives(int first_drive)
#endif
}
-void sd_sleepnow(void)
-{
-}
-
bool sd_disk_is_active(void)
{
return false;
@@ -814,3 +730,28 @@ int sd_spinup_time(void)
}
#endif /* CONFIG_STORAGE_MULTI */
+
+int sd_event(long id, intptr_t data)
+{
+ int rc = 0;
+
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx);
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info[data].initialized = 0;
+ sd_status[data].retry = 0;
+ mutex_unlock(&sd_mtx);
+ break;
+#endif /* HAVE_HOTSWAP */
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity, STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
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 @@
*
****************************************************************************/
-#include "sd.h"
#include "system.h"
#include <string.h>
#include "gcc_extensions.h"
-#include "thread.h"
#include "panic.h"
-#include "kernel.h"
#include "dma-target.h"
#include "ata_idle_notify.h"
@@ -42,8 +39,8 @@
#endif
#endif
#include "sdmmc.h"
-#include "disk.h"
#include "system-target.h"
+#include "storage.h"
/* The configuration method is not very flexible. */
#define CARD_NUM_SLOT 1
@@ -105,7 +102,6 @@ struct sd_card_status
static long last_disk_activity = -1;
static bool initialized = false;
-static unsigned int sd_thread_id = 0;
static bool sd_enabled = false;
static long next_yield = 0;
@@ -122,10 +118,7 @@ static struct sd_card_status sd_status[NUM_CARDS] =
};
/* Shoot for around 75% usage */
-static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
-static const char sd_thread_name[] = "sd";
static struct mutex sd_mtx SHAREDBSS_ATTR;
-static struct event_queue sd_queue;
static volatile unsigned int transfer_error[NUM_DRIVES];
/* align on cache line size */
static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE]
@@ -154,20 +147,16 @@ static void sd_card_mux(int card_no)
#endif
}
+static inline void enable_controller(bool on)
+{
+ sd_enabled = on;
+}
void sd_enable(bool on)
{
- if (sd_enabled == on)
- return; /* nothing to do */
-
- if (on)
- {
- sd_enabled = true;
- }
- else
- {
- sd_enabled = false;
- }
+ mutex_lock(&sd_mtx);
+ enable_controller(on);
+ mutex_unlock(&sd_mtx);
}
/* sets clock rate just like OF does */
@@ -514,17 +503,13 @@ static inline bool card_detect_target(void)
static int sd1_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
-
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (card_detect_target())
- {
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- }
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
+ queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED :
+ SYS_HOTSWAP_EXTRACTED,
+ CARD_NUM_SLOT);
return 0;
+ (void)tmo;
}
#ifdef SANSA_CONNECT
@@ -577,57 +562,6 @@ bool sd_removable(IF_MD_NONVOID(int card_no))
#endif /* HAVE_HOTSWAP */
-static void sd_thread(void) NORETURN_ATTR;
-static void sd_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
-
- while (1)
- {
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
- switch ( ev.id )
- {
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- disk_unmount(0); /* release "by force" */
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card_info[0].initialized = 0;
-
- mutex_unlock(&sd_mtx);
-
- if (ev.id == SYS_HOTSWAP_INSERTED)
- success = disk_mount(0); /* 0 if fail */
-
- /* notify the system about the changed filesystems */
- if (success)
- queue_broadcast(SYS_FS_CHANGED, 0);
-
- break;
-#endif /* HAVE_HOTSWAP */
-
- case SYS_TIMEOUT:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- {
- idle_notified = false;
- }
- else if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- break;
- }
- }
-}
-
static int sd_wait_for_state(unsigned int state)
{
unsigned long response = 0;
@@ -671,7 +605,7 @@ static int sd_transfer_sectors(int card_no, unsigned long start,
dbgprintf("transfer %d %d %d", card_no, start, count);
mutex_lock(&sd_mtx);
- sd_enable(true);
+ enable_controller(true);
sd_transfer_retry:
if (card_no == CARD_NUM_SLOT && !card_detect_target())
@@ -812,7 +746,7 @@ sd_transfer_retry:
while (1)
{
- sd_enable(false);
+ enable_controller(false);
mutex_unlock(&sd_mtx);
return ret;
@@ -860,14 +794,17 @@ int sd_init(void)
{
int ret = EC_OK;
-#ifndef BOOTLOADER
- sd_enabled = true;
- sd_enable(false);
-#endif
- mutex_init(&sd_mtx);
+ if (!initialized)
+ {
+ mutex_init(&sd_mtx);
+ initialized = true;
+ }
mutex_lock(&sd_mtx);
- initialized = true;
+
+#ifndef BOOTLOADER
+ enable_controller(false);
+#endif
/* based on linux/drivers/mmc/dm320mmc.c
Copyright (C) 2006 ZSI, All Rights Reserved.
@@ -919,12 +856,6 @@ int sd_init(void)
/* Disable Memory Card CLK - it is enabled on demand by TMS320DM320 */
bitclr16(&IO_MMC_MEM_CLK_CONTROL, (1 << 8));
-
- queue_init(&sd_queue, true);
- sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack),
- 0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
- IF_COP(, CPU));
-
mutex_unlock(&sd_mtx);
return ret;
@@ -940,7 +871,27 @@ tCardInfo *card_get_info_target(int card_no)
return &card_info[card_no];
}
-void sd_sleepnow(void)
+int sd_event(long id, intptr_t data)
{
-}
+ int rc = 0;
+ switch (id)
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx); /* lock-out card activity */
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info[data].initialized = 0;
+ mutex_unlock(&sd_mtx);
+ break;
+#endif /* HAVE_HOTSWAP */
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_SD);
+ break;
+ }
+
+ return rc;
+}
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 @@
#include "config.h"
#include "gcc_extensions.h"
#include "jz4740.h"
-#include "ata.h"
-#include "ata_idle_notify.h"
#include "ata-sd-target.h"
-#include "disk.h"
#include "led.h"
#include "sdmmc.h"
#include "logf.h"
-#include "sd.h"
-#include "system.h"
-#include "kernel.h"
#include "storage.h"
#include "string.h"
-#include "usb.h"
static long last_disk_activity = -1;
#if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP)
static int sd_drive_nr = 0;
+#else
+#define sd_drive_nr 0
#endif
static tCardInfo card;
-static long sd_stack[(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
-static const char sd_thread_name[] = "ata/sd";
-static struct event_queue sd_queue;
static struct mutex sd_mtx;
static struct semaphore sd_wakeup;
-static void sd_thread(void) NORETURN_ATTR;
static int use_4bit;
static int num_6;
@@ -1229,11 +1220,6 @@ int sd_init(void)
{
semaphore_init(&sd_wakeup, 1, 0);
mutex_init(&sd_mtx);
- queue_init(&sd_queue, true);
- create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
- sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
- IF_COP(, CPU));
-
inited = true;
}
@@ -1265,7 +1251,7 @@ static inline void sd_stop_transfer(void)
mutex_unlock(&sd_mtx);
}
-int sd_read_sectors(IF_MV(int drive,) unsigned long start, int count, void* buf)
+int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count, void* buf)
{
#ifdef HAVE_MULTIVOLUME
(void)drive;
@@ -1404,7 +1390,7 @@ int sd_soft_reset(void)
}
#ifdef HAVE_HOTSWAP
-bool sd_removable(IF_MV_NONVOID(int drive))
+bool sd_removable(IF_MD_NONVOID(int drive))
{
#ifdef HAVE_MULTIVOLUME
(void)drive;
@@ -1414,19 +1400,16 @@ bool sd_removable(IF_MV_NONVOID(int drive))
static int sd_oneshot_callback(struct timeout *tmo)
{
- (void)tmo;
int state = card_detect_target();
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
- if (state)
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
- else
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
+ queue_broadcast(state ? SYS_HOTSWAP_INSERTED : SYS_HOTSWAP_EXTRACTED,
+ sd_drive_nr);
sd_gpio_setup_irq(state);
-
return 0;
+ (void)tmo;
}
/* called on insertion/removal interrupt */
@@ -1453,58 +1436,27 @@ int sd_num_drives(int first_drive)
}
#endif
-static void sd_thread(void)
+int sd_event(long id, intptr_t data)
{
- struct queue_event ev;
- bool idle_notified = false;
+ int rc = 0;
- while (1)
+ switch (id)
{
- queue_wait_w_tmo(&sd_queue, &ev, HZ);
-
- switch (ev.id)
- {
#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- case SYS_HOTSWAP_EXTRACTED:;
- int success = 1;
-
- disk_unmount(sd_drive_nr); /* release "by force" */
-
- mutex_lock(&sd_mtx); /* lock-out card activity */
-
- /* Force card init for new card, re-init for re-inserted one or
- * clear if the last attempt to init failed with an error. */
- card.initialized = 0;
-
- mutex_unlock(&sd_mtx);
-
- if(ev.id == SYS_HOTSWAP_INSERTED)
- success = disk_mount(sd_drive_nr); /* 0 if fail */
-
- if(success)
- queue_broadcast(SYS_FS_CHANGED, 0);
-
- break;
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ mutex_lock(&sd_mtx); /* lock-out card activity */
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card.initialized = 0;
+ mutex_unlock(&sd_mtx);
+ break;
#endif /* HAVE_HOTSWAP */
-
- case SYS_TIMEOUT:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- idle_notified = false;
- else
- {
- if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- }
- break;
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&sd_queue);
- break;
- }
+ default:
+ rc = storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_SD);
+ break;
}
+
+ return rc;
}
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 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include <stdbool.h>
-#include "mmc.h"
+#include "config.h"
#include "ata_mmc.h"
#include "sdmmc.h"
-#include "ata_idle_notify.h"
#include "kernel.h"
-#include "thread.h"
#include "led.h"
#include "sh7034.h"
#include "system.h"
#include "debug.h"
#include "panic.h"
-#include "usb.h"
#include "power.h"
#include "string.h"
#include "hwcompat.h"
#include "adc.h"
#include "bitswap.h"
-#include "disk.h" /* for mount/unmount */
#include "storage.h"
+
+#ifdef HAVE_MULTIDRIVE
+#define MMC_NUM_DRIVES 2
+#else
+#define MMC_NUM_DRIVES 1
+#endif
+
#define BLOCK_SIZE 512 /* fixed */
/* Command definitions */
@@ -90,15 +92,14 @@ static long last_disk_activity = -1;
/* private variables */
-static struct mutex mmc_mutex SHAREDBSS_ATTR;
-
-#ifdef HAVE_HOTSWAP
-static long mmc_stack[((DEFAULT_STACK_SIZE*2) + 0x800)/sizeof(long)];
+#ifdef CONFIG_STORAGE_MULTI
+static int mmc_first_drive = 0;
#else
-static long mmc_stack[(DEFAULT_STACK_SIZE*2)/sizeof(long)];
+#define mmc_first_drive 0
#endif
-static const char mmc_thread_name[] = "mmc";
-static struct event_queue mmc_queue SHAREDBSS_ATTR;
+
+static struct mutex mmc_mutex SHAREDBSS_ATTR;
+
static bool initialized = false;
static bool new_mmc_circuit;
@@ -158,6 +159,21 @@ static void mmc_tick(void);
/* implementation */
+static void enable_controller(bool on)
+{
+ PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIO,
+ * if not modified below */
+ if (on)
+ PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */
+
+ and_b(~0x80, &PADRL); /* assert flash reset */
+ sleep(HZ/100);
+ or_b(0x80, &PADRL); /* de-assert flash reset */
+ sleep(HZ/100);
+ card_info[0].initialized = false;
+ card_info[1].initialized = false;
+}
+
void mmc_enable_int_flash_clock(bool on)
{
/* Internal flash clock is enabled by setting PA12 high with the new
@@ -763,51 +779,6 @@ bool mmc_disk_is_active(void)
return mutex_test(&mmc_mutex);
}
-static void mmc_thread(void)
-{
- struct queue_event ev;
- bool idle_notified = false;
-
- while (1) {
- queue_wait_w_tmo(&mmc_queue, &ev, HZ);
- switch ( ev.id )
- {
- case SYS_USB_CONNECTED:
- usb_acknowledge(SYS_USB_CONNECTED_ACK);
- /* Wait until the USB cable is extracted again */
- usb_wait_for_disconnect(&mmc_queue);
- break;
-
-#ifdef HAVE_HOTSWAP
- case SYS_HOTSWAP_INSERTED:
- disk_mount(1); /* mount MMC */
- queue_broadcast(SYS_FS_CHANGED, 0);
- break;
-
- case SYS_HOTSWAP_EXTRACTED:
- disk_unmount(1); /* release "by force" */
- queue_broadcast(SYS_FS_CHANGED, 0);
- break;
-#endif
-
- default:
- if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
- {
- idle_notified = false;
- }
- else
- {
- if (!idle_notified)
- {
- call_storage_idle_notifys(false);
- idle_notified = true;
- }
- }
- break;
- }
- }
-}
-
bool mmc_detect(void)
{
return (adc_read(ADC_MMC_SWITCH) < 0x200);
@@ -868,11 +839,11 @@ static void mmc_tick(void)
{
if (current_status)
{
- queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
+ queue_broadcast(SYS_HOTSWAP_INSERTED, mmc_first_drive + 1);
}
else
{
- queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
+ queue_broadcast(SYS_HOTSWAP_EXTRACTED, mmc_first_drive + 1);
mmc_status = MMC_UNTOUCHED;
card_info[1].initialized = false;
}
@@ -882,17 +853,9 @@ static void mmc_tick(void)
void mmc_enable(bool on)
{
- PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIO,
- * if not modified below */
- if (on)
- PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */
-
- and_b(~0x80, &PADRL); /* assert flash reset */
- sleep(HZ/100);
- or_b(0x80, &PADRL); /* de-assert flash reset */
- sleep(HZ/100);
- card_info[0].initialized = false;
- card_info[1].initialized = false;
+ mutex_lock(&mmc_mutex);
+ enable_controller(on);
+ mutex_unlock(&mmc_mutex);
}
int mmc_init(void)
@@ -900,10 +863,8 @@ int mmc_init(void)
int rc = 0;
if (!initialized)
- {
mutex_init(&mmc_mutex);
- queue_init(&mmc_queue, true);
- }
+
mutex_lock(&mmc_mutex);
led(false);
@@ -933,15 +894,10 @@ int mmc_init(void)
IPRE &= 0x0FFF; /* disable SCI1 interrupts for the CPU */
new_mmc_circuit = ((HW_MASK & MMC_CLOCK_POLARITY) != 0);
-
- create_thread(mmc_thread, mmc_stack,
- sizeof(mmc_stack), 0, mmc_thread_name
- IF_PRIO(, PRIORITY_SYSTEM)
- IF_COP(, CPU));
tick_add_task(mmc_tick);
initialized = true;
}
- mmc_enable(true);
+ enable_controller(true);
mutex_unlock(&mmc_mutex);
return rc;
@@ -998,11 +954,6 @@ bool mmc_present(IF_MD_NONVOID(int drive))
}
#endif
-
-void mmc_sleep(void)
-{
-}
-
void mmc_spin(void)
{
}
@@ -1015,13 +966,13 @@ void mmc_spindown(int seconds)
#ifdef CONFIG_STORAGE_MULTI
int mmc_num_drives(int first_drive)
{
- /* We don't care which logical drive number(s) we have been assigned */
- (void)first_drive;
-
-#ifdef HAVE_MULTIDRIVE
- return 2;
-#else
- return 1;
-#endif
+ mmc_first_drive = first_drive;
+ return MMC_NUM_DRIVES;
+}
+#endif /* CONFIG_STORAGE_MULTI */
+
+int mmc_event(long id, intptr_t data)
+{
+ return storage_event_default_handler(id, data, last_disk_activity,
+ STORAGE_MMC);
}
-#endif