diff -Naur rockbox/apps/debug_menu.c rockbox-new/apps/debug_menu.c --- rockbox/apps/debug_menu.c 2007-05-14 19:55:19.000000000 -0400 +++ rockbox-new/apps/debug_menu.c 2007-05-28 21:43:55.000000000 -0400 @@ -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); } } diff -Naur rockbox/apps/main.c rockbox-new/apps/main.c --- rockbox/apps/main.c 2007-05-17 13:42:29.000000000 -0400 +++ rockbox-new/apps/main.c 2007-05-28 21:43:55.000000000 -0400 @@ -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(); diff -Naur rockbox/apps/misc.c rockbox-new/apps/misc.c --- rockbox/apps/misc.c 2007-04-12 15:52:53.000000000 -0400 +++ rockbox-new/apps/misc.c 2007-05-28 21:43:55.000000000 -0400 @@ -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(); diff -Naur rockbox/apps/screens.c rockbox-new/apps/screens.c --- rockbox/apps/screens.c 2007-05-02 17:08:59.000000000 -0400 +++ rockbox-new/apps/screens.c 2007-05-28 21:43:55.000000000 -0400 @@ -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; diff -Naur rockbox/apps/screens.h rockbox-new/apps/screens.h --- rockbox/apps/screens.h 2007-03-26 20:57:26.000000000 -0400 +++ rockbox-new/apps/screens.h 2007-05-28 21:43:55.000000000 -0400 @@ -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 diff -Naur rockbox/apps/settings.h rockbox-new/apps/settings.h --- rockbox/apps/settings.h 2007-05-27 12:59:31.000000000 -0400 +++ rockbox-new/apps/settings.h 2007-05-28 21:43:55.000000000 -0400 @@ -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 diff -Naur rockbox/apps/settings_list.c rockbox-new/apps/settings_list.c --- rockbox/apps/settings_list.c 2007-05-27 12:59:31.000000000 -0400 +++ rockbox-new/apps/settings_list.c 2007-05-28 21:45:18.000000000 -0400 @@ -1208,6 +1208,11 @@ INT_SETTING(0, list_accel_wait, LANG_LISTACCEL_ACCEL_SPEED, 3, "list_accel_wait", UNIT_SEC, 1, 10, 1, scanaccel_formatter, scanaccel_getlang, NULL), + +#ifdef HAVE_HOTSWAP + SYSTEM_SETTING(NVRAM(4), card_count, -1), +#endif + }; const int nb_settings = sizeof(settings)/sizeof(*settings); diff -Naur rockbox/apps/tree.c rockbox-new/apps/tree.c --- rockbox/apps/tree.c 2007-05-20 21:15:05.000000000 -0400 +++ rockbox-new/apps/tree.c 2007-05-28 21:43:55.000000000 -0400 @@ -40,6 +40,7 @@ #include "status.h" #include "debug.h" #include "ata.h" +#include "hotswap.h" #include "rolo.h" #include "icons.h" #include "lang.h" @@ -743,6 +744,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 diff -Naur rockbox/firmware/SOURCES rockbox-new/firmware/SOURCES --- rockbox/firmware/SOURCES 2007-05-22 15:46:12.000000000 -0400 +++ rockbox-new/firmware/SOURCES 2007-05-28 21:43:55.000000000 -0400 @@ -113,6 +113,9 @@ #endif /* HAVE_FLASH_DISK */ #endif /* HAVE_MMC */ drivers/fat.c +#ifdef HAVE_HOTSWAP +hotswap.c +#endif #endif /* SIMULATOR */ /* EEPROM */ diff -Naur rockbox/firmware/common/dir.c rockbox-new/firmware/common/dir.c --- rockbox/firmware/common/dir.c 2007-03-26 12:43:22.000000000 -0400 +++ rockbox-new/firmware/common/dir.c 2007-05-28 21:43:55.000000000 -0400 @@ -37,11 +37,23 @@ #ifdef HAVE_MMC static const char* vol_names = ""; #define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */ +#elif defined(SANSA_E200) +static const char* vol_names = ""; +#define VOL_ENUM_POS 8 #else static const char* vol_names = ""; #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) diff -Naur rockbox/firmware/common/disk.c rockbox-new/firmware/common/disk.c --- rockbox/firmware/common/disk.c 2007-05-23 15:56:24.000000000 -0400 +++ rockbox-new/firmware/common/disk.c 2007-05-28 21:43:55.000000000 -0400 @@ -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,14 +110,12 @@ 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); -#endif + hotswap_enable_monitoring(true); #endif return mounted; diff -Naur rockbox/firmware/drivers/ata_mmc.c rockbox-new/firmware/drivers/ata_mmc.c --- rockbox/firmware/drivers/ata_mmc.c 2007-04-11 21:30:05.000000000 -0400 +++ rockbox-new/firmware/drivers/ata_mmc.c 2007-05-28 21:43:55.000000000 -0400 @@ -397,26 +397,6 @@ 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) { @@ -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; } diff -Naur rockbox/firmware/export/ata_mmc.h rockbox-new/firmware/export/ata_mmc.h --- rockbox/firmware/export/ata_mmc.h 2007-03-26 12:42:42.000000000 -0400 +++ rockbox-new/firmware/export/ata_mmc.h 2007-05-28 21:43:55.000000000 -0400 @@ -18,34 +18,14 @@ ****************************************************************************/ #ifndef __ATA_MMC_H__ #define __ATA_MMC_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; +#include "hotswap.h" 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 diff -Naur rockbox/firmware/export/config-e200.h rockbox-new/firmware/export/config-e200.h --- rockbox/firmware/export/config-e200.h 2007-05-28 16:06:17.000000000 -0400 +++ rockbox-new/firmware/export/config-e200.h 2007-05-28 21:43:55.000000000 -0400 @@ -22,6 +22,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 diff -Naur rockbox/firmware/export/config.h rockbox-new/firmware/export/config.h --- rockbox/firmware/export/config.h 2007-05-22 15:46:10.000000000 -0400 +++ rockbox-new/firmware/export/config.h 2007-05-28 21:43:55.000000000 -0400 @@ -246,7 +246,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 diff -Naur rockbox/firmware/export/hotswap.h rockbox-new/firmware/export/hotswap.h --- rockbox/firmware/export/hotswap.h 1969-12-31 19:00:00.000000000 -0500 +++ rockbox-new/firmware/export/hotswap.h 2007-05-28 21:43:55.000000000 -0400 @@ -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 diff -Naur rockbox/firmware/export/kernel.h rockbox-new/firmware/export/kernel.h --- rockbox/firmware/export/kernel.h 2007-03-26 15:09:35.000000000 -0400 +++ rockbox-new/firmware/export/kernel.h 2007-05-28 21:43:55.000000000 -0400 @@ -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))) diff -Naur rockbox/firmware/hotswap.c rockbox-new/firmware/hotswap.c --- rockbox/firmware/hotswap.c 1969-12-31 19:00:00.000000000 -0500 +++ rockbox-new/firmware/hotswap.c 2007-05-28 21:43:55.000000000 -0400 @@ -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 +#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 + + diff -Naur rockbox/firmware/include/dir.h rockbox-new/firmware/include/dir.h --- rockbox/firmware/include/dir.h 2007-03-26 12:42:48.000000000 -0400 +++ rockbox-new/firmware/include/dir.h 2007-05-28 21:43:55.000000000 -0400 @@ -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); diff -Naur rockbox/firmware/target/arm/sandisk/sansa-e200/ata-e200.c rockbox-new/firmware/target/arm/sandisk/sansa-e200/ata-e200.c --- rockbox/firmware/target/arm/sandisk/sansa-e200/ata-e200.c 2007-04-23 19:45:01.000000000 -0400 +++ rockbox-new/firmware/target/arm/sandisk/sansa-e200/ata-e200.c 2007-05-28 19:12:29.000000000 -0400 @@ -17,11 +17,13 @@ * ****************************************************************************/ #include "ata.h" +#include "hotswap.h" #include "ata-target.h" #include "ata_idle_notify.h" #include "system.h" #include #include "thread.h" +#include "disk.h" #include "pp5024.h" #define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */ @@ -107,11 +109,19 @@ static struct mutex sd_mtx; -static long sd_stack [(DEFAULT_STACK_SIZE*2)/sizeof(long)]; +static long sd_stack [((DEFAULT_STACK_SIZE*2) + 0x800)/sizeof(long)]; 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 */ @@ -311,7 +321,7 @@ } } -void sd_init_device(void) +void sd_init_device(int card_no) { /* SD Protocol registers */ unsigned int dummy; @@ -324,7 +334,9 @@ 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; @@ -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(current_tick, timeout_tick)) + { + /* timed out */ + return; + } if (card->ocr == 0) { - /* TODO: Handle failure */ - while (1) {}; + while (1) + { + /* TODO: Handle failure */ + if (TIME_AFTER(current_tick, timeout_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,37 @@ 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); - last_disk_activity = current_tick; - spinup_start = current_tick; - 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) || !card_info[drive].initialized) + { + current_card = drive; + sd_init_device(drive); + } + + card = &card_info[current_card]; + if (!card->initialized) + { + ret = -9; + goto error; + } + + last_disk_activity = current_tick; + spinup_start = current_tick; + timeout = current_tick + READ_TIMEOUT; /* TODO: Select device */ @@ -529,6 +589,9 @@ sd_wait_for_state(card, TRAN); break; } + + error: + ata_led(false); ata_enable(false); @@ -551,11 +614,35 @@ 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) || !card_info[drive].initialized) + { + current_card = drive; + sd_init_device(drive); + } + + card = &card_info[current_card]; + if (!card->initialized) + { + ret = -9; + goto error; + } + + + card = &card_info[current_card]; + if(current_card == 0) { if(start < BLOCKS_PER_BANK) @@ -607,6 +694,9 @@ sd_read_response(&response, 1); sd_wait_for_state(card, TRAN); + + error: + ata_led(false); ata_enable(false); mutex_unlock(&sd_mtx); @@ -616,6 +706,7 @@ static void sd_thread(void) { + int retry; struct event ev; bool idle_notified = false; @@ -623,6 +714,23 @@ queue_wait_w_tmo(&sd_queue, &ev, HZ); switch ( ev.id ) { + case SYS_HOTSWAP_INSERTED: + for (retry = 3; retry > 0; retry--) + { + if (disk_mount(1)) /* mount SD-CARD */ + { + queue_broadcast(SYS_FS_CHANGED, 0); + break; + } + yield(); + } + 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 +798,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; + } + } + } + } +} diff -Naur rockbox/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h rockbox-new/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h --- rockbox/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h 1969-12-31 19:00:00.000000000 -0500 +++ rockbox-new/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h 2007-05-28 21:43:55.000000000 -0400 @@ -0,0 +1,31 @@ +/*************************************************************************** + * __________ __ ___. + * 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_TARGET_H__ +#define __HOTSWAP_TARGET_H__ + +#include "config.h" +#include "hotswap.h" + +bool hotswap_detect_target(void); +tCardInfo *hotswap_card_info_target(int card_no); +bool hotswap_touched_target(void); +void hotswap_enable_monitoring_target(bool on); + + +#endif /* __HOTSWAP_TARGET_H__ */ \ No newline at end of file diff -Naur rockbox/firmware/usb.c rockbox-new/firmware/usb.c --- rockbox/firmware/usb.c 2007-04-11 21:30:06.000000000 -0400 +++ rockbox-new/firmware/usb.c 2007-05-28 21:43:55.000000000 -0400 @@ -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);