diff --strip-trailing-cr -u -r rockbox/trunk/firmware/export/config-e200.h rockbox-daily-20070511/firmware/export/config-e200.h --- rockbox/trunk/firmware/export/config-e200.h 2007-05-04 12:52:35.000000000 +0300 +++ rockbox-daily-20070511/firmware/export/config-e200.h 2007-05-08 23:07:09.000000000 +0300 @@ -19,6 +19,10 @@ /* define this if you have LCD enable function */ #define HAVE_LCD_ENABLE +#define HAVE_MMC +#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-20070511/firmware/export/config.h --- rockbox/trunk/firmware/export/config.h 2007-05-04 12:52:35.000000000 +0300 +++ rockbox-daily-20070511/firmware/export/config.h 2007-05-08 23:18:22.000000000 +0300 @@ -242,7 +242,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/SOURCES rockbox-daily-20070511/firmware/SOURCES --- rockbox/trunk/firmware/SOURCES 2007-05-04 12:56:00.000000000 +0300 +++ rockbox-daily-20070511/firmware/SOURCES 2007-05-08 23:02:01.000000000 +0300 @@ -101,7 +101,7 @@ /* Storage */ #ifndef SIMULATOR -#ifdef HAVE_MMC +#if defined(HAVE_MMC) && !defined(SANSA_E200) drivers/ata_mmc.c #else /* !HAVE_MMC */ #ifdef HAVE_FLASH_DISK diff --strip-trailing-cr -u -r rockbox/trunk/firmware/target/arm/sandisk/sansa-e200/ata-e200.c rockbox-daily-20070511/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-20070511/firmware/target/arm/sandisk/sansa-e200/ata-e200.c 2007-05-08 23:06:11.000000000 +0300 @@ -17,11 +17,13 @@ * ****************************************************************************/ #include "ata.h" +#include "ata_mmc.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 */ @@ -112,6 +114,14 @@ 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 */ @@ -444,7 +475,7 @@ dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */ } } - mutex_init(&sd_mtx); + card->initialized = true; } /* API Functions */ @@ -467,21 +498,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); - 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) + { + current_card = drive; + sd_init_device(drive); + } + + card = &card_info[current_card]; + + last_disk_activity = current_tick; + spinup_start = current_tick; + timeout = current_tick + READ_TIMEOUT; /* TODO: Select device */ @@ -529,6 +571,9 @@ sd_wait_for_state(card, TRAN); break; } + + error: + ata_led(false); ata_enable(false); @@ -551,11 +596,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 +668,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 +687,16 @@ queue_wait_w_tmo(&sd_queue, &ev, HZ); switch ( ev.id ) { + case SYS_MMC_INSERTED: + disk_mount(1); /* mount SD-CARD */ + queue_broadcast(SYS_FS_CHANGED, 0); + break; + + case SYS_MMC_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 +764,139 @@ 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)); + tick_add_task(sd_tick); initialized = true; } return 0; } + +/* move the sd-card info to mmc struct */ +tCardInfo *mmc_card_info(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 = mmc_extract_bits(card.csd, 29, 3); + card.speed = mantissa[mmc_extract_bits(card.csd, 25, 4)] + * exponent[temp > 2 ? 7 : temp + 4]; + card.nsac = 100 * mmc_extract_bits(card.csd, 16, 8); + temp = mmc_extract_bits(card.csd, 13, 3); + card.tsac = mantissa[mmc_extract_bits(card.csd, 9, 4)] + * exponent[temp] / 10; + + return &card; +} + +/* 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; +} + +bool mmc_touched(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 mmc_usb_active(int delayticks) +{ + (void)delayticks; + return false; +} + +bool mmc_detect(void) +{ + return GPIOA_INPUT_VAL & 0x80 ? false : true; +} + +void mmc_enable_monitoring(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_MMC_INSERTED, 0); + } + else + { + queue_broadcast(SYS_MMC_EXTRACTED, 0); + sd_status = SD_UNKNOWN; + card_info[1].initialized = false; + } + } + } + } +}