Index: apps/screens.c
===================================================================
--- apps/screens.c	(revision 13403)
+++ apps/screens.c	(working copy)
@@ -147,8 +147,8 @@
 #endif /* USB_NONE */
 }
 
-#ifdef HAVE_MMC
-int mmc_remove_request(void)
+#ifdef HAVE_HOTSWAP
+int hotswap_remove_request(void)
 {
     struct event ev;
     int i;
@@ -163,8 +163,8 @@
         queue_wait_w_tmo(&button_queue, &ev, HZ/2);
         switch (ev.id)
         {
-            case SYS_MMC_EXTRACTED:
-                return SYS_MMC_EXTRACTED;
+            case SYS_HOTSWAP_EXTRACTED:
+                return SYS_HOTSWAP_EXTRACTED;
 
             case SYS_USB_DISCONNECTED:
                 return SYS_USB_DISCONNECTED;
Index: apps/screens.h
===================================================================
--- apps/screens.h	(revision 13403)
+++ apps/screens.h	(working copy)
@@ -29,8 +29,8 @@
 int charging_screen(void);
 void charging_splash(void);
 
-#ifdef HAVE_MMC
-int mmc_remove_request(void);
+#ifdef HAVE_HOTSWAP
+int hotswap_remove_request(void);
 #endif
 
 #ifdef HAVE_PITCHSCREEN
Index: apps/tree.c
===================================================================
--- apps/tree.c	(revision 13403)
+++ apps/tree.c	(working copy)
@@ -41,6 +41,7 @@
 #include "status.h"
 #include "debug.h"
 #include "ata.h"
+#include "hotswap.h"
 #include "rolo.h"
 #include "icons.h"
 #include "lang.h"
@@ -744,6 +745,32 @@
 
 #ifdef HAVE_HOTSWAP
             case SYS_FS_CHANGED:
+                if (hotswap_detect())
+                {
+                    /* figure out the card number */
+                    char card_id_file[MAX_PATH];
+                    int fd;
+                    snprintf(card_id_file, MAX_PATH, "/%s/.rb_cardid", get_volume_name(1));
+                    fd = open(card_id_file, O_RDONLY);
+                    if (fd < 0)
+                    {
+                        fd = open(card_id_file, O_CREAT|O_WRONLY);
+                        if (fd >= 0)
+                        {
+                            global_status.card_count++;
+                            write(fd, &global_status.card_count, sizeof(int));
+                            close(fd);
+                            global_status.current_card = global_status.card_count;
+                        }
+                    }
+                    else
+                    {
+                        read(fd, &global_status.current_card, sizeof(int));
+                        close(fd);
+                    }
+                }
+                else global_status.current_card = -1;
+
 #ifdef HAVE_TAGCACHE
                 if (!id3db)
 #endif
Index: apps/settings.h
===================================================================
--- apps/settings.h	(revision 13403)
+++ apps/settings.h	(working copy)
@@ -301,6 +301,11 @@
 #endif
     char last_screen;
     int  viewer_icon_count;
+#ifdef HAVE_HOTSWAP
+    int current_card; /* not stored after reboot, -1 for none */
+    int card_count; /* number of cards identified already */
+#endif
+
 };
 
 struct user_settings
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c	(revision 13403)
+++ apps/settings_list.c	(working copy)
@@ -1188,6 +1188,10 @@
         "button light brightness",UNIT_INT, MIN_BRIGHTNESS_SETTING, MAX_BRIGHTNESS_SETTING, 1,
         NULL, NULL, buttonlight_set_brightness),
 #endif
+#ifdef HAVE_HOTSWAP
+    SYSTEM_SETTING(NVRAM(4), card_count, -1),
+#endif
+
 };
 
 const int nb_settings = sizeof(settings)/sizeof(*settings);
Index: apps/debug_menu.c
===================================================================
--- apps/debug_menu.c	(revision 13403)
+++ apps/debug_menu.c	(working copy)
@@ -1558,29 +1558,29 @@
 
                 strncpy(card_name, ((unsigned char*)card->cid) + 3, 6);
                 snprintf(pbuf, sizeof(pbuf), "%s Rev %d.%d", card_name,
-                         (int) mmc_extract_bits(card->cid, 72, 4),
-                         (int) mmc_extract_bits(card->cid, 76, 4));
+                         (int) hotswap_extract_bits(card->cid, 72, 4),
+                         (int) hotswap_extract_bits(card->cid, 76, 4));
                 lcd_puts(0, line++, pbuf);
                 snprintf(pbuf, sizeof(pbuf), "Prod: %d/%d",
-                         (int) mmc_extract_bits(card->cid, 112, 4),
-                         (int) mmc_extract_bits(card->cid, 116, 4) + 1997);
+                         (int) hotswap_extract_bits(card->cid, 112, 4),
+                         (int) hotswap_extract_bits(card->cid, 116, 4) + 1997);
                 lcd_puts(0, line++, pbuf);
                 snprintf(pbuf, sizeof(pbuf), "Ser#: 0x%08lx",
-                         mmc_extract_bits(card->cid, 80, 32));
+                         hotswap_extract_bits(card->cid, 80, 32));
                 lcd_puts(0, line++, pbuf);
                 snprintf(pbuf, sizeof(pbuf), "M=%02x, O=%04x",
-                         (int) mmc_extract_bits(card->cid, 0, 8),
-                         (int) mmc_extract_bits(card->cid, 8, 16));
+                         (int) hotswap_extract_bits(card->cid, 0, 8),
+                         (int) hotswap_extract_bits(card->cid, 8, 16));
                 lcd_puts(0, line++, pbuf);
-                temp = mmc_extract_bits(card->csd, 2, 4);
+                temp = hotswap_extract_bits(card->csd, 2, 4);
                 snprintf(pbuf, sizeof(pbuf), "MMC v%s", temp < 5 ?
                          spec_vers[temp] : "?.?");
                 lcd_puts(0, line++, pbuf);
                 snprintf(pbuf, sizeof(pbuf), "Blocks: 0x%06lx", card->numblocks);
                 lcd_puts(0, line++, pbuf);
                 snprintf(pbuf, sizeof(pbuf), "Blksz.: %d P:%c%c", card->blocksize,
-                         mmc_extract_bits(card->csd, 48, 1) ? 'R' : '-',
-                         mmc_extract_bits(card->csd, 106, 1) ? 'W' : '-');
+                         hotswap_extract_bits(card->csd, 48, 1) ? 'R' : '-',
+                         hotswap_extract_bits(card->csd, 106, 1) ? 'W' : '-');
                 lcd_puts(0, line++, pbuf);
             }
             else                  /* Technical details */
@@ -1600,12 +1600,12 @@
                 snprintf(pbuf, sizeof(pbuf), "R2W: *%d", card->r2w_factor);
                 lcd_puts(0, line++, pbuf);
                 snprintf(pbuf, sizeof(pbuf), "IRmax: %d..%d mA",
-                         i_vmin[mmc_extract_bits(card->csd, 66, 3)],
-                         i_vmax[mmc_extract_bits(card->csd, 69, 3)]);
+                         i_vmin[hotswap_extract_bits(card->csd, 66, 3)],
+                         i_vmax[hotswap_extract_bits(card->csd, 69, 3)]);
                 lcd_puts(0, line++, pbuf);
                 snprintf(pbuf, sizeof(pbuf), "IWmax: %d..%d mA",
-                         i_vmin[mmc_extract_bits(card->csd, 72, 3)],
-                         i_vmax[mmc_extract_bits(card->csd, 75, 3)]);
+                         i_vmin[hotswap_extract_bits(card->csd, 72, 3)],
+                         i_vmax[hotswap_extract_bits(card->csd, 75, 3)]);
                 lcd_puts(0, line++, pbuf);
             }
         }
Index: apps/main.c
===================================================================
--- apps/main.c	(revision 13403)
+++ apps/main.c	(working copy)
@@ -91,7 +91,7 @@
 #if CONFIG_TUNER
 #include "radio.h"
 #endif
-#ifdef HAVE_MMC
+#ifdef HAVE_HOTSWAP
 #include "ata_mmc.h"
 #endif
 
@@ -428,8 +428,9 @@
 #endif
         /* enter USB mode early, before trying to mount */
         if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
-#ifdef HAVE_MMC
-            if (!mmc_touched() || (mmc_remove_request() == SYS_MMC_EXTRACTED))
+#ifdef HAVE_HOTSWAP
+            if (!hotswap_touched() || 
+                (hotswap_remove_request() == SYS_HOTSWAP_EXTRACTED))
 #endif
             {
                 usb_screen();
Index: apps/misc.c
===================================================================
--- apps/misc.c	(revision 13403)
+++ apps/misc.c	(working copy)
@@ -47,8 +47,8 @@
 #include "splash.h"
 #include "tagcache.h"
 #include "scrobbler.h"
-#ifdef HAVE_MMC
-#include "ata_mmc.h"
+#ifdef HAVE_HOTSWAP
+#include "hotswap.h"
 #endif
 #include "tree.h"
 #include "eeprom_settings.h"
@@ -815,8 +815,9 @@
         case SYS_USB_CONNECTED:
             if (callback != NULL)
                 callback(parameter);
-#ifdef HAVE_MMC
-            if (!mmc_touched() || (mmc_remove_request() == SYS_MMC_EXTRACTED))
+#ifdef HAVE_HOTSWAP
+            if (!hotswap_touched() || 
+                (hotswap_remove_request() == SYS_HOTSWAP_EXTRACTED))
 #endif
             {
                 scrobbler_flush_cache();
Index: firmware/export/config.h
===================================================================
--- firmware/export/config.h	(revision 13403)
+++ firmware/export/config.h	(working copy)
@@ -243,7 +243,7 @@
 /* Enable the directory cache and tagcache in RAM if we have
  * plenty of RAM. Both features can be enabled independently. */
 #if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \
- !defined(BOOTLOADER)
+ !defined(BOOTLOADER) && !defined(SANSA_E200)
 #define HAVE_DIRCACHE
 #ifdef HAVE_TAGCACHE
 #define HAVE_TC_RAMCACHE
Index: firmware/export/hotswap.h
===================================================================
--- firmware/export/hotswap.h	(revision 0)
+++ firmware/export/hotswap.h	(revision 0)
@@ -0,0 +1,61 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: ata_mmc.h 6502 2005-05-22 00:42:00Z amiconn $
+ *
+ * Copyright (C) 2004 by Jens Arnold
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __HOTSWAP_H__
+#define __HOTSWAP_H__
+
+typedef struct
+{  
+    bool initialized;
+    unsigned char bitrate_register;
+    unsigned long read_timeout;   /* n * 8 clock cycles */
+    unsigned long write_timeout;  /* n * 8 clock cycles */
+
+    unsigned long ocr;            /* OCR register */
+    unsigned long csd[4];         /* CSD register, 16 bytes */
+    unsigned long cid[4];         /* CID register, 16 bytes */
+    unsigned long speed;          /* bit/s */
+    unsigned int nsac;            /* clock cycles */
+    unsigned long tsac;           /* n * 0.1 ns */
+    unsigned int r2w_factor;
+    unsigned long size;           /* size in bytes */
+    unsigned long numblocks;      /* size in flash blocks */
+    unsigned int blocksize;       /* block size in bytes */
+    unsigned int block_exp;       /* block size exponent */
+} tCardInfo;
+
+#ifdef TARGET_TREE
+bool hotswap_detect(void);
+tCardInfo *hostswap_card_info(int card_no);
+bool hotswap_touched(void);
+void hotswap_enable_monitoring(bool on);
+#else /* HAVE_MMC */
+#include "ata_mmc.h"
+#define hotswap_detect mmc_detect
+#define hotswap_card_info mmc_card_info
+#define hotswap_touched mmc_touched
+#define hotswap_enable_monitoring mmc_enable_monitoring
+#endif
+
+/* helper function to extract n (<=32) bits from an arbitrary position.
+   counting from MSB to LSB */
+unsigned long hotswap_extract_bits(
+        const unsigned long *p, /* the start of the bitfield array */
+        unsigned int start,     /* bit no. to start reading  */
+        unsigned int size);     /* how many bits to read */
+#endif
Index: firmware/export/config-e200.h
===================================================================
--- firmware/export/config-e200.h	(revision 13403)
+++ firmware/export/config-e200.h	(working copy)
@@ -19,6 +19,9 @@
 /* define this if you have LCD enable function */
 #define HAVE_LCD_ENABLE
 
+#define HAVE_HOTSWAP
+#define HAVE_MULTIVOLUME
+
 #define HAVE_BACKLIGHT_BRIGHTNESS
 /* Main LCD backlight brightness range and defaults */
 #define MIN_BRIGHTNESS_SETTING           1
Index: firmware/export/kernel.h
===================================================================
--- firmware/export/kernel.h	(revision 13403)
+++ firmware/export/kernel.h	(working copy)
@@ -41,8 +41,8 @@
 #define SYS_USB_DISCONNECTED      ((SYS_EVENT | ((long)3 << 27)))
 #define SYS_USB_DISCONNECTED_ACK  ((SYS_EVENT | ((long)4 << 27)))
 #define SYS_TIMEOUT               ((SYS_EVENT | ((long)5 << 27)))
-#define SYS_MMC_INSERTED          ((SYS_EVENT | ((long)6 << 27)))
-#define SYS_MMC_EXTRACTED         ((SYS_EVENT | ((long)7 << 27)))
+#define SYS_HOTSWAP_INSERTED      ((SYS_EVENT | ((long)6 << 27)))
+#define SYS_HOTSWAP_EXTRACTED     ((SYS_EVENT | ((long)7 << 27)))
 #define SYS_POWEROFF              ((SYS_EVENT | ((long)8 << 27)))
 #define SYS_FS_CHANGED            ((SYS_EVENT | ((long)9 << 27)))
 #define SYS_CHARGER_CONNECTED     ((SYS_EVENT | ((long)10 << 27)))
Index: firmware/export/ata_mmc.h
===================================================================
--- firmware/export/ata_mmc.h	(revision 13403)
+++ firmware/export/ata_mmc.h	(working copy)
@@ -18,34 +18,14 @@
  ****************************************************************************/
 #ifndef __ATA_MMC_H__
 #define __ATA_MMC_H__
+#include "hotswap.h"
 
-typedef struct
-{  
-    bool initialized;
-    unsigned char bitrate_register;
-    unsigned long read_timeout;   /* n * 8 clock cycles */
-    unsigned long write_timeout;  /* n * 8 clock cycles */
-
-    unsigned long ocr;            /* OCR register */
-    unsigned long csd[4];         /* CSD register, 16 bytes */
-    unsigned long cid[4];         /* CID register, 16 bytes */
-    unsigned long speed;          /* bit/s */
-    unsigned int nsac;            /* clock cycles */
-    unsigned long tsac;           /* n * 0.1 ns */
-    unsigned int r2w_factor;
-    unsigned long size;           /* size in bytes */
-    unsigned long numblocks;      /* size in flash blocks */
-    unsigned int blocksize;       /* block size in bytes */
-    unsigned int block_exp;       /* block size exponent */
-} tCardInfo;
-
 void mmc_enable_int_flash_clock(bool on);
 bool mmc_detect(void);
-unsigned long mmc_extract_bits(const unsigned long *p, unsigned int start,
-                               unsigned int size);
 tCardInfo *mmc_card_info(int card_no);
 bool mmc_touched(void);
 bool mmc_usb_active(int delayticks);
+
 #ifdef HAVE_HOTSWAP
 void mmc_enable_monitoring(bool on);
 #endif
Index: firmware/SOURCES
===================================================================
--- firmware/SOURCES	(revision 13403)
+++ firmware/SOURCES	(working copy)
@@ -113,6 +113,9 @@
 #endif /* HAVE_FLASH_DISK */
 #endif /* HAVE_MMC */
 drivers/fat.c
+#ifdef HAVE_HOTSWAP
+hotswap.c
+#endif
 #endif /* SIMULATOR */
 
 /* EEPROM */
Index: firmware/include/dir.h
===================================================================
--- firmware/include/dir.h	(revision 13403)
+++ firmware/include/dir.h	(working copy)
@@ -71,6 +71,10 @@
 #endif
 } DIR;
 
+#ifdef HAVE_HOTSWAP
+char *get_volume_name(int volume);
+#endif
+
 #ifndef DIRFUNCTIONS_DEFINED
 
 extern DIR* opendir(const char* name);
Index: firmware/target/arm/sandisk/sansa-e200/ata-e200.c
===================================================================
--- firmware/target/arm/sandisk/sansa-e200/ata-e200.c	(revision 13403)
+++ firmware/target/arm/sandisk/sansa-e200/ata-e200.c	(working copy)
@@ -17,11 +17,13 @@
  *
  ****************************************************************************/
 #include "ata.h"
+#include "hotswap.h"
 #include "ata-target.h"
 #include "ata_idle_notify.h"
 #include "system.h"
 #include <string.h>
 #include "thread.h"
+#include "disk.h"
 #include "pp5024.h"
 
 #define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */
@@ -112,7 +114,15 @@
 static const char sd_thread_name[] = "sd";
 static struct event_queue sd_queue;
 
+static int       sd_countdown;  /* for sd switch debouncing */
+static bool      sd_monitor_enabled = true;
+static int       last_sd_status     = 0;
+static tCardInfo card;
+static enum {SD_UNKNOWN, SD_UNTOUCHED, SD_TOUCHED} sd_status = SD_UNKNOWN;
 
+static void sd_tick(void);
+
+
 /* Private Functions */
 
 bool sd_send_command(unsigned int cmd, unsigned long arg1, unsigned int arg2)
@@ -311,7 +321,7 @@
     }
 }
 
-void sd_init_device(void)
+void sd_init_device(int card_no)
 {
 /* SD Protocol registers */
     unsigned int dummy;
@@ -324,8 +334,10 @@
 
     unsigned char carddata[512];
     unsigned char *dataptr;
-    tSDCardInfo *card = &card_info[0]; /* Init onboard flash only */
+    tSDCardInfo *card = &card_info[card_no];
 
+    current_card = card_no;
+
 /* Initialise card data as blank */
     card->initialized = false;
     card->ocr = 0;
@@ -351,15 +363,34 @@
     outl(inl(0x70000080) | 0x4, 0x70000080);
     outl(inl(0x70000084) | 0x4, 0x70000084);
     REG_1 = 6;
-    outl(inl(0x70000014) & ~(0x3ffff), 0x70000014);
-    outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014);
     outl(0x1010, 0x70000034);
 
-    GPIOA_ENABLE |= (1 << 7);
-    GPIOA_OUTPUT_EN &= ~(1 << 7);
-    GPIOD_ENABLE |= (0x1f);
-    GPIOD_OUTPUT_EN |= (0x1f);
-    GPIOD_OUTPUT_VAL |= (0x1f);
+    GPIOA_ENABLE     |=  (1 << 7);
+    GPIOA_OUTPUT_EN  &= ~(1 << 7);
+
+    if(card_no == 0)
+    {
+        GPIOA_ENABLE    &= ~0x7a;
+        GPIOA_OUTPUT_EN &= ~0x7a;
+
+        GPIOD_ENABLE     |= (0x1f);
+        GPIOD_OUTPUT_EN  |= (0x1f);
+
+        outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014);
+    }
+    else
+    {
+        outl(inl(0x70000080) & ~0x4, 0x70000080);
+
+        GPIOA_ENABLE    |= 0x7a;
+        GPIOA_OUTPUT_EN |= 0x7a;
+
+        GPIOD_ENABLE     = 0x40;
+        GPIOD_OUTPUT_EN  = 0x40;
+
+        outl(inl(0x70000014) & ~(0x3ffff), 0x70000014);
+    }
+
     DEV_EN |= DEV_ATA; /* Enable controller */
     DEV_RS |= DEV_ATA; /* Reset controller */
     DEV_RS &=~DEV_ATA; /* Clear Reset */
@@ -378,15 +409,28 @@
     REG_5 = 0xf;
 
     sd_send_command(GO_IDLE_STATE, 0, 256);
+    int timeout_tick = current_tick + READ_TIMEOUT;
     while ((card->ocr & (1 << 31)) == 0) /* Loop until the card is powered up */
     {
         sd_send_acommand(SD_APP_OP_COND, 0x100000, 3);
         sd_read_response(&(card->ocr), 3);
 
+        if (TIME_AFTER(timeout_tick, current_tick))
+        {
+            /* timed out */
+            return;
+        }
         if (card->ocr == 0)
         {
-            /* TODO: Handle failure */
-            while (1) {};
+            while (1) 
+            {
+                /* TODO: Handle failure */
+                if (TIME_AFTER(timeout_tick, current_tick))
+                {
+                    /* timed out */
+                    return;
+                }
+            }
         }
     }
 
@@ -444,7 +488,7 @@
             dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */
         }
     }
-    mutex_init(&sd_mtx);
+    card->initialized = true;
 }
 
 /* API Functions */
@@ -467,21 +511,32 @@
     unsigned int dummy;
     unsigned int response;
     unsigned int i;
-    tSDCardInfo *card = &card_info[current_card];
-
+    tSDCardInfo *card;
+    
     /* TODO: Add DMA support. */
 
-#ifdef HAVE_MULTIVOLUME
-    (void)drive; /* unused for now */
-#endif
     mutex_lock(&sd_mtx);
 
+    ata_enable(true);
+    ata_led(true);
+
+    if(drive && (GPIOA_INPUT_VAL & 0x80)) /* no external sd-card inserted */
+    {
+        ret = -9;
+        goto error;
+    }
+
+    if(drive != current_card)
+    {
+        current_card = drive;
+        sd_init_device(drive);
+    }
+
+    card = &card_info[current_card];
+
     last_disk_activity = current_tick;
     spinup_start = current_tick;
 
-    ata_enable(true);
-    ata_led(true);
-
     timeout = current_tick + READ_TIMEOUT;
 
     /* TODO: Select device */
@@ -529,6 +584,9 @@
         sd_wait_for_state(card, TRAN);
         break;
     }
+
+  error:
+
     ata_led(false);
     ata_enable(false);
 
@@ -551,11 +609,27 @@
     int ret = 0;
     unsigned int i;
     long timeout;
-    tSDCardInfo *card = &card_info[current_card];
+    tSDCardInfo *card;
 
     mutex_lock(&sd_mtx);
+
     ata_enable(true);
     ata_led(true);
+
+    if(drive && (GPIOA_INPUT_VAL & 0x80)) /* no external sd-card inserted */
+    {
+        ret = -9;
+        goto error;
+    }
+
+    if(drive != current_card)
+    {
+        current_card = drive;
+        sd_init_device(drive);
+    }
+
+    card = &card_info[current_card];
+
     if(current_card == 0)
     {
         if(start < BLOCKS_PER_BANK)
@@ -607,6 +681,9 @@
     sd_read_response(&response, 1);
 
     sd_wait_for_state(card, TRAN);
+
+  error:
+
     ata_led(false);
     ata_enable(false);
     mutex_unlock(&sd_mtx);
@@ -623,6 +700,16 @@
         queue_wait_w_tmo(&sd_queue, &ev, HZ);
         switch ( ev.id ) 
         {
+            case SYS_HOTSWAP_INSERTED:
+                disk_mount(1); /* mount SD-CARD */
+                queue_broadcast(SYS_FS_CHANGED, 0);
+                break;
+
+            case SYS_HOTSWAP_EXTRACTED:
+                disk_unmount(1); /* release "by force" */
+                queue_broadcast(SYS_FS_CHANGED, 0);
+                break;
+
             default:
                 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
                 {
@@ -690,15 +777,112 @@
 
 int ata_init(void)
 {
-    sd_init_device();
+    mutex_init(&sd_mtx);
+    sd_init_device(0);
     if ( !initialized ) 
     {
         queue_init(&sd_queue, true);
         create_thread(sd_thread, sd_stack,
                       sizeof(sd_stack), sd_thread_name IF_PRIO(, PRIORITY_SYSTEM)
-		      IF_COP(, CPU, false));
+                      IF_COP(, CPU, false));
+        tick_add_task(sd_tick);
         initialized = true;
     }
 
     return 0;
 }
+
+/* move the sd-card info to mmc struct */
+tCardInfo *hotswap_card_info_target(int card_no)
+{
+    int temp;
+    static const char mantissa[] = {  /* *10 */
+        0,  10, 12, 13, 15, 20, 25, 30,
+        35, 40, 45, 50, 55, 60, 70, 80
+    };
+    static const int exponent[] = {  /* use varies */
+        1, 10, 100, 1000, 10000, 100000, 1000000,
+        10000000, 100000000, 1000000000 };
+
+    card.initialized = card_info[card_no].initialized;
+    card.ocr         = card_info[card_no].ocr;
+    memcpy(card.csd,   card_info[card_no].csd, sizeof(card.csd));
+    memcpy(card.cid,   card_info[card_no].cid, sizeof(card.cid));
+    card.numblocks   = card_info[card_no].numblocks;
+    card.blocksize   = card_info[card_no].block_size;
+    card.size        = card_info[card_no].capacity < 0xffffffff ?
+                       card_info[card_no].capacity : 0xffffffff;
+    card.block_exp   = card_info[card_no].block_exp;
+    temp             = hotswap_extract_bits(card.csd, 29, 3);
+    card.speed       = mantissa[hotswap_extract_bits(card.csd, 25, 4)]
+                     * exponent[temp > 2 ? 7 : temp + 4];
+    card.nsac        = 100 * hotswap_extract_bits(card.csd, 16, 8);
+    temp             = hotswap_extract_bits(card.csd, 13, 3);
+    card.tsac        = mantissa[hotswap_extract_bits(card.csd, 9, 4)]
+                     * exponent[temp] / 10;
+
+    return &card;
+}
+
+bool hotswap_touched_target(void)
+{
+    if (sd_status == SD_UNKNOWN) /* try to detect */
+    {
+        if(~GPIOA_INPUT_VAL & 0x80)
+        {
+            mutex_lock(&sd_mtx);
+            sd_init_device(1);
+            sd_status = SD_TOUCHED;
+            mutex_unlock(&sd_mtx);
+        }
+    }
+
+    return sd_status == SD_TOUCHED;
+}
+
+bool hotswap_detect_target(void)
+{
+    return GPIOA_INPUT_VAL & 0x80 ? false : true;
+}
+
+void hotswap_enable_monitoring_target(bool on)
+{
+    sd_monitor_enabled = on;
+}
+
+static void sd_tick(void)
+{
+    int current_status;
+
+    if (sd_monitor_enabled)
+    {
+        /* 0x80:inserted, 0x00:not inserted */
+        current_status = ~GPIOA_INPUT_VAL & 0x80;
+        /* Only report when the status has changed */
+        if (current_status != last_sd_status)
+        {
+            last_sd_status = current_status;
+            sd_countdown = 30;
+        }
+        else
+        {
+            /* Count down until it gets negative */
+            if (sd_countdown >= 0)
+                sd_countdown--;
+
+            if (sd_countdown == 0)
+            {
+                if (current_status)
+                {
+                    queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
+                }
+                else
+                {
+                    queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
+                    sd_status = SD_UNKNOWN;
+                    card_info[1].initialized = false;
+                }
+            }
+        }
+    }
+}
Index: firmware/common/disk.c
===================================================================
--- firmware/common/disk.c	(revision 13403)
+++ firmware/common/disk.c	(working copy)
@@ -20,8 +20,8 @@
 #include "ata.h"
 #include "debug.h"
 #include "fat.h"
-#ifdef HAVE_MMC
-#include "ata_mmc.h"
+#ifdef HAVE_HOTSWAP
+#include "hotswap.h"
 #endif
 #include "file.h" /* for release_dirs() */
 #include "dir.h" /* for release_files() */
@@ -101,8 +101,8 @@
     int mounted;
     int i;
     
-#if defined(HAVE_MMC) && defined(HAVE_HOTSWAP)
-    mmc_enable_monitoring(false);
+#ifdef HAVE_HOTSWAP
+    hotswap_enable_monitoring(false);
 #endif
 
     fat_init(); /* reset all mounted partitions */
@@ -110,15 +110,13 @@
         vol_drive[i] = -1; /* mark all as unassigned */
 
     mounted = disk_mount(0);
-#ifdef HAVE_MMC
-    if (mmc_detect()) /* for Ondio, only if card detected */
+#ifdef HAVE_HOTSWAP
+    if (hotswap_detect())
     {
         mounted += disk_mount(1); /* try 2nd "drive", too */
     }
-#ifdef HAVE_HOTSWAP
-    mmc_enable_monitoring(true);
+    hotswap_enable_monitoring(true);
 #endif
-#endif
 
     return mounted;
 }
Index: firmware/common/dir.c
===================================================================
--- firmware/common/dir.c	(revision 13403)
+++ firmware/common/dir.c	(working copy)
@@ -37,11 +37,23 @@
 #ifdef HAVE_MMC
 static const char* vol_names = "<MMC%d>";
 #define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */
+#elif defined(SANSA_E200)
+static const char* vol_names = "<microSD%d>";
+#define VOL_ENUM_POS 8
 #else
 static const char* vol_names = "<HD%d>";
 #define VOL_ENUM_POS 3
 #endif
 
+#ifdef HAVE_HOTSWAP
+char *get_volume_name(int volume)
+{
+    static char buffer[16]; /* larger than the longets vol_names above */
+    /* requires vol_names to have a %d for the volume id */
+    snprintf(buffer, 16, vol_names, volume);
+    return buffer;
+}
+#endif
 /* returns on which volume this is, and copies the reduced name
    (sortof a preprocessor for volume-decorated pathnames) */
 static int strip_volume(const char* name, char* namecopy)
Index: firmware/hotswap.c
===================================================================
--- firmware/hotswap.c	(revision 0)
+++ firmware/hotswap.c	(revision 0)
@@ -0,0 +1,69 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: ata_mmc.h 6502 2005-05-22 00:42:00Z amiconn $
+ *
+ * Copyright (C) 2004 by Jens Arnold
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <stdbool.h>
+#include "config.h"
+#ifdef TARGET_TREE
+#include "hotswap-target.h"
+#else
+#include "ata_mmc.h"
+#endif
+
+/* helper function to extract n (<=32) bits from an arbitrary position.
+   counting from MSB to LSB */
+unsigned long hotswap_extract_bits(
+    const unsigned long *p, /* the start of the bitfield array */
+    unsigned int start,     /* bit no. to start reading  */
+    unsigned int size)      /* how many bits to read */
+{
+    unsigned int long_index = start / 32;
+    unsigned int bit_index = start % 32;
+    unsigned long result;
+    
+    result = p[long_index] << bit_index;
+
+    if (bit_index + size > 32)    /* crossing longword boundary */
+        result |= p[long_index+1] >> (32 - bit_index);
+        
+    result >>= 32 - size;
+
+    return result;
+}
+#ifdef TARGET_TREE
+
+bool hotswap_detect(void)
+{
+    return hotswap_detect_target();
+}
+
+tCardInfo *hotswap_card_info(int card_no)
+{
+    return hotswap_card_info_target(card_no);
+}
+
+bool hotswap_touched(void)
+{
+    return hotswap_touched_target();
+}
+void hotswap_enable_monitoring(bool on)
+{
+    hotswap_enable_monitoring_target(on);
+}
+#endif
+
+
Index: firmware/usb.c
===================================================================
--- firmware/usb.c	(revision 13403)
+++ firmware/usb.c	(working copy)
@@ -255,8 +255,8 @@
                 break;
 
 #ifdef HAVE_MMC
-            case SYS_MMC_INSERTED:
-            case SYS_MMC_EXTRACTED:
+            case SYS_HOTSWAP_INSERTED:
+            case SYS_HOTSWAP_EXTRACTED:
                 if(usb_state == USB_INSERTED)
                 {
                     usb_enable(false);
Index: firmware/drivers/ata_mmc.c
===================================================================
--- firmware/drivers/ata_mmc.c	(revision 13403)
+++ firmware/drivers/ata_mmc.c	(working copy)
@@ -397,27 +397,7 @@
     return 0;
 }
 
-/* helper function to extract n (<=32) bits from an arbitrary position.
-   counting from MSB to LSB */
-unsigned long mmc_extract_bits(
-    const unsigned long *p, /* the start of the bitfield array */
-    unsigned int start,     /* bit no. to start reading  */
-    unsigned int size)      /* how many bits to read */
-{
-    unsigned int long_index = start / 32;
-    unsigned int bit_index = start % 32;
-    unsigned long result;
-    
-    result = p[long_index] << bit_index;
 
-    if (bit_index + size > 32)    /* crossing longword boundary */
-        result |= p[long_index+1] >> (32 - bit_index);
-        
-    result >>= 32 - size;
-
-    return result;
-}
-
 static int initialize_card(int card_no)
 {
     int rc, i, temp;
@@ -470,9 +450,9 @@
         return rc * 10 - 6;
 
     /* check block sizes */
-    card->block_exp = mmc_extract_bits(card->csd, 44, 4);
+    card->block_exp = hotswap_extract_bits(card->csd, 44, 4);
     card->blocksize = 1 << card->block_exp;
-    if ((mmc_extract_bits(card->csd, 102, 4) != card->block_exp)
+    if ((hotswap_extract_bits(card->csd, 102, 4) != card->block_exp)
         || card->blocksize > MAX_BLOCK_SIZE)
     {
         return -7;
@@ -486,16 +466,16 @@
     }
 
     /* max transmission speed, clock divider */
-    temp = mmc_extract_bits(card->csd, 29, 3);
+    temp = hotswap_extract_bits(card->csd, 29, 3);
     temp = (temp > 3) ? 3 : temp;
-    card->speed = mantissa[mmc_extract_bits(card->csd, 25, 4)]
+    card->speed = mantissa[hotswap_extract_bits(card->csd, 25, 4)]
                 * exponent[temp + 4];
     card->bitrate_register = (FREQ/4-1) / card->speed;
 
     /* NSAC, TSAC, read timeout */
-    card->nsac = 100 * mmc_extract_bits(card->csd, 16, 8);
-    card->tsac = mantissa[mmc_extract_bits(card->csd, 9, 4)];
-    temp = mmc_extract_bits(card->csd, 13, 3);
+    card->nsac = 100 * hotswap_extract_bits(card->csd, 16, 8);
+    card->tsac = mantissa[hotswap_extract_bits(card->csd, 9, 4)];
+    temp = hotswap_extract_bits(card->csd, 13, 3);
     card->read_timeout = ((FREQ/4) / (card->bitrate_register + 1)
                          * card->tsac / exponent[9 - temp]
                          + (10 * card->nsac));
@@ -503,7 +483,7 @@
     card->tsac = card->tsac * exponent[temp] / 10;
 
     /* r2w_factor, write timeout */
-    card->r2w_factor = 1 << mmc_extract_bits(card->csd, 99, 3);
+    card->r2w_factor = 1 << hotswap_extract_bits(card->csd, 99, 3);
     if (card->r2w_factor > 32)    /* dirty MMC spec violation */
     {
         card->read_timeout *= 4;  /* add safety factor */
@@ -513,8 +493,8 @@
         card->write_timeout = card->read_timeout * card->r2w_factor;
 
     /* card size */
-    card->numblocks = (mmc_extract_bits(card->csd, 54, 12) + 1)
-                      * (1 << (mmc_extract_bits(card->csd, 78, 3) + 2));
+    card->numblocks = (hotswap_extract_bits(card->csd, 54, 12) + 1)
+            * (1 << (hotswap_extract_bits(card->csd, 78, 3) + 2));
     card->size = card->numblocks * card->blocksize;
 
     /* switch to full speed */
@@ -993,12 +973,12 @@
                 break;
 
 #ifdef HAVE_HOTSWAP
-            case SYS_MMC_INSERTED:
+            case SYS_HOTSWAP_INSERTED:
                 disk_mount(1); /* mount MMC */
                 queue_broadcast(SYS_FS_CHANGED, 0);
                 break;
 
-            case SYS_MMC_EXTRACTED:
+            case SYS_HOTSWAP_EXTRACTED:
                 disk_unmount(1); /* release "by force" */
                 queue_broadcast(SYS_FS_CHANGED, 0);
                 break;
@@ -1097,11 +1077,11 @@
             {
                 if (current_status)
                 {
-                    queue_broadcast(SYS_MMC_INSERTED, 0);
+                    queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
                 }
                 else
                 {
-                    queue_broadcast(SYS_MMC_EXTRACTED, 0);
+                    queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
                     mmc_status = MMC_UNTOUCHED;
                     card_info[1].initialized = false;
                 }
