diff --strip-trailing-cr -u -r rockbox/trunk/apps/debug_menu.c rockbox-daily-20070528/apps/debug_menu.c --- rockbox/trunk/apps/debug_menu.c 2007-05-18 12:09:05.000000000 +0300 +++ rockbox-daily-20070528/apps/debug_menu.c 2007-05-29 23:38:25.000000000 +0300 @@ -59,7 +59,7 @@ #include "fat.h" #include "mas.h" #include "eeprom_24cxx.h" -#ifdef HAVE_MMC +#if defined(HAVE_MMC) || defined(HAVE_HOTSWAP) #include "ata_mmc.h" #endif #if CONFIG_TUNER @@ -1518,8 +1518,8 @@ #endif #ifndef SIMULATOR -#ifdef HAVE_MMC -static bool dbg_mmc_info(void) +#if defined(HAVE_MMC) || defined(HAVE_HOTSWAP) +static bool dbg_card_info(void) { bool done = false; int currval = 0; @@ -1542,7 +1542,7 @@ while (!done) { - card = mmc_card_info(currval / 2); + card = card_get_info(currval / 2); line = 0; lcd_clear_display(); @@ -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) card_extract_bits(card->cid, 72, 4), + (int) card_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) card_extract_bits(card->cid, 112, 4), + (int) card_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)); + card_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) card_extract_bits(card->cid, 0, 8), + (int) card_extract_bits(card->cid, 8, 16)); lcd_puts(0, line++, pbuf); - temp = mmc_extract_bits(card->csd, 2, 4); + temp = card_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' : '-'); + card_extract_bits(card->csd, 48, 1) ? 'R' : '-', + card_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[card_extract_bits(card->csd, 66, 3)], + i_vmax[card_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[card_extract_bits(card->csd, 72, 3)], + i_vmax[card_extract_bits(card->csd, 75, 3)]); lcd_puts(0, line++, pbuf); } } @@ -1636,7 +1636,7 @@ action_signalscreenchange(); return false; } -#else /* !HAVE_MMC */ +#else /* !defined(HAVE_MMC) && !defined(HAVE_HOTSWAP) */ static bool dbg_disk_info(void) { char buf[128]; @@ -1793,7 +1793,7 @@ action_signalscreenchange(); return false; } -#endif /* !HAVE_MMC */ +#endif /* !defined(HAVE_MMC) && !defined(HAVE_HOTSWAP) */ #endif /* !SIMULATOR */ #ifdef HAVE_DIRCACHE @@ -2240,8 +2240,10 @@ { "View partitions", dbg_partitions }, #endif #ifndef SIMULATOR -#ifdef HAVE_MMC - { "View MMC info", dbg_mmc_info }, +#if defined(HAVE_MMC) + { "View MMC info", dbg_card_info }, +#elif defined(HAVE_HOTSWAP) + { "View microSD info", dbg_card_info }, #else { "View disk info", dbg_disk_info }, #endif diff --strip-trailing-cr -u -r rockbox/trunk/apps/main.c rockbox-daily-20070528/apps/main.c --- rockbox/trunk/apps/main.c 2007-05-18 12:09:05.000000000 +0300 +++ rockbox-daily-20070528/apps/main.c 2007-05-29 23:27:23.000000000 +0300 @@ -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 (!card_touched() || + (card_remove_request() == SYS_CARD_EXTRACTED)) #endif { usb_screen(); diff --strip-trailing-cr -u -r rockbox/trunk/apps/misc.c rockbox-daily-20070528/apps/misc.c --- rockbox/trunk/apps/misc.c 2007-05-04 12:35:53.000000000 +0300 +++ rockbox-daily-20070528/apps/misc.c 2007-05-29 23:27:23.000000000 +0300 @@ -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 (!card_touched() || + (card_remove_request() == SYS_CARD_EXTRACTED)) #endif { scrobbler_flush_cache(); diff --strip-trailing-cr -u -r rockbox/trunk/apps/screens.c rockbox-daily-20070528/apps/screens.c --- rockbox/trunk/apps/screens.c 2007-05-04 12:35:52.000000000 +0300 +++ rockbox-daily-20070528/apps/screens.c 2007-05-29 23:27:23.000000000 +0300 @@ -147,8 +147,8 @@ #endif /* USB_NONE */ } -#ifdef HAVE_MMC -int mmc_remove_request(void) +#ifdef HAVE_HOTSWAP +int card_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_CARD_EXTRACTED: + return SYS_CARD_EXTRACTED; case SYS_USB_DISCONNECTED: return SYS_USB_DISCONNECTED; diff --strip-trailing-cr -u -r rockbox/trunk/apps/screens.h rockbox-daily-20070528/apps/screens.h --- rockbox/trunk/apps/screens.h 2007-05-04 12:35:52.000000000 +0300 +++ rockbox-daily-20070528/apps/screens.h 2007-05-29 23:27:23.000000000 +0300 @@ -29,8 +29,8 @@ int charging_screen(void); void charging_splash(void); -#ifdef HAVE_MMC -int mmc_remove_request(void); +#ifdef HAVE_HOTSWAP +int card_remove_request(void); #endif #ifdef HAVE_PITCHSCREEN diff --strip-trailing-cr -u -r rockbox/trunk/apps/settings.h rockbox-daily-20070528/apps/settings.h --- rockbox/trunk/apps/settings.h 2007-05-29 23:24:18.000000000 +0300 +++ rockbox-daily-20070528/apps/settings.h 2007-05-29 23:27:23.000000000 +0300 @@ -307,6 +307,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 --strip-trailing-cr -u -r rockbox/trunk/apps/settings_list.c rockbox-daily-20070528/apps/settings_list.c --- rockbox/trunk/apps/settings_list.c 2007-05-29 23:24:18.000000000 +0300 +++ rockbox-daily-20070528/apps/settings_list.c 2007-05-29 23:27:23.000000000 +0300 @@ -1224,6 +1224,9 @@ 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 --strip-trailing-cr -u -r rockbox/trunk/apps/tree.c rockbox-daily-20070528/apps/tree.c --- rockbox/trunk/apps/tree.c 2007-05-20 17:30:25.000000000 +0300 +++ rockbox-daily-20070528/apps/tree.c 2007-05-29 23:27:23.000000000 +0300 @@ -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 (card_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 --strip-trailing-cr -u -r rockbox/trunk/firmware/common/dir.c rockbox-daily-20070528/firmware/common/dir.c --- rockbox/trunk/firmware/common/dir.c 2007-05-04 12:54:56.000000000 +0300 +++ rockbox-daily-20070528/firmware/common/dir.c 2007-05-29 23:27:23.000000000 +0300 @@ -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 --strip-trailing-cr -u -r rockbox/trunk/firmware/common/disk.c rockbox-daily-20070528/firmware/common/disk.c --- rockbox/trunk/firmware/common/disk.c 2007-05-26 09:36:04.000000000 +0300 +++ rockbox-daily-20070528/firmware/common/disk.c 2007-05-29 23:27:23.000000000 +0300 @@ -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 + card_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 (card_detect()) { mounted += disk_mount(1); /* try 2nd "drive", too */ } -#ifdef HAVE_HOTSWAP - mmc_enable_monitoring(true); -#endif + card_enable_monitoring(true); #endif return mounted; diff --strip-trailing-cr -u -r rockbox/trunk/firmware/drivers/ata_mmc.c rockbox-daily-20070528/firmware/drivers/ata_mmc.c --- rockbox/trunk/firmware/drivers/ata_mmc.c 2007-05-04 12:56:00.000000000 +0300 +++ rockbox-daily-20070528/firmware/drivers/ata_mmc.c 2007-05-29 23:27:23.000000000 +0300 @@ -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 = card_extract_bits(card->csd, 44, 4); card->blocksize = 1 << card->block_exp; - if ((mmc_extract_bits(card->csd, 102, 4) != card->block_exp) + if ((card_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 = card_extract_bits(card->csd, 29, 3); temp = (temp > 3) ? 3 : temp; - card->speed = mantissa[mmc_extract_bits(card->csd, 25, 4)] + card->speed = mantissa[card_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 * card_extract_bits(card->csd, 16, 8); + card->tsac = mantissa[card_extract_bits(card->csd, 9, 4)]; + temp = card_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 << card_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 = (card_extract_bits(card->csd, 54, 12) + 1) + * (1 << (card_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 --strip-trailing-cr -u -r rockbox/trunk/firmware/export/ata_mmc.h rockbox-daily-20070528/firmware/export/ata_mmc.h --- rockbox/trunk/firmware/export/ata_mmc.h 2007-05-04 12:52:35.000000000 +0300 +++ rockbox-daily-20070528/firmware/export/ata_mmc.h 2007-05-29 23:27:23.000000000 +0300 @@ -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 --strip-trailing-cr -u -r rockbox/trunk/firmware/export/config-e200.h rockbox-daily-20070528/firmware/export/config-e200.h --- rockbox/trunk/firmware/export/config-e200.h 2007-05-28 23:13:30.000000000 +0300 +++ rockbox-daily-20070528/firmware/export/config-e200.h 2007-05-29 23:27:23.000000000 +0300 @@ -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 --strip-trailing-cr -u -r rockbox/trunk/firmware/export/config.h rockbox-daily-20070528/firmware/export/config.h --- rockbox/trunk/firmware/export/config.h 2007-05-22 20:59:53.000000000 +0300 +++ rockbox-daily-20070528/firmware/export/config.h 2007-05-29 23:27:23.000000000 +0300 @@ -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 --strip-trailing-cr -u -r rockbox/trunk/firmware/export/hotswap.h rockbox-daily-20070528/firmware/export/hotswap.h --- rockbox/trunk/firmware/export/hotswap.h 2007-05-29 23:08:58.000000000 +0300 +++ rockbox-daily-20070528/firmware/export/hotswap.h 2007-05-29 23:27:23.000000000 +0300 @@ -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 card_detect(void); +tCardInfo *card_get_info(int card_no); +bool card_touched(void); +void card_enable_monitoring(bool on); +#else /* HAVE_MMC */ +#include "ata_mmc.h" +#define card_detect mmc_detect +#define card_get_info mmc_card_info +#define card_touched mmc_touched +#define card_enable_monitoring mmc_enable_monitoring +#endif + +/* helper function to extract n (<=32) bits from an arbitrary position. + counting from MSB to LSB */ +unsigned long card_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 --strip-trailing-cr -u -r rockbox/trunk/firmware/export/kernel.h rockbox-daily-20070528/firmware/export/kernel.h --- rockbox/trunk/firmware/export/kernel.h 2007-05-04 12:52:35.000000000 +0300 +++ rockbox-daily-20070528/firmware/export/kernel.h 2007-05-29 23:27:23.000000000 +0300 @@ -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_CARD_INSERTED ((SYS_EVENT | ((long)6 << 27))) +#define SYS_CARD_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 --strip-trailing-cr -u -r rockbox/trunk/firmware/hotswap.c rockbox-daily-20070528/firmware/hotswap.c --- rockbox/trunk/firmware/hotswap.c 2007-05-29 23:10:15.000000000 +0300 +++ rockbox-daily-20070528/firmware/hotswap.c 2007-05-29 23:27:23.000000000 +0300 @@ -0,0 +1,67 @@ +/*************************************************************************** + * __________ __ ___. + * 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 card_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 card_detect(void) +{ + return card_detect_target(); +} + +tCardInfo *card_get_info(int card_no) +{ + return card_get_info_target(card_no); +} + +bool card_touched(void) +{ + return card_touched_target(); +} +void card_enable_monitoring(bool on) +{ + card_enable_monitoring_target(on); +} +#endif diff --strip-trailing-cr -u -r rockbox/trunk/firmware/include/dir.h rockbox-daily-20070528/firmware/include/dir.h --- rockbox/trunk/firmware/include/dir.h 2007-05-04 12:53:10.000000000 +0300 +++ rockbox-daily-20070528/firmware/include/dir.h 2007-05-29 23:27:23.000000000 +0300 @@ -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 --strip-trailing-cr -u -r rockbox/trunk/firmware/SOURCES rockbox-daily-20070528/firmware/SOURCES --- rockbox/trunk/firmware/SOURCES 2007-05-22 20:59:55.000000000 +0300 +++ rockbox-daily-20070528/firmware/SOURCES 2007-05-29 23:27:23.000000000 +0300 @@ -113,6 +113,9 @@ #endif /* HAVE_FLASH_DISK */ #endif /* HAVE_MMC */ drivers/fat.c +#ifdef HAVE_HOTSWAP +hotswap.c +#endif #endif /* SIMULATOR */ /* EEPROM */ diff --strip-trailing-cr -u -r rockbox/trunk/firmware/target/arm/sandisk/sansa-e200/ata-e200.c rockbox-daily-20070528/firmware/target/arm/sandisk/sansa-e200/ata-e200.c --- rockbox/trunk/firmware/target/arm/sandisk/sansa-e200/ata-e200.c 2007-05-04 12:53:30.000000000 +0300 +++ rockbox-daily-20070528/firmware/target/arm/sandisk/sansa-e200/ata-e200.c 2007-05-29 23:40:30.000000000 +0300 @@ -17,14 +17,15 @@ * ****************************************************************************/ #include "ata.h" +#include "hotswap-target.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 */ +#include "panic.h" #define BLOCK_SIZE (512) #define SECTOR_SIZE (512) @@ -48,6 +49,7 @@ #define DATA_DONE (1 << 12) #define CMD_DONE (1 << 13) #define ERROR_BITS (0x3f) +#define READY_FOR_DATA (1 << 8) #define FIFO_FULL (1 << 7) #define FIFO_EMPTY (1 << 6) @@ -65,181 +67,171 @@ #define FIFO_SIZE 16 /* FIFO is 16 words deep */ /* SD Commands */ -#define GO_IDLE_STATE 0 -#define ALL_SEND_CID 2 -#define SEND_RELATIVE_ADDR 3 -#define SET_DSR 4 -#define SWITCH_FUNC 6 -#define SELECT_CARD 7 -#define DESELECT_CARD 7 -#define SEND_CSD 9 -#define SEND_CID 10 -#define STOP_TRANSMISSION 12 -#define SEND_STATUS 13 -#define GO_INACTIVE_STATE 15 -#define SET_BLOCKLEN 16 -#define READ_SINGLE_BLOCK 17 -#define READ_MULTIPLE_BLOCK 18 -#define WRITE_BLOCK 24 -#define WRITE_MULTIPLE_BLOCK 25 -#define ERASE_WR_BLK_START 32 -#define ERASE_WR_BLK_END 33 -#define ERASE 38 +#define GO_IDLE_STATE 0 +#define ALL_SEND_CID 2 +#define SEND_RELATIVE_ADDR 3 +#define SET_DSR 4 +#define SWITCH_FUNC 6 +#define SELECT_CARD 7 +#define DESELECT_CARD 7 +#define SEND_CSD 9 +#define SEND_CID 10 +#define STOP_TRANSMISSION 12 +#define SEND_STATUS 13 +#define GO_INACTIVE_STATE 15 +#define SET_BLOCKLEN 16 +#define READ_SINGLE_BLOCK 17 +#define READ_MULTIPLE_BLOCK 18 +#define SEND_NUM_WR_BLOCKS 22 +#define WRITE_BLOCK 24 +#define WRITE_MULTIPLE_BLOCK 25 +#define ERASE_WR_BLK_START 32 +#define ERASE_WR_BLK_END 33 +#define ERASE 38 + +#define EC_POWER_UP 1 /* error code */ +#define EC_READ_TIMEOUT 2 /* error code */ +#define EC_WRITE_TIMEOUT 3 /* error code */ +#define EC_TRAN_SEL_BANK 4 /* error code */ +#define EC_TRAN_READ_ENTRY 5 /* error code */ +#define EC_TRAN_READ_EXIT 6 /* error code */ +#define EC_TRAN_WRITE_ENTRY 7 /* error code */ +#define EC_TRAN_WRITE_EXIT 8 /* error code */ +#define DO_PANIC 32 /* marker */ +#define NO_PANIC 0 /* marker */ +#define EC_COMMAND 10 /* error code */ +#define EC_FIFO_SEL_BANK_EMPTY 11 /* error code */ +#define EC_FIFO_SEL_BANK_DONE 12 /* error code */ +#define EC_FIFO_ENA_BANK_EMPTY 13 /* error code */ +#define EC_FIFO_READ_FULL 14 /* error code */ +#define EC_FIFO_WR_EMPTY 15 /* error code */ +#define EC_FIFO_WR_DONE 16 /* error code */ /* Application Specific commands */ #define SET_BUS_WIDTH 6 #define SD_APP_OP_COND 41 -#define READ_TIMEOUT 5*HZ -#define WRITE_TIMEOUT 0.5*HZ - -static unsigned short identify_info[SECTOR_SIZE]; -int ata_spinup_time = 0; long last_disk_activity = -1; -static bool initialized = false; - -static unsigned char current_bank = 0; /* The bank that we are working with */ +static bool sd_thread_initialized = false; static tSDCardInfo card_info[2]; - -/* For multi volume support */ -static int current_card = 0; +static tSDCardInfo *currcard; /* current active card */ 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 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 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) +static unsigned int check_time[10]; + +static inline void sd_check_timeout(unsigned int timeout, int id) { - bool result = false; - do + if(USEC_TIMER > check_time[id] + timeout) + panicf("Error SDCard: %d", id); +} + +static inline bool sd_poll_status(unsigned int trigger, unsigned int timeout, + int id) +{ + unsigned int t = USEC_TIMER; + + while ((STATUS_REG & trigger) == 0) { - CMD_REG0 = cmd; - CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16); - CMD_REG2 = (unsigned int)((arg1 & 0xffff)); - UNKNOWN = arg2; - while ((STATUS_REG & CMD_DONE) == 0) + if(USEC_TIMER > t + timeout) { - /* Busy wait */ + if(id & DO_PANIC) + panicf("Error SDCard: %d", id & 31); + + return false; } - if ((STATUS_REG & ERROR_BITS) == 0) - { - result = true; - } - } while ((STATUS_REG & ERROR_BITS) != 0); - return result; + } + + return true; } -void sd_read_response(unsigned int *response, int type) + +bool sd_command(unsigned int cmd, unsigned long arg1, unsigned int *response, + unsigned int type) { - int i; - int words; /* Number of 16 bit words to read from RESPONSE_REG */ - unsigned int response_from_card[9]; - if(type == 2) - { - words = 9; /* R2 types are 8.5 16-bit words long */ - } else { - words = 3; - } + int i, words; /* Number of 16 bit words to read from RESPONSE_REG */ + unsigned int data[9]; + + do + { CMD_REG0 = cmd; + CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16); + CMD_REG2 = (unsigned int)((arg1 & 0xffff)); + UNKNOWN = type; + + sd_poll_status(CMD_DONE, 100000, EC_COMMAND | DO_PANIC); + + } while (STATUS_REG & ERROR_BITS); + + if(cmd == GO_IDLE_STATE) return true; /* no response here */ + + words = (type == 2) ? 9 : 3; for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */ { - response_from_card[i] = RESPONSE_REG; /* Read most significant 16-bit word */ + data[i] = RESPONSE_REG; /* Read most significant 16-bit word */ } - switch (type) + if(type == 2) { - case 1: - /* Response type 1 has the following structure: - Start bit - Transmission bit - Command index (6 bits) - Card Status (32 bits) - CRC7 (7 bits) - Stop bit - */ - /* TODO: Sanity checks */ - response[0] = ((response_from_card[0] & 0xff) << 24) - + (response_from_card[1] << 8) - + ((response_from_card[2] & 0xff00) >> 8); - break; - case 2: - /* Response type 2 has the following structure: - Start bit - Transmission bit - Reserved (6 bits) - CSD/CID register (127 bits) - Stop bit - */ - response[3] = ((response_from_card[0]&0xff)<<24) + - (response_from_card[1]<<8) + - ((response_from_card[2]&0xff00)>>8); - response[2] = ((response_from_card[2]&0xff)<<24) + - (response_from_card[3]<<8) + - ((response_from_card[4]&0xff00)>>8); - response[1] = ((response_from_card[4]&0xff)<<24) + - (response_from_card[5]<<8) + - ((response_from_card[6]&0xff00)>>8); - response[0] = ((response_from_card[6]&0xff)<<24) + - (response_from_card[7]<<8) + - ((response_from_card[8]&0xff00)>>8); - break; - case 3: - /* Response type 3 has the following structure: - Start bit - Transmission bit - Reserved (6 bits) - OCR register (32 bits) - Reserved (7 bits) - Stop bit - */ - response[0] = ((response_from_card[0] & 0xff) << 24) - + (response_from_card[1] << 8) - + ((response_from_card[2] & 0xff00) >> 8); - /* Types 4-6 not supported yet */ - } -} - -bool sd_send_acommand(unsigned int cmd, unsigned long arg1, unsigned int arg2) -{ - unsigned int returncode; - if (sd_send_command(55, (card_info[current_card].rca)<<16, 1) == false) - return false; - sd_read_response(&returncode, 1); - if (sd_send_command(cmd, arg1, arg2) == false) - return false; + /* Response type 2 has the following structure: + Start bit + Transmission bit + Reserved (6 bits) + CSD/CID register (127 bits) + Stop bit */ + response[3] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8); + response[2] = (data[2]<<24) + (data[3]<<8) + ((data[4]&0xff00)>>8); + response[1] = (data[4]<<24) + (data[5]<<8) + ((data[6]&0xff00)>>8); + response[0] = (data[6]<<24) + (data[7]<<8) + ((data[8]&0xff00)>>8); + } + else + { + /* Response types 1,3 have the following structure: + Start bit Transmission bit + Command index (6 bits) + Card data (32 bits) + CRC7 (7 bits) + Stop bit */ + response[0] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8); + } + return true; } -void sd_wait_for_state(tSDCardInfo* card, unsigned int state) +void sd_wait_for_state(unsigned int state, unsigned int id) { unsigned int response = 0; + + check_time[id] = USEC_TIMER; while(((response >> 9) & 0xf) != state) { - sd_send_command(SEND_STATUS, (card->rca) << 16, 1); - sd_read_response(&response, 1); - /* TODO: Add a timeout and error handling */ + sd_command(SEND_STATUS, currcard->rca, &response, 1); + sd_check_timeout(0x80000, id); } SD_STATE_REG = state; } -STATICIRAM void copy_read_sectors(unsigned char* buf, int wordcount) - NOINLINE_ATTR ICODE_ATTR; - -STATICIRAM void copy_read_sectors(unsigned char* buf, int wordcount) +static inline void copy_read_sectors(unsigned char* buf) { - unsigned int tmp = 0; - - if ( (unsigned long)buf & 1) + if ( (int)buf & 1) { /* not 16-bit aligned, copy byte by byte */ - unsigned char* bufend = buf + wordcount*2; + unsigned int tmp = 0; + unsigned char* bufend = buf + FIFO_SIZE*2; do { tmp = DATA_REG; @@ -250,24 +242,33 @@ else { /* 16-bit aligned, can do faster copy */ unsigned short* wbuf = (unsigned short*)buf; - unsigned short* wbufend = wbuf + wordcount; - do - { - *wbuf = DATA_REG; - } while (++wbuf < wbufend); /* tail loop is faster */ + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; + *wbuf++ = DATA_REG; } } -STATICIRAM void copy_write_sectors(const unsigned char* buf, int wordcount) - NOINLINE_ATTR ICODE_ATTR; - -STATICIRAM void copy_write_sectors(const unsigned char* buf, int wordcount) +static inline void copy_write_sectors(const unsigned char* buf) { unsigned short tmp = 0; - const unsigned char* bufend = buf + wordcount*2; + const unsigned char* bufend = buf + FIFO_SIZE*2; + do { - tmp = (unsigned short) *buf++; + tmp = (unsigned short) *buf++; tmp |= (unsigned short) *buf++ << 8; DATA_REG = tmp; } while (buf < bufend); /* tail loop is faster */ @@ -280,16 +281,14 @@ unsigned char card_data[512]; unsigned char* write_buf; int i; - tSDCardInfo *card = &card_info[0]; /* Bank selection will only be done on - the onboard flash */ - if (current_bank != bank) + + if (currcard->current_bank != bank) { memset(card_data, 0, 512); - sd_wait_for_state(card, TRAN); + sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK); BLOCK_SIZE_REG = 512; BLOCK_COUNT_REG = 1; - sd_send_command(35, 0, 0x1c0d); /* CMD35 is vendor specific */ - sd_read_response(&response, 1); + sd_command(35, 0, &response, 0x1c0d); /* CMD35 is vendor specific */ SD_STATE_REG = PRG; card_data[0] = bank; @@ -298,68 +297,69 @@ write_buf = card_data; for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE) { - /* Wait for the FIFO to be empty */ - while((STATUS_REG & FIFO_EMPTY) == 0) {} /* Erm... is this right? */ + /* Wait for the FIFO to empty */ + sd_poll_status(FIFO_EMPTY, 10000, EC_FIFO_SEL_BANK_EMPTY | DO_PANIC); - copy_write_sectors(write_buf, FIFO_SIZE); + copy_write_sectors(write_buf); /* Copy one chunk of 16 words */ write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ } - while((STATUS_REG & DATA_DONE) == 0) {} - current_bank = bank; + sd_poll_status(DATA_DONE, 10000, EC_FIFO_SEL_BANK_DONE | DO_PANIC); + + currcard->current_bank = bank; } } -void sd_init_device(void) +void sd_init_device(int card_no) { /* SD Protocol registers */ - unsigned int dummy; - int i; - - static unsigned int read_bl_len = 0; - static unsigned int c_size = 0; - static unsigned int c_size_mult = 0; - static unsigned long mult = 0; - + unsigned int i, dummy; + unsigned int c_size = 0; + unsigned long c_mult = 0; unsigned char carddata[512]; unsigned char *dataptr; - tSDCardInfo *card = &card_info[0]; /* Init onboard flash only */ + + currcard = &card_info[card_no]; /* Initialise card data as blank */ - card->initialized = false; - card->ocr = 0; - card->csd[0] = 0; - card->csd[1] = 0; - card->csd[2] = 0; - card->cid[0] = 0; - card->cid[1] = 0; - card->cid[2] = 0; - card->rca = 0; - - card->capacity = 0; - card->numblocks = 0; - card->block_size = 0; - card->block_exp = 0; + memset(currcard, 0, sizeof(*currcard)); /* Enable and initialise controller */ - GPIOG_ENABLE |= (0x3 << 5); - GPIOG_OUTPUT_EN |= (0x3 << 5); + GPIOG_ENABLE |= (0x3 << 5); + GPIOG_OUTPUT_EN |= (0x3 << 5); GPIOG_OUTPUT_VAL |= (0x3 << 5); outl(inl(0x70000088) & ~(0x4), 0x70000088); outl(inl(0x7000008c) & ~(0x4), 0x7000008c); 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); + + GPIOD_ENABLE &= ~0x1f; + GPIOD_OUTPUT_EN &= ~0x1f; + GPIOA_ENABLE |= 0x7a; + GPIOA_OUTPUT_EN |= 0x7a; + + outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); + } + DEV_EN |= DEV_ATA; /* Enable controller */ DEV_RS |= DEV_ATA; /* Reset controller */ DEV_RS &=~DEV_ATA; /* Clear Reset */ @@ -367,69 +367,50 @@ outl(0, 0x6000a000); /* Init DMA controller? */ /* Init NAND */ - REG_11 |= (1 << 15); - REG_12 |= (1 << 15); + REG_11 |= (1 << 15); + REG_12 |= (1 << 15); REG_12 &= ~(3 << 12); - REG_12 |= (1 << 13); + REG_12 |= (1 << 13); REG_11 &= ~(3 << 12); - REG_11 |= (1 << 13); + REG_11 |= (1 << 13); SD_STATE_REG = TRAN; REG_5 = 0xf; - sd_send_command(GO_IDLE_STATE, 0, 256); - 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 (card->ocr == 0) - { - /* TODO: Handle failure */ - while (1) {}; - } + sd_command(GO_IDLE_STATE, 0, &dummy, 256); + check_time[EC_POWER_UP] = USEC_TIMER; + while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ + { + sd_command(55, currcard->rca, &dummy, 1); + sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3); + sd_check_timeout(5000000, EC_POWER_UP); } - sd_send_command(ALL_SEND_CID, 0, 2); - sd_read_response(card->cid, 2); - sd_send_command(SEND_RELATIVE_ADDR, 0, 1); - sd_read_response(&card->rca, 1); - card->rca >>= 16; /* The Relative Card Address is the top 16 bits of the - 32 bits returned. Whenever it is used, it gets - shifted left by 16 bits, so this step could possibly - be skipped. */ + sd_command(ALL_SEND_CID, 0, currcard->cid, 2); + sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1); + sd_command(SEND_CSD, currcard->rca, currcard->csd, 2); - sd_send_command(SEND_CSD, card->rca << 16, 2); - sd_read_response(card->csd, 2); - - /* Parse disk geometry */ /* These calculations come from the Sandisk SD card product manual */ - read_bl_len = ((card->csd[2] >> 16) & 0xf); - c_size = ((card->csd[2] & (0x3ff)) << 2) + - ((card->csd[1] & (0xc0000000)) >> 30); - c_size_mult = ((card->csd[1] >> 15) & 0x7); - mult = (1<<(c_size_mult + 2)); - card->max_read_bl_len = (1<block_size = BLOCK_SIZE; /* Always use 512 byte blocks */ - card->numblocks = (c_size + 1) * mult * (card->max_read_bl_len / 512); - card->capacity = card->numblocks * card->block_size; + c_size = ((currcard->csd[2] & 0x3ff) << 2) + (currcard->csd[1] >> 30) + 1; + c_mult = 4 << ((currcard->csd[1] >> 15) & 7); + currcard->max_read_bl_len = 1 << ((currcard->csd[2] >> 16) & 15); + currcard->block_size = BLOCK_SIZE; /* Always use 512 byte blocks */ + currcard->numblocks = c_size * c_mult * (currcard->max_read_bl_len / 512); + currcard->capacity = currcard->numblocks * currcard->block_size; REG_1 = 0; - sd_send_command(SELECT_CARD, card->rca << 16, 129); - sd_read_response(&dummy, 1); /* I don't think we use the result from this */ - sd_send_acommand(SET_BUS_WIDTH, (card->rca << 16) | 2, 1); - sd_read_response(&dummy, 1); /* 4 bit wide bus */ - sd_send_command(SET_BLOCKLEN, card->block_size, 1); - sd_read_response(&dummy, 1); - BLOCK_SIZE_REG = card->block_size; + sd_command(SELECT_CARD, currcard->rca , &dummy, 129); + sd_command(55, currcard->rca , &dummy, 1); + sd_command(SET_BUS_WIDTH, currcard->rca | 2 , &dummy, 1); /* 4 bit */ + sd_command(SET_BLOCKLEN, currcard->block_size, &dummy, 1); + BLOCK_SIZE_REG = currcard->block_size; /* If this card is > 4Gb, then we need to enable bank switching */ - if(card->numblocks >= BLOCKS_PER_BANK) + if(currcard->numblocks >= BLOCKS_PER_BANK) { SD_STATE_REG = TRAN; BLOCK_COUNT_REG = 1; - sd_send_command(SWITCH_FUNC, 0x80ffffef, 0x1c05); - sd_read_response(&dummy, 1); + sd_command(SWITCH_FUNC, 0x80ffffef, &dummy, 0x1c05); /* Read 512 bytes from the card. The first 512 bits contain the status information TODO: Do something useful with this! */ @@ -437,14 +418,14 @@ for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE) { /* Wait for the FIFO to be full */ - while((STATUS_REG & FIFO_FULL) == 0) {} + sd_poll_status(FIFO_FULL, 100000, EC_FIFO_ENA_BANK_EMPTY | DO_PANIC); - copy_read_sectors(dataptr, FIFO_SIZE); + copy_read_sectors(dataptr); /* Copy one chunk of 16 words */ dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */ } } - mutex_init(&sd_mtx); + currcard->initialized = true; } /* API Functions */ @@ -454,81 +435,62 @@ (void)onoff; } -int ata_read_sectors(IF_MV2(int drive,) - unsigned long start, - int incount, +int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, void* inbuf) { - int ret = 0; - long timeout; - int count; - void* buf; - long spinup_start; + int ret = 0; + void *buf, *buf_end; unsigned int dummy; - unsigned int response; - unsigned int i; - tSDCardInfo *card = &card_info[current_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); - timeout = current_tick + READ_TIMEOUT; - - /* TODO: Select device */ - if(current_card == 0) + if(drive && (GPIOA_INPUT_VAL & 0x80)) /* no external sd-card inserted */ { - if(start >= BLOCKS_PER_BANK) - { - sd_select_bank(1); - start -= BLOCKS_PER_BANK; - } else { - sd_select_bank(0); - } + ret = -9; + goto error; } - buf = inbuf; - count = incount; - while (TIME_BEFORE(current_tick, timeout)) { - ret = 0; - last_disk_activity = current_tick; + if((card_info+drive != currcard) || !card_info[drive].initialized) + sd_init_device(drive); - SD_STATE_REG = TRAN; - BLOCK_COUNT_REG = count; - sd_send_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, 0x1c25); - sd_read_response(&dummy, 1); - /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ + last_disk_activity = current_tick; - for (i = 0; i < count * card->block_size / 2; i += FIFO_SIZE) - { - /* Wait for the FIFO to be full */ - while((STATUS_REG & FIFO_FULL) == 0) {} + if(start >= BLOCKS_PER_BANK) + { + sd_select_bank(1); + start -= BLOCKS_PER_BANK; + } + else + sd_select_bank(0); - copy_read_sectors(buf, FIFO_SIZE); + ret = 0; + sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); + BLOCK_COUNT_REG = incount; + sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &dummy, 0x1c25); + /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ - buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ + buf_end = inbuf + incount * currcard->block_size; + for (buf = inbuf; buf < buf_end; buf += FIFO_SIZE*2) + { + /* Wait for the FIFO to be full */ + sd_poll_status(FIFO_FULL, 0x80000, EC_FIFO_READ_FULL | DO_PANIC); - /* TODO: Switch bank if necessary */ + copy_read_sectors(buf); /* Copy one chunk of 16 words */ - last_disk_activity = current_tick; - } - udelay(75); - sd_send_command(STOP_TRANSMISSION, 0, 1); - sd_read_response(&dummy, 1); - - response = 0; - sd_wait_for_state(card, TRAN); - break; + /* TODO: Switch bank if necessary */ } + + last_disk_activity = current_tick; +// udelay(75); + sd_command(STOP_TRANSMISSION, 0, &dummy, 1); + sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT); + + error: ata_led(false); ata_enable(false); @@ -538,75 +500,71 @@ } -int ata_write_sectors(IF_MV2(int drive,) - unsigned long start, - int count, - const void* buf) +int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, + const void* outbuf) { /* Write support is not finished yet */ -/* TODO: The standard suggests using ACMD23 prior to writing multiple blocks +/* TODO: The standard suggests using ACMD23 prior to writing multiple blocks to improve performance */ unsigned int response; - void const* write_buf; + void const* buf, *buf_end; int ret = 0; - unsigned int i; - long timeout; - tSDCardInfo *card = &card_info[current_card]; mutex_lock(&sd_mtx); + ata_enable(true); ata_led(true); - if(current_card == 0) + + if(drive && (GPIOA_INPUT_VAL & 0x80)) /* no external sd-card inserted */ { - if(start < BLOCKS_PER_BANK) - { - sd_select_bank(0); - } else { - sd_select_bank(1); - start -= BLOCKS_PER_BANK; - } + ret = -9; + goto error; } -retry: - sd_wait_for_state(card, TRAN); + if((card_info+drive != currcard) || !card_info[drive].initialized) + sd_init_device(drive); + + if(start >= BLOCKS_PER_BANK) + { + sd_select_bank(1); + start -= BLOCKS_PER_BANK; + } + else + sd_select_bank(0); + + check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; + sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); BLOCK_COUNT_REG = count; - sd_send_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, 0x1c2d); - sd_read_response(&response, 1); - write_buf = buf; - for (i = 0; i < count * card->block_size / 2; i += FIFO_SIZE) + sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, &response, 0x1c2d); + + buf_end = outbuf + count * currcard->block_size; + for (buf = outbuf; buf < buf_end; buf += 2 * FIFO_SIZE) { - if(i >= (count * card->block_size / 2)-FIFO_SIZE) + if(buf >= buf_end - 2 * FIFO_SIZE) { /* Set SD_STATE_REG to PRG for the last buffer fill */ SD_STATE_REG = PRG; } - /* Wait for the FIFO to be empty */ - while((STATUS_REG & FIFO_EMPTY) == 0) {} - /* Perhaps we could use bit 8 of card status (READY_FOR_DATA)? */ + udelay(2); /* needed here (loop is too fast :-) */ - copy_write_sectors(write_buf, FIFO_SIZE); + /* Wait for the FIFO to empty */ + sd_poll_status(FIFO_EMPTY, 0x80000, EC_FIFO_WR_EMPTY | DO_PANIC); - write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ - /* TODO: Switch bank if necessary */ + copy_write_sectors(buf); /* Copy one chunk of 16 words */ - last_disk_activity = current_tick; + /* TODO: Switch bank if necessary */ } - timeout = current_tick + WRITE_TIMEOUT; + last_disk_activity = current_tick; + + sd_poll_status(DATA_DONE, 0x80000, EC_FIFO_WR_DONE | DO_PANIC); + sd_check_timeout(0x80000, EC_WRITE_TIMEOUT); - while((STATUS_REG & DATA_DONE) == 0) { - if(current_tick >= timeout) - { - sd_send_command(STOP_TRANSMISSION, 0, 1); - sd_read_response(&response, 1); - goto retry; - } - } - sd_send_command(STOP_TRANSMISSION, 0, 1); - sd_read_response(&response, 1); + sd_command(STOP_TRANSMISSION, 0, &response, 1); + sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT); - sd_wait_for_state(card, TRAN); + error: ata_led(false); ata_enable(false); mutex_unlock(&sd_mtx); @@ -623,6 +581,16 @@ queue_wait_w_tmo(&sd_queue, &ev, HZ); switch ( ev.id ) { + case SYS_CARD_INSERTED: + disk_mount(1); /* mount SD-CARD */ + queue_broadcast(SYS_FS_CHANGED, 0); + break; + + case SYS_CARD_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))) { @@ -683,22 +651,115 @@ } } -unsigned short* ata_get_identify(void) -{ - return identify_info; -} - int ata_init(void) { - sd_init_device(); - if ( !initialized ) + mutex_init(&sd_mtx); + sd_init_device(0); + if ( !sd_thread_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)); - initialized = true; + create_thread(sd_thread, sd_stack, sizeof(sd_stack), + sd_thread_name IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU, false)); + tick_add_task(sd_tick); + sd_thread_initialized = true; } return 0; } + +/* move the sd-card info to mmc struct */ +tCardInfo *card_get_info_target(int card_no) +{ + int i, temp; + static tCardInfo card; + 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; + for(i=0; i<4; i++) card.csd[i] = card_info[card_no].csd[3-i]; + for(i=0; i<4; i++) card.cid[i] = card_info[card_no].cid[3-i]; + 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 = card_extract_bits(card.csd, 29, 3); + card.speed = mantissa[card_extract_bits(card.csd, 25, 4)] + * exponent[temp > 2 ? 7 : temp + 4]; + card.nsac = 100 * card_extract_bits(card.csd, 16, 8); + temp = card_extract_bits(card.csd, 13, 3); + card.tsac = mantissa[card_extract_bits(card.csd, 9, 4)] + * exponent[temp] / 10; + card.cid[0] = htobe32(card.cid[0]); /* ascii chars here */ + card.cid[1] = htobe32(card.cid[1]); /* ascii chars here */ + temp = *((char*)card.cid+13); /* adjust year<=>month, 1997 <=> 2000 */ + *((char*)card.cid+13) = (unsigned char)((temp >> 4) | (temp << 4)) + 3; + + return &card; +} + +bool card_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 card_detect_target(void) +{ + return GPIOA_INPUT_VAL & 0x80 ? false : true; +} + +void card_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_CARD_INSERTED, 0); + } + else + { + queue_broadcast(SYS_CARD_EXTRACTED, 0); + sd_status = SD_UNKNOWN; + card_info[1].initialized = false; + } + } + } + } +} diff --strip-trailing-cr -u -r rockbox/trunk/firmware/target/arm/sandisk/sansa-e200/ata-target.h rockbox-daily-20070528/firmware/target/arm/sandisk/sansa-e200/ata-target.h --- rockbox/trunk/firmware/target/arm/sandisk/sansa-e200/ata-target.h 2007-05-04 12:53:30.000000000 +0300 +++ rockbox-daily-20070528/firmware/target/arm/sandisk/sansa-e200/ata-target.h 2007-05-29 23:27:23.000000000 +0300 @@ -19,25 +19,4 @@ #ifndef ATA_TARGET_H #define ATA_TARGET_H -#include "inttypes.h" - -typedef struct -{ - bool initialized; - - unsigned int ocr; /* OCR register */ - unsigned int csd[4]; /* CSD register */ - unsigned int cid[4]; /* CID register */ - unsigned int rca; - - uint64_t capacity; /* size in bytes */ - unsigned long numblocks; /* size in flash blocks */ - unsigned int block_size; /* block size in bytes */ - unsigned int max_read_bl_len;/* max read data block length */ - unsigned int block_exp; /* block size exponent */ -} tSDCardInfo; - -tSDCardInfo *sd_card_info(int card_no); -bool sd_touched(void); - #endif diff --strip-trailing-cr -u -r rockbox/trunk/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h rockbox-daily-20070528/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h --- rockbox/trunk/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h 2007-05-29 23:11:05.000000000 +0300 +++ rockbox-daily-20070528/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h 2007-05-29 23:27:23.000000000 +0300 @@ -0,0 +1,48 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: hotswap-target.h 13250 2007-04-23 23:26:23Z barrywardell $ + * + * Copyright (C) 2007 by Antonius Hellmann + * + * 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 "inttypes.h" +#include "hotswap.h" + +typedef struct +{ + bool initialized; + + unsigned int ocr; /* OCR register */ + unsigned int csd[4]; /* CSD register */ + unsigned int cid[4]; /* CID register */ + unsigned int rca; + + uint64_t capacity; /* size in bytes */ + unsigned long numblocks; /* size in flash blocks */ + unsigned int block_size; /* block size in bytes */ + unsigned int max_read_bl_len;/* max read data block length */ + unsigned int block_exp; /* block size exponent */ + unsigned char current_bank; /* The bank that we are working with */ +} tSDCardInfo; + +tCardInfo *card_get_info_target(int card_no); +bool card_detect_target(void); +void card_enable_monitoring_target(bool on); +bool card_touched_target(void); + + +#endif /* __HOTSWAP_TARGET_H__ */ diff --strip-trailing-cr -u -r rockbox/trunk/firmware/usb.c rockbox-daily-20070528/firmware/usb.c --- rockbox/trunk/firmware/usb.c 2007-05-04 12:56:00.000000000 +0300 +++ rockbox-daily-20070528/firmware/usb.c 2007-05-29 23:27:23.000000000 +0300 @@ -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);