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 #include -#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,23 +59,27 @@ #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; +#if defined(HAVE_USBSTACK) +#define ATA_ACTIVE_IN_USB 1 +#else +#define ATA_ACTIVE_IN_USB 0 #endif -#if defined(HAVE_USBSTACK) -#define ALLOW_USB_SPINDOWN -#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(§or_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 + 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 #include "config.h" /* for HAVE_MULTIDRIVE or not */ #include "mv.h" +#include #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 - -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; - - 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) - { +/* defaults: override elsewhere target-wise if they must be different */ #if (CONFIG_STORAGE & STORAGE_ATA) - case STORAGE_ATA: - return ata_write_sectors(IF_MD(ldrive,)start,count,buf); + #ifndef ATA_THREAD_STACK_SIZE + #define ATA_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2) + #endif #endif - #if (CONFIG_STORAGE & STORAGE_MMC) - case STORAGE_MMC: - return mmc_write_sectors(IF_MD(ldrive,)start,count,buf); + #ifndef MMC_THREAD_STACK_SIZE + #define MMC_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2) + #endif #endif - #if (CONFIG_STORAGE & STORAGE_SD) - case STORAGE_SD: - return sd_write_sectors(IF_MD(ldrive,)start,count,buf); + #ifndef SD_THREAD_STACK_SIZE + #define SD_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2) + #endif #endif - #if (CONFIG_STORAGE & STORAGE_NAND) - case STORAGE_NAND: - return nand_write_sectors(IF_MD(ldrive,)start,count,buf); + #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 -#if (CONFIG_STORAGE & STORAGE_RAMDISK) - case STORAGE_RAMDISK: - return ramdisk_write_sectors(IF_MD(ldrive,)start,count,buf); +static struct event_queue storage_queue SHAREDBSS_ATTR; +static unsigned int storage_thread_id = 0; + +static union { +#if (CONFIG_STORAGE & STORAGE_ATA) + long stk_ata[ATA_THREAD_STACK_SIZE / sizeof (long)]; #endif - } - - return -1; -#else /* CONFIG_STORAGE_MULTI */ - return STORAGE_FUNCTION(write_sectors)(IF_MD(drive,)start,count,buf); -#endif /* CONFIG_STORAGE_MULTI */ -} +#if (CONFIG_STORAGE & STORAGE_MMC) + long stk_mmc[MMC_THREAD_STACK_SIZE / sizeof (long)]; +#endif +#if (CONFIG_STORAGE & STORAGE_SD) + long stk_sd[SD_THREAD_STACK_SIZE / sizeof (long)]; +#endif +#if (CONFIG_STORAGE & STORAGE_NAND) + 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) + "/ramdisk" +#endif + ; + +/* event is targeted to a specific drive */ +#define DRIVE_EVT (1 << STORAGE_NUM_TYPES) #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) +static int storage_event_send(unsigned int route, long id, intptr_t data) { - return num_drives; + /* 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) + if (route & STORAGE_ATA) { + rc = ata_event(id, data); + } +#endif +#if (CONFIG_STORAGE & STORAGE_MMC) + if (route & STORAGE_MMC) { + rc = mmc_event(id, data); + } +#endif +#if (CONFIG_STORAGE & STORAGE_SD) + if (route & STORAGE_SD) { + rc = sd_event(id, data); + } +#endif +#if (CONFIG_STORAGE & STORAGE_NAND) + if (route & STORAGE_NAND) { + rc = nand_event(id, data); + } +#endif +#if (CONFIG_STORAGE & STORAGE_RAMDISK) + if (route & STORAGE_RAMDISK) { + rc = ramdisk_event(id, data); + } +#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 */ + +static void NORETURN_ATTR storage_thread(void) +{ + unsigned int bdcast = CONFIG_STORAGE; + bool usb_mode = false; + struct queue_event ev; + + 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; + +#if (CONFIG_STORAGE & STORAGE_ATA) + case Q_STORAGE_SLEEP: + storage_event_send(bdcast, ev.id, 0); + break; +#endif + +#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 */ + } + } } -int storage_driver_type(int drive) +#if (CONFIG_STORAGE & STORAGE_ATA) +void storage_sleep(void) { - if ((unsigned int)drive >= num_drives) - return -1; + if (storage_thread_id) { + queue_post(&storage_queue, Q_STORAGE_SLEEP, 0); + } +} +#endif /* (CONFIG_STORAGE & STORAGE_ATA) */ - unsigned int bit = (storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET; - return bit ? find_first_set_bit(bit) : -1; +#ifdef STORAGE_CLOSE +void storage_close(void) +{ + if (storage_thread_id) { + queue_post(&storage_queue, Q_STORAGE_CLOSE, 0); + thread_wait(storage_thread_id); + } +} +#endif /* STORAGE_CLOSE */ + +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,10 +329,121 @@ int storage_init(void) (STORAGE_RAMDISK<>DRIVER_OFFSET; + int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET; + + 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) + case STORAGE_ATA: + return ata_write_sectors(IF_MD(ldrive,)start,count,buf); +#endif + +#if (CONFIG_STORAGE & STORAGE_MMC) + case STORAGE_MMC: + return mmc_write_sectors(IF_MD(ldrive,)start,count,buf); +#endif + +#if (CONFIG_STORAGE & STORAGE_SD) + case STORAGE_SD: + return sd_write_sectors(IF_MD(ldrive,)start,count,buf); +#endif + +#if (CONFIG_STORAGE & STORAGE_NAND) + case STORAGE_NAND: + return nand_write_sectors(IF_MD(ldrive,)start,count,buf); +#endif + +#if (CONFIG_STORAGE & STORAGE_RAMDISK) + 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 */ +} + +#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) { @@ -229,29 +468,6 @@ void storage_enable(bool on) #endif } -void storage_sleep(void) -{ -#if (CONFIG_STORAGE & STORAGE_ATA) - ata_sleep(); -#endif - -#if (CONFIG_STORAGE & STORAGE_MMC) - mmc_sleep(); -#endif - -#if (CONFIG_STORAGE & STORAGE_SD) - sd_sleep(); -#endif - -#if (CONFIG_STORAGE & STORAGE_NAND) - nand_sleep(); -#endif - -#if (CONFIG_STORAGE & STORAGE_RAMDISK) - ramdisk_sleep(); -#endif -} - void storage_sleepnow(void) { #if (CONFIG_STORAGE & STORAGE_ATA) @@ -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 -#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 -#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); + sd_select_device(0); - if (currcard->initialized < 0) - ret = currcard->initialized; + if (currcard->initialized < 0) + ret = currcard->initialized; - 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)); - - /* 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); + GPIOL_INT_CLR = 0x08; + + /* enable the card detect interrupt */ + GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); #endif -#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 #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 @@ -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 #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 #include #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 #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 #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 -#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 */ +#ifdef CONFIG_STORAGE_MULTI +static int mmc_first_drive = 0; +#else +#define mmc_first_drive 0 +#endif + static struct mutex mmc_mutex SHAREDBSS_ATTR; -#ifdef HAVE_HOTSWAP -static long mmc_stack[((DEFAULT_STACK_SIZE*2) + 0x800)/sizeof(long)]; -#else -static long mmc_stack[(DEFAULT_STACK_SIZE*2)/sizeof(long)]; -#endif -static const char mmc_thread_name[] = "mmc"; -static struct event_queue mmc_queue 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