summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/common/disk.c5
-rw-r--r--firmware/drivers/audio/as3514.c3
-rw-r--r--firmware/drivers/fat.c19
-rw-r--r--firmware/export/fat.h4
-rw-r--r--firmware/target/arm/i2c-pp.c3
-rw-r--r--firmware/target/arm/sandisk/ata-c200_e200.c65
-rw-r--r--firmware/target/arm/wmcodec-pp.c3
7 files changed, 73 insertions, 29 deletions
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index 3d4dd3dc1d..c6200ba286 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -104,7 +104,7 @@ int disk_mount_all(void)
int mounted;
int i;
-#ifdef HAVE_MMC
+#if defined(HAVE_MMC) || defined(HAVE_HOTSWAP)
card_enable_monitoring(false);
#endif
@@ -118,10 +118,9 @@ int disk_mount_all(void)
{
mounted += disk_mount(1); /* try 2nd "drive", too */
}
-#ifdef HAVE_MMC
+
card_enable_monitoring(true);
#endif
-#endif
return mounted;
}
diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c
index 08d4d538a4..d51341d8c3 100644
--- a/firmware/drivers/audio/as3514.c
+++ b/firmware/drivers/audio/as3514.c
@@ -132,9 +132,6 @@ void audiohw_init(void)
{
unsigned int i;
- /* reset I2C */
- i2c_init();
-
/* normal outputs for CDI and I2S pin groups */
DEV_INIT2 &= ~0x300;
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 9dd27cf72a..f3374fc4c4 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -172,6 +172,7 @@ struct bpb
};
static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
+static bool initialized = false;
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb));
@@ -202,6 +203,18 @@ static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE];
static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
static struct mutex cache_mutex NOCACHEBSS_ATTR;
+#ifdef HAVE_HOTSWAP
+void fat_lock(void)
+{
+ mutex_lock(&cache_mutex);
+}
+
+void fat_unlock(void)
+{
+ mutex_unlock(&cache_mutex);
+}
+#endif
+
static long cluster2sec(IF_MV2(struct bpb* fat_bpb,) long cluster)
{
#ifndef HAVE_MULTIVOLUME
@@ -240,7 +253,11 @@ void fat_init(void)
{
unsigned int i;
- mutex_init(&cache_mutex);
+ if (!initialized)
+ {
+ initialized = true;
+ mutex_init(&cache_mutex);
+ }
/* mark the FAT cache as unused */
for(i = 0;i < FAT_CACHE_SIZE;i++)
diff --git a/firmware/export/fat.h b/firmware/export/fat.h
index 0dfd395ea7..3cf2923b78 100644
--- a/firmware/export/fat.h
+++ b/firmware/export/fat.h
@@ -82,6 +82,10 @@ struct fat_dir
unsigned char sectorcache[3][SECTOR_SIZE];
};
+#ifdef HAVE_HOTSWAP
+extern void fat_lock(void);
+extern void fat_unlock(void);
+#endif
extern void fat_init(void);
extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector);
diff --git a/firmware/target/arm/i2c-pp.c b/firmware/target/arm/i2c-pp.c
index b8e3869907..092a59be84 100644
--- a/firmware/target/arm/i2c-pp.c
+++ b/firmware/target/arm/i2c-pp.c
@@ -187,6 +187,7 @@ int pp_i2c_send(unsigned int addr, int data0, int data1)
void i2c_init(void)
{
/* From ipodlinux */
+ mutex_init(&i2c_mtx);
#ifdef IPOD_MINI
/* GPIO port C disable port 0x10 */
@@ -231,7 +232,5 @@ void i2c_init(void)
#endif
#endif
- mutex_init(&i2c_mtx);
-
i2c_readbyte(0x8, 0);
}
diff --git a/firmware/target/arm/sandisk/ata-c200_e200.c b/firmware/target/arm/sandisk/ata-c200_e200.c
index 150b08fd92..99a00358ff 100644
--- a/firmware/target/arm/sandisk/ata-c200_e200.c
+++ b/firmware/target/arm/sandisk/ata-c200_e200.c
@@ -16,7 +16,7 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include "ata.h"
+#include "fat.h"
#include "hotswap-target.h"
#include "ata-target.h"
#include "ata_idle_notify.h"
@@ -29,8 +29,8 @@
#include "panic.h"
#include "usb.h"
-#define BLOCK_SIZE (512)
-#define SECTOR_SIZE (512)
+#define BLOCK_SIZE 512
+#define SECTOR_SIZE 512
#define BLOCKS_PER_BANK 0x7a7800
#define STATUS_REG (*(volatile unsigned int *)(0x70008204))
@@ -1045,22 +1045,33 @@ static void sd_thread(void)
{
#ifdef HAVE_HOTSWAP
case SYS_HOTSWAP_INSERTED:
- mutex_lock(&sd_mtx); /* Lock-out card activity */
- card_info[1].initialized = 0;
- sd_status[1].retry = 0;
- disk_unmount(1); /* Force remount */
- disk_mount(1); /* mount microSD card */
- queue_broadcast(SYS_FS_CHANGED, 0);
- mutex_unlock(&sd_mtx);
- break;
-
case SYS_HOTSWAP_EXTRACTED:
- mutex_lock(&sd_mtx); /* Lock-out card activity */
- card_info[1].initialized = 0;
+ fat_lock(); /* lock-out FAT activity first -
+ prevent deadlocking via disk_mount that
+ would cause a reverse-order attempt with
+ another thread */
+ mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
+ into driver that bypass the fat cache */
+
+ /* We now have exclusive control of fat cache and ata */
+
+ disk_unmount(1); /* release "by force", ensure file
+ descriptors aren't leaked and any busy
+ ones are invalid if mounting */
+
+ /* 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;
- disk_unmount(1); /* release "by force" */
+
+ if (ev.id == SYS_HOTSWAP_INSERTED)
+ disk_mount(1);
+
queue_broadcast(SYS_FS_CHANGED, 0);
+
+ /* Access is now safe */
mutex_unlock(&sd_mtx);
+ fat_unlock();
break;
#endif
case SYS_TIMEOUT:
@@ -1135,6 +1146,28 @@ void ata_enable(bool on)
}
}
+#ifdef HAVE_HOTSWAP
+void card_enable_monitoring(bool on)
+{
+ if (on)
+ {
+#ifdef SANSA_E200
+ GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
+#elif defined(SANSA_C200)
+ GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
+#endif
+ }
+ else
+ {
+#ifdef SANSA_E200
+ GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80);
+#elif defined(SANSA_C200)
+ GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08);
+#endif
+ }
+}
+#endif
+
int ata_init(void)
{
int ret = 0;
@@ -1193,7 +1226,6 @@ int ata_init(void)
GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80);
GPIOA_INT_CLR = 0x80;
- GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
#elif defined SANSA_C200
CPU_INT_EN = HI_MASK;
CPU_HI_INT_EN = GPIO2_MASK;
@@ -1201,7 +1233,6 @@ int ata_init(void)
GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08);
GPIOL_INT_CLR = 0x08;
- GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
#endif
#endif
}
diff --git a/firmware/target/arm/wmcodec-pp.c b/firmware/target/arm/wmcodec-pp.c
index 3bd9d7fd2b..cfdd311c52 100644
--- a/firmware/target/arm/wmcodec-pp.c
+++ b/firmware/target/arm/wmcodec-pp.c
@@ -41,9 +41,6 @@
* Initialise the PP I2C and I2S.
*/
void audiohw_init(void) {
- /* reset I2C */
- i2c_init();
-
#ifdef CPU_PP502x
/* normal outputs for CDI and I2S pin groups */
DEV_INIT2 &= ~0x300;