summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-06-30 02:08:27 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-06-30 02:08:27 +0000
commit1167e3c72f5d0d581b81fd2cb8f2580a1524ca5a (patch)
tree501f9901636d5586271067d0c157204e500a2cfd
parent189a5f812f47e43e5704a44c3abb85a4c37c8662 (diff)
downloadrockbox-1167e3c72f5d0d581b81fd2cb8f2580a1524ca5a.tar.gz
rockbox-1167e3c72f5d0d581b81fd2cb8f2580a1524ca5a.zip
Accept FS#7134 - Sansa: external sd card support by Antonius Hellmann with some tweaks. All testers have given the green light. (Now for the RED ?? ;).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13741 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/debug_menu.c46
-rw-r--r--apps/main.c3
-rw-r--r--apps/misc.c3
-rw-r--r--apps/screens.c4
-rw-r--r--bootloader/main-pp.c20
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/common/dir.c3
-rw-r--r--firmware/common/disk.c16
-rw-r--r--firmware/drivers/ata_mmc.c48
-rw-r--r--firmware/export/ata_mmc.h24
-rw-r--r--firmware/export/config-e200.h5
-rw-r--r--firmware/export/config.h2
-rw-r--r--firmware/export/hotswap.h59
-rw-r--r--firmware/export/kernel.h4
-rw-r--r--firmware/export/pp5024.h2
-rw-r--r--firmware/hotswap.c58
-rw-r--r--firmware/include/dir.h4
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-e200.c1031
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-target.h21
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/hotswap-target.h45
-rw-r--r--firmware/target/arm/system-pp502x.c13
-rw-r--r--firmware/usb.c4
22 files changed, 882 insertions, 536 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 0b39430d56..fe7d5b584b 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -59,7 +59,7 @@
59#include "fat.h" 59#include "fat.h"
60#include "mas.h" 60#include "mas.h"
61#include "eeprom_24cxx.h" 61#include "eeprom_24cxx.h"
62#ifdef HAVE_MMC 62#if defined(HAVE_MMC) || defined(HAVE_HOTSWAP)
63#include "ata_mmc.h" 63#include "ata_mmc.h"
64#endif 64#endif
65#if CONFIG_TUNER 65#if CONFIG_TUNER
@@ -1524,8 +1524,8 @@ static bool view_battery(void)
1524#endif 1524#endif
1525 1525
1526#ifndef SIMULATOR 1526#ifndef SIMULATOR
1527#ifdef HAVE_MMC 1527#if defined(HAVE_MMC) || defined(HAVE_HOTSWAP)
1528static bool dbg_mmc_info(void) 1528static bool dbg_card_info(void)
1529{ 1529{
1530 bool done = false; 1530 bool done = false;
1531 int currval = 0; 1531 int currval = 0;
@@ -1548,7 +1548,7 @@ static bool dbg_mmc_info(void)
1548 1548
1549 while (!done) 1549 while (!done)
1550 { 1550 {
1551 card = mmc_card_info(currval / 2); 1551 card = card_get_info(currval / 2);
1552 1552
1553 line = 0; 1553 line = 0;
1554 lcd_clear_display(); 1554 lcd_clear_display();
@@ -1564,29 +1564,29 @@ static bool dbg_mmc_info(void)
1564 1564
1565 strncpy(card_name, ((unsigned char*)card->cid) + 3, 6); 1565 strncpy(card_name, ((unsigned char*)card->cid) + 3, 6);
1566 snprintf(pbuf, sizeof(pbuf), "%s Rev %d.%d", card_name, 1566 snprintf(pbuf, sizeof(pbuf), "%s Rev %d.%d", card_name,
1567 (int) mmc_extract_bits(card->cid, 72, 4), 1567 (int) card_extract_bits(card->cid, 72, 4),
1568 (int) mmc_extract_bits(card->cid, 76, 4)); 1568 (int) card_extract_bits(card->cid, 76, 4));
1569 lcd_puts(0, line++, pbuf); 1569 lcd_puts(0, line++, pbuf);
1570 snprintf(pbuf, sizeof(pbuf), "Prod: %d/%d", 1570 snprintf(pbuf, sizeof(pbuf), "Prod: %d/%d",
1571 (int) mmc_extract_bits(card->cid, 112, 4), 1571 (int) card_extract_bits(card->cid, 112, 4),
1572 (int) mmc_extract_bits(card->cid, 116, 4) + 1997); 1572 (int) card_extract_bits(card->cid, 116, 4) + 1997);
1573 lcd_puts(0, line++, pbuf); 1573 lcd_puts(0, line++, pbuf);
1574 snprintf(pbuf, sizeof(pbuf), "Ser#: 0x%08lx", 1574 snprintf(pbuf, sizeof(pbuf), "Ser#: 0x%08lx",
1575 mmc_extract_bits(card->cid, 80, 32)); 1575 card_extract_bits(card->cid, 80, 32));
1576 lcd_puts(0, line++, pbuf); 1576 lcd_puts(0, line++, pbuf);
1577 snprintf(pbuf, sizeof(pbuf), "M=%02x, O=%04x", 1577 snprintf(pbuf, sizeof(pbuf), "M=%02x, O=%04x",
1578 (int) mmc_extract_bits(card->cid, 0, 8), 1578 (int) card_extract_bits(card->cid, 0, 8),
1579 (int) mmc_extract_bits(card->cid, 8, 16)); 1579 (int) card_extract_bits(card->cid, 8, 16));
1580 lcd_puts(0, line++, pbuf); 1580 lcd_puts(0, line++, pbuf);
1581 temp = mmc_extract_bits(card->csd, 2, 4); 1581 temp = card_extract_bits(card->csd, 2, 4);
1582 snprintf(pbuf, sizeof(pbuf), "MMC v%s", temp < 5 ? 1582 snprintf(pbuf, sizeof(pbuf), "MMC v%s", temp < 5 ?
1583 spec_vers[temp] : "?.?"); 1583 spec_vers[temp] : "?.?");
1584 lcd_puts(0, line++, pbuf); 1584 lcd_puts(0, line++, pbuf);
1585 snprintf(pbuf, sizeof(pbuf), "Blocks: 0x%06lx", card->numblocks); 1585 snprintf(pbuf, sizeof(pbuf), "Blocks: 0x%06lx", card->numblocks);
1586 lcd_puts(0, line++, pbuf); 1586 lcd_puts(0, line++, pbuf);
1587 snprintf(pbuf, sizeof(pbuf), "Blksz.: %d P:%c%c", card->blocksize, 1587 snprintf(pbuf, sizeof(pbuf), "Blksz.: %d P:%c%c", card->blocksize,
1588 mmc_extract_bits(card->csd, 48, 1) ? 'R' : '-', 1588 card_extract_bits(card->csd, 48, 1) ? 'R' : '-',
1589 mmc_extract_bits(card->csd, 106, 1) ? 'W' : '-'); 1589 card_extract_bits(card->csd, 106, 1) ? 'W' : '-');
1590 lcd_puts(0, line++, pbuf); 1590 lcd_puts(0, line++, pbuf);
1591 } 1591 }
1592 else /* Technical details */ 1592 else /* Technical details */
@@ -1606,12 +1606,12 @@ static bool dbg_mmc_info(void)
1606 snprintf(pbuf, sizeof(pbuf), "R2W: *%d", card->r2w_factor); 1606 snprintf(pbuf, sizeof(pbuf), "R2W: *%d", card->r2w_factor);
1607 lcd_puts(0, line++, pbuf); 1607 lcd_puts(0, line++, pbuf);
1608 snprintf(pbuf, sizeof(pbuf), "IRmax: %d..%d mA", 1608 snprintf(pbuf, sizeof(pbuf), "IRmax: %d..%d mA",
1609 i_vmin[mmc_extract_bits(card->csd, 66, 3)], 1609 i_vmin[card_extract_bits(card->csd, 66, 3)],
1610 i_vmax[mmc_extract_bits(card->csd, 69, 3)]); 1610 i_vmax[card_extract_bits(card->csd, 69, 3)]);
1611 lcd_puts(0, line++, pbuf); 1611 lcd_puts(0, line++, pbuf);
1612 snprintf(pbuf, sizeof(pbuf), "IWmax: %d..%d mA", 1612 snprintf(pbuf, sizeof(pbuf), "IWmax: %d..%d mA",
1613 i_vmin[mmc_extract_bits(card->csd, 72, 3)], 1613 i_vmin[card_extract_bits(card->csd, 72, 3)],
1614 i_vmax[mmc_extract_bits(card->csd, 75, 3)]); 1614 i_vmax[card_extract_bits(card->csd, 75, 3)]);
1615 lcd_puts(0, line++, pbuf); 1615 lcd_puts(0, line++, pbuf);
1616 } 1616 }
1617 } 1617 }
@@ -1642,7 +1642,7 @@ static bool dbg_mmc_info(void)
1642 action_signalscreenchange(); 1642 action_signalscreenchange();
1643 return false; 1643 return false;
1644} 1644}
1645#else /* !HAVE_MMC */ 1645#else /* !defined(HAVE_MMC) && !defined(HAVE_HOTSWAP) */
1646static bool dbg_disk_info(void) 1646static bool dbg_disk_info(void)
1647{ 1647{
1648 char buf[128]; 1648 char buf[128];
@@ -1799,7 +1799,7 @@ static bool dbg_disk_info(void)
1799 action_signalscreenchange(); 1799 action_signalscreenchange();
1800 return false; 1800 return false;
1801} 1801}
1802#endif /* !HAVE_MMC */ 1802#endif /* !defined(HAVE_MMC) && !defined(HAVE_HOTSWAP) */
1803#endif /* !SIMULATOR */ 1803#endif /* !SIMULATOR */
1804 1804
1805#ifdef HAVE_DIRCACHE 1805#ifdef HAVE_DIRCACHE
@@ -2278,8 +2278,10 @@ static const struct the_menu_item menuitems[] = {
2278 { "View partitions", dbg_partitions }, 2278 { "View partitions", dbg_partitions },
2279#endif 2279#endif
2280#ifndef SIMULATOR 2280#ifndef SIMULATOR
2281#ifdef HAVE_MMC 2281#if defined(HAVE_MMC)
2282 { "View MMC info", dbg_mmc_info }, 2282 { "View MMC info", dbg_card_info },
2283#elif defined(HAVE_HOTSWAP)
2284 { "View microSD info", dbg_card_info },
2283#else 2285#else
2284 { "View disk info", dbg_disk_info }, 2286 { "View disk info", dbg_disk_info },
2285#endif 2287#endif
diff --git a/apps/main.c b/apps/main.c
index 3dfab06280..2dd90ef5fe 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -430,7 +430,8 @@ static void init(void)
430 /* enter USB mode early, before trying to mount */ 430 /* enter USB mode early, before trying to mount */
431 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED) 431 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
432#ifdef HAVE_MMC 432#ifdef HAVE_MMC
433 if (!mmc_touched() || (mmc_remove_request() == SYS_MMC_EXTRACTED)) 433 if (!mmc_touched() ||
434 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
434#endif 435#endif
435 { 436 {
436 usb_screen(); 437 usb_screen();
diff --git a/apps/misc.c b/apps/misc.c
index 88ec73e2d3..daa96b006a 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -828,7 +828,8 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
828 if (callback != NULL) 828 if (callback != NULL)
829 callback(parameter); 829 callback(parameter);
830#ifdef HAVE_MMC 830#ifdef HAVE_MMC
831 if (!mmc_touched() || (mmc_remove_request() == SYS_MMC_EXTRACTED)) 831 if (!mmc_touched() ||
832 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
832#endif 833#endif
833 { 834 {
834 scrobbler_flush_cache(); 835 scrobbler_flush_cache();
diff --git a/apps/screens.c b/apps/screens.c
index d8e3121121..aebb7bd469 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -163,8 +163,8 @@ int mmc_remove_request(void)
163 queue_wait_w_tmo(&button_queue, &ev, HZ/2); 163 queue_wait_w_tmo(&button_queue, &ev, HZ/2);
164 switch (ev.id) 164 switch (ev.id)
165 { 165 {
166 case SYS_MMC_EXTRACTED: 166 case SYS_HOTSWAP_EXTRACTED:
167 return SYS_MMC_EXTRACTED; 167 return SYS_HOTSWAP_EXTRACTED;
168 168
169 case SYS_USB_DISCONNECTED: 169 case SYS_USB_DISCONNECTED:
170 return SYS_USB_DISCONNECTED; 170 return SYS_USB_DISCONNECTED;
diff --git a/bootloader/main-pp.c b/bootloader/main-pp.c
index 49d7f0a2f7..dd8b7984ca 100644
--- a/bootloader/main-pp.c
+++ b/bootloader/main-pp.c
@@ -352,7 +352,7 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
352 unsigned long sum; 352 unsigned long sum;
353 353
354 /* Read header to find out how long the mi4 file is. */ 354 /* Read header to find out how long the mi4 file is. */
355 ata_read_sectors(pinfo->start + PPMI_SECTOR_OFFSET, 355 ata_read_sectors(IF_MV2(0,) pinfo->start + PPMI_SECTOR_OFFSET,
356 PPMI_SECTORS, &ppmi_header); 356 PPMI_SECTORS, &ppmi_header);
357 357
358 /* The first four characters at 0x80000 (sector 1024) should be PPMI*/ 358 /* The first four characters at 0x80000 (sector 1024) should be PPMI*/
@@ -362,7 +362,7 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
362 printf("BL mi4 size: %x", ppmi_header.length); 362 printf("BL mi4 size: %x", ppmi_header.length);
363 363
364 /* Read mi4 header of the OF */ 364 /* Read mi4 header of the OF */
365 ata_read_sectors(pinfo->start + PPMI_SECTOR_OFFSET + PPMI_SECTORS 365 ata_read_sectors(IF_MV2(0,) pinfo->start + PPMI_SECTOR_OFFSET + PPMI_SECTORS
366 + (ppmi_header.length/512), MI4_HEADER_SECTORS, &mi4header); 366 + (ppmi_header.length/512), MI4_HEADER_SECTORS, &mi4header);
367 367
368 /* We don't support encrypted mi4 files yet */ 368 /* We don't support encrypted mi4 files yet */
@@ -385,7 +385,7 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
385 printf("Binary type: %.4s", mi4header.type); 385 printf("Binary type: %.4s", mi4header.type);
386 386
387 /* Load firmware */ 387 /* Load firmware */
388 ata_read_sectors(pinfo->start + PPMI_SECTOR_OFFSET + PPMI_SECTORS 388 ata_read_sectors(IF_MV2(0,) pinfo->start + PPMI_SECTOR_OFFSET + PPMI_SECTORS
389 + (ppmi_header.length/512) + MI4_HEADER_SECTORS, 389 + (ppmi_header.length/512) + MI4_HEADER_SECTORS,
390 (mi4header.mi4size-MI4_HEADER_SIZE)/512, buf); 390 (mi4header.mi4size-MI4_HEADER_SIZE)/512, buf);
391 391
@@ -404,7 +404,7 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
404 unsigned int i; 404 unsigned int i;
405 /* check which known version we have */ 405 /* check which known version we have */
406 /* These are taken from the PPPS section, 0x00780240 */ 406 /* These are taken from the PPPS section, 0x00780240 */
407 ata_read_sectors(pinfo->start + 0x3C01, 1, block); 407 ata_read_sectors(IF_MV2(0,) pinfo->start + 0x3C01, 1, block);
408 for (i=0; i<sizeof(OFDatabaseOffsets)/sizeof(*OFDatabaseOffsets); i++) 408 for (i=0; i<sizeof(OFDatabaseOffsets)/sizeof(*OFDatabaseOffsets); i++)
409 { 409 {
410 if (!memcmp(&block[0x40], OFDatabaseOffsets[i].version, 410 if (!memcmp(&block[0x40], OFDatabaseOffsets[i].version,
@@ -417,9 +417,9 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
417 } 417 }
418 if (sector && offset) 418 if (sector && offset)
419 { 419 {
420 ata_read_sectors(sector, 1, block); 420 ata_read_sectors(IF_MV2(0,) sector, 1, block);
421 block[offset] = 0; 421 block[offset] = 0;
422 ata_write_sectors(sector, 1, block); 422 ata_write_sectors(IF_MV2(0,) sector, 1, block);
423 } 423 }
424 } 424 }
425 return EOK; 425 return EOK;
@@ -428,12 +428,14 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
428 428
429void* main(void) 429void* main(void)
430{ 430{
431#ifndef SANSA_E200
431 char buf[256]; 432 char buf[256];
433 unsigned short* identify_info;
434#endif
432 int i; 435 int i;
433 int btn; 436 int btn;
434 int rc; 437 int rc;
435 int num_partitions; 438 int num_partitions;
436 unsigned short* identify_info;
437 struct partinfo* pinfo; 439 struct partinfo* pinfo;
438#ifdef SANSA_E200 440#ifdef SANSA_E200
439 int usb_retry = 0; 441 int usb_retry = 0;
@@ -475,6 +477,7 @@ void* main(void)
475 printf(MODEL_NAME); 477 printf(MODEL_NAME);
476 478
477 i=ata_init(); 479 i=ata_init();
480#ifndef SANSA_E200
478 if (i==0) { 481 if (i==0) {
479 identify_info=ata_get_identify(); 482 identify_info=ata_get_identify();
480 /* Show model */ 483 /* Show model */
@@ -489,8 +492,9 @@ void* main(void)
489 } else { 492 } else {
490 error(EATA, i); 493 error(EATA, i);
491 } 494 }
495#endif
492 496
493 disk_init(); 497 disk_init(IF_MV(0));
494 num_partitions = disk_mount_all(); 498 num_partitions = disk_mount_all();
495 if (num_partitions<=0) 499 if (num_partitions<=0)
496 { 500 {
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 28ef38e8db..2a7bea3e9f 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -116,6 +116,9 @@ drivers/ata.c
116#endif /* HAVE_FLASH_DISK */ 116#endif /* HAVE_FLASH_DISK */
117#endif /* HAVE_MMC */ 117#endif /* HAVE_MMC */
118drivers/fat.c 118drivers/fat.c
119#ifdef HAVE_HOTSWAP
120hotswap.c
121#endif
119#endif /* SIMULATOR */ 122#endif /* SIMULATOR */
120 123
121/* EEPROM */ 124/* EEPROM */
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index bc44a53b70..0f46652b3c 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -37,6 +37,9 @@ static DIR opendirs[MAX_OPEN_DIRS];
37#ifdef HAVE_MMC 37#ifdef HAVE_MMC
38static const char* vol_names = "<MMC%d>"; 38static const char* vol_names = "<MMC%d>";
39#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */ 39#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */
40#elif defined(HAVE_HOTSWAP)
41static const char* vol_names = "<microSD%d>";
42#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */
40#else 43#else
41static const char* vol_names = "<HD%d>"; 44static const char* vol_names = "<HD%d>";
42#define VOL_ENUM_POS 3 45#define VOL_ENUM_POS 3
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index ebf8103aa0..f491c9b26a 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -20,8 +20,8 @@
20#include "ata.h" 20#include "ata.h"
21#include "debug.h" 21#include "debug.h"
22#include "fat.h" 22#include "fat.h"
23#ifdef HAVE_MMC 23#ifdef HAVE_HOTSWAP
24#include "ata_mmc.h" 24#include "hotswap.h"
25#endif 25#endif
26#include "file.h" /* for release_dirs() */ 26#include "file.h" /* for release_dirs() */
27#include "dir.h" /* for release_files() */ 27#include "dir.h" /* for release_files() */
@@ -101,8 +101,8 @@ int disk_mount_all(void)
101 int mounted; 101 int mounted;
102 int i; 102 int i;
103 103
104#if defined(HAVE_MMC) && defined(HAVE_HOTSWAP) 104#ifdef HAVE_MMC
105 mmc_enable_monitoring(false); 105 card_enable_monitoring(false);
106#endif 106#endif
107 107
108 fat_init(); /* reset all mounted partitions */ 108 fat_init(); /* reset all mounted partitions */
@@ -110,13 +110,13 @@ int disk_mount_all(void)
110 vol_drive[i] = -1; /* mark all as unassigned */ 110 vol_drive[i] = -1; /* mark all as unassigned */
111 111
112 mounted = disk_mount(0); 112 mounted = disk_mount(0);
113#ifdef HAVE_MMC 113#ifdef HAVE_HOTSWAP
114 if (mmc_detect()) /* for Ondio, only if card detected */ 114 if (card_detect())
115 { 115 {
116 mounted += disk_mount(1); /* try 2nd "drive", too */ 116 mounted += disk_mount(1); /* try 2nd "drive", too */
117 } 117 }
118#ifdef HAVE_HOTSWAP 118#ifdef HAVE_MMC
119 mmc_enable_monitoring(true); 119 card_enable_monitoring(true);
120#endif 120#endif
121#endif 121#endif
122 122
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index 847e282e3b..66e60ead1d 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -397,26 +397,6 @@ static int receive_cxd(unsigned char *buf)
397 return 0; 397 return 0;
398} 398}
399 399
400/* helper function to extract n (<=32) bits from an arbitrary position.
401 counting from MSB to LSB */
402unsigned long mmc_extract_bits(
403 const unsigned long *p, /* the start of the bitfield array */
404 unsigned int start, /* bit no. to start reading */
405 unsigned int size) /* how many bits to read */
406{
407 unsigned int long_index = start / 32;
408 unsigned int bit_index = start % 32;
409 unsigned long result;
410
411 result = p[long_index] << bit_index;
412
413 if (bit_index + size > 32) /* crossing longword boundary */
414 result |= p[long_index+1] >> (32 - bit_index);
415
416 result >>= 32 - size;
417
418 return result;
419}
420 400
421static int initialize_card(int card_no) 401static int initialize_card(int card_no)
422{ 402{
@@ -470,9 +450,9 @@ static int initialize_card(int card_no)
470 return rc * 10 - 6; 450 return rc * 10 - 6;
471 451
472 /* check block sizes */ 452 /* check block sizes */
473 card->block_exp = mmc_extract_bits(card->csd, 44, 4); 453 card->block_exp = card_extract_bits(card->csd, 44, 4);
474 card->blocksize = 1 << card->block_exp; 454 card->blocksize = 1 << card->block_exp;
475 if ((mmc_extract_bits(card->csd, 102, 4) != card->block_exp) 455 if ((card_extract_bits(card->csd, 102, 4) != card->block_exp)
476 || card->blocksize > MAX_BLOCK_SIZE) 456 || card->blocksize > MAX_BLOCK_SIZE)
477 { 457 {
478 return -7; 458 return -7;
@@ -486,16 +466,16 @@ static int initialize_card(int card_no)
486 } 466 }
487 467
488 /* max transmission speed, clock divider */ 468 /* max transmission speed, clock divider */
489 temp = mmc_extract_bits(card->csd, 29, 3); 469 temp = card_extract_bits(card->csd, 29, 3);
490 temp = (temp > 3) ? 3 : temp; 470 temp = (temp > 3) ? 3 : temp;
491 card->speed = mantissa[mmc_extract_bits(card->csd, 25, 4)] 471 card->speed = mantissa[card_extract_bits(card->csd, 25, 4)]
492 * exponent[temp + 4]; 472 * exponent[temp + 4];
493 card->bitrate_register = (FREQ/4-1) / card->speed; 473 card->bitrate_register = (FREQ/4-1) / card->speed;
494 474
495 /* NSAC, TSAC, read timeout */ 475 /* NSAC, TSAC, read timeout */
496 card->nsac = 100 * mmc_extract_bits(card->csd, 16, 8); 476 card->nsac = 100 * card_extract_bits(card->csd, 16, 8);
497 card->tsac = mantissa[mmc_extract_bits(card->csd, 9, 4)]; 477 card->tsac = mantissa[card_extract_bits(card->csd, 9, 4)];
498 temp = mmc_extract_bits(card->csd, 13, 3); 478 temp = card_extract_bits(card->csd, 13, 3);
499 card->read_timeout = ((FREQ/4) / (card->bitrate_register + 1) 479 card->read_timeout = ((FREQ/4) / (card->bitrate_register + 1)
500 * card->tsac / exponent[9 - temp] 480 * card->tsac / exponent[9 - temp]
501 + (10 * card->nsac)); 481 + (10 * card->nsac));
@@ -503,7 +483,7 @@ static int initialize_card(int card_no)
503 card->tsac = card->tsac * exponent[temp] / 10; 483 card->tsac = card->tsac * exponent[temp] / 10;
504 484
505 /* r2w_factor, write timeout */ 485 /* r2w_factor, write timeout */
506 card->r2w_factor = 1 << mmc_extract_bits(card->csd, 99, 3); 486 card->r2w_factor = 1 << card_extract_bits(card->csd, 99, 3);
507 if (card->r2w_factor > 32) /* dirty MMC spec violation */ 487 if (card->r2w_factor > 32) /* dirty MMC spec violation */
508 { 488 {
509 card->read_timeout *= 4; /* add safety factor */ 489 card->read_timeout *= 4; /* add safety factor */
@@ -513,8 +493,8 @@ static int initialize_card(int card_no)
513 card->write_timeout = card->read_timeout * card->r2w_factor; 493 card->write_timeout = card->read_timeout * card->r2w_factor;
514 494
515 /* card size */ 495 /* card size */
516 card->numblocks = (mmc_extract_bits(card->csd, 54, 12) + 1) 496 card->numblocks = (card_extract_bits(card->csd, 54, 12) + 1)
517 * (1 << (mmc_extract_bits(card->csd, 78, 3) + 2)); 497 * (1 << (card_extract_bits(card->csd, 78, 3) + 2));
518 card->size = card->numblocks * card->blocksize; 498 card->size = card->numblocks * card->blocksize;
519 499
520 /* switch to full speed */ 500 /* switch to full speed */
@@ -993,12 +973,12 @@ static void mmc_thread(void)
993 break; 973 break;
994 974
995#ifdef HAVE_HOTSWAP 975#ifdef HAVE_HOTSWAP
996 case SYS_MMC_INSERTED: 976 case SYS_HOTSWAP_INSERTED:
997 disk_mount(1); /* mount MMC */ 977 disk_mount(1); /* mount MMC */
998 queue_broadcast(SYS_FS_CHANGED, 0); 978 queue_broadcast(SYS_FS_CHANGED, 0);
999 break; 979 break;
1000 980
1001 case SYS_MMC_EXTRACTED: 981 case SYS_HOTSWAP_EXTRACTED:
1002 disk_unmount(1); /* release "by force" */ 982 disk_unmount(1); /* release "by force" */
1003 queue_broadcast(SYS_FS_CHANGED, 0); 983 queue_broadcast(SYS_FS_CHANGED, 0);
1004 break; 984 break;
@@ -1097,11 +1077,11 @@ static void mmc_tick(void)
1097 { 1077 {
1098 if (current_status) 1078 if (current_status)
1099 { 1079 {
1100 queue_broadcast(SYS_MMC_INSERTED, 0); 1080 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
1101 } 1081 }
1102 else 1082 else
1103 { 1083 {
1104 queue_broadcast(SYS_MMC_EXTRACTED, 0); 1084 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
1105 mmc_status = MMC_UNTOUCHED; 1085 mmc_status = MMC_UNTOUCHED;
1106 card_info[1].initialized = false; 1086 card_info[1].initialized = false;
1107 } 1087 }
diff --git a/firmware/export/ata_mmc.h b/firmware/export/ata_mmc.h
index a4e9f71f09..2361c439b5 100644
--- a/firmware/export/ata_mmc.h
+++ b/firmware/export/ata_mmc.h
@@ -18,34 +18,14 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19#ifndef __ATA_MMC_H__ 19#ifndef __ATA_MMC_H__
20#define __ATA_MMC_H__ 20#define __ATA_MMC_H__
21 21#include "hotswap.h"
22typedef struct
23{
24 bool initialized;
25 unsigned char bitrate_register;
26 unsigned long read_timeout; /* n * 8 clock cycles */
27 unsigned long write_timeout; /* n * 8 clock cycles */
28
29 unsigned long ocr; /* OCR register */
30 unsigned long csd[4]; /* CSD register, 16 bytes */
31 unsigned long cid[4]; /* CID register, 16 bytes */
32 unsigned long speed; /* bit/s */
33 unsigned int nsac; /* clock cycles */
34 unsigned long tsac; /* n * 0.1 ns */
35 unsigned int r2w_factor;
36 unsigned long size; /* size in bytes */
37 unsigned long numblocks; /* size in flash blocks */
38 unsigned int blocksize; /* block size in bytes */
39 unsigned int block_exp; /* block size exponent */
40} tCardInfo;
41 22
42void mmc_enable_int_flash_clock(bool on); 23void mmc_enable_int_flash_clock(bool on);
43bool mmc_detect(void); 24bool mmc_detect(void);
44unsigned long mmc_extract_bits(const unsigned long *p, unsigned int start,
45 unsigned int size);
46tCardInfo *mmc_card_info(int card_no); 25tCardInfo *mmc_card_info(int card_no);
47bool mmc_touched(void); 26bool mmc_touched(void);
48bool mmc_usb_active(int delayticks); 27bool mmc_usb_active(int delayticks);
28
49#ifdef HAVE_HOTSWAP 29#ifdef HAVE_HOTSWAP
50void mmc_enable_monitoring(bool on); 30void mmc_enable_monitoring(bool on);
51#endif 31#endif
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h
index 71b1270749..f9708697dc 100644
--- a/firmware/export/config-e200.h
+++ b/firmware/export/config-e200.h
@@ -33,6 +33,11 @@
33/* define this if you have LCD enable function */ 33/* define this if you have LCD enable function */
34#define HAVE_LCD_ENABLE 34#define HAVE_LCD_ENABLE
35 35
36#ifndef SIMULATOR
37#define HAVE_HOTSWAP
38#define HAVE_MULTIVOLUME
39#endif
40
36#define HAVE_BACKLIGHT_BRIGHTNESS 41#define HAVE_BACKLIGHT_BRIGHTNESS
37/* Main LCD backlight brightness range and defaults */ 42/* Main LCD backlight brightness range and defaults */
38#define MIN_BRIGHTNESS_SETTING 1 43#define MIN_BRIGHTNESS_SETTING 1
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 4652359e62..ffcbf688ea 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -247,7 +247,7 @@
247/* Enable the directory cache and tagcache in RAM if we have 247/* Enable the directory cache and tagcache in RAM if we have
248 * plenty of RAM. Both features can be enabled independently. */ 248 * plenty of RAM. Both features can be enabled independently. */
249#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \ 249#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \
250 !defined(BOOTLOADER) 250 !defined(BOOTLOADER) && !defined(SANSA_E200)
251#define HAVE_DIRCACHE 251#define HAVE_DIRCACHE
252#ifdef HAVE_TAGCACHE 252#ifdef HAVE_TAGCACHE
253#define HAVE_TC_RAMCACHE 253#define HAVE_TC_RAMCACHE
diff --git a/firmware/export/hotswap.h b/firmware/export/hotswap.h
new file mode 100644
index 0000000000..c6a657d731
--- /dev/null
+++ b/firmware/export/hotswap.h
@@ -0,0 +1,59 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef __HOTSWAP_H__
20#define __HOTSWAP_H__
21
22typedef struct
23{
24 bool initialized;
25 unsigned char bitrate_register;
26 unsigned long read_timeout; /* n * 8 clock cycles */
27 unsigned long write_timeout; /* n * 8 clock cycles */
28
29 unsigned long ocr; /* OCR register */
30 unsigned long csd[4]; /* CSD register, 16 bytes */
31 unsigned long cid[4]; /* CID register, 16 bytes */
32 unsigned long speed; /* bit/s */
33 unsigned int nsac; /* clock cycles */
34 unsigned long tsac; /* n * 0.1 ns */
35 unsigned int r2w_factor;
36 unsigned long size; /* size in bytes */
37 unsigned long numblocks; /* size in flash blocks */
38 unsigned int blocksize; /* block size in bytes */
39 unsigned int block_exp; /* block size exponent */
40} tCardInfo;
41
42#ifdef TARGET_TREE
43bool card_detect(void);
44tCardInfo *card_get_info(int card_no);
45#else /* HAVE_MMC */
46#include "ata_mmc.h"
47#define card_detect mmc_detect
48#define card_get_info mmc_card_info
49#define card_touched mmc_touched
50#define card_enable_monitoring mmc_enable_monitoring
51#endif
52
53/* helper function to extract n (<=32) bits from an arbitrary position.
54 counting from MSB to LSB */
55unsigned long card_extract_bits(
56 const unsigned long *p, /* the start of the bitfield array */
57 unsigned int start, /* bit no. to start reading */
58 unsigned int size); /* how many bits to read */
59#endif
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h
index 9e3a8d25df..d5898a97f1 100644
--- a/firmware/export/kernel.h
+++ b/firmware/export/kernel.h
@@ -41,8 +41,8 @@
41#define SYS_USB_DISCONNECTED ((SYS_EVENT | ((long)3 << 27))) 41#define SYS_USB_DISCONNECTED ((SYS_EVENT | ((long)3 << 27)))
42#define SYS_USB_DISCONNECTED_ACK ((SYS_EVENT | ((long)4 << 27))) 42#define SYS_USB_DISCONNECTED_ACK ((SYS_EVENT | ((long)4 << 27)))
43#define SYS_TIMEOUT ((SYS_EVENT | ((long)5 << 27))) 43#define SYS_TIMEOUT ((SYS_EVENT | ((long)5 << 27)))
44#define SYS_MMC_INSERTED ((SYS_EVENT | ((long)6 << 27))) 44#define SYS_HOTSWAP_INSERTED ((SYS_EVENT | ((long)6 << 27)))
45#define SYS_MMC_EXTRACTED ((SYS_EVENT | ((long)7 << 27))) 45#define SYS_HOTSWAP_EXTRACTED ((SYS_EVENT | ((long)7 << 27)))
46#define SYS_POWEROFF ((SYS_EVENT | ((long)8 << 27))) 46#define SYS_POWEROFF ((SYS_EVENT | ((long)8 << 27)))
47#define SYS_FS_CHANGED ((SYS_EVENT | ((long)9 << 27))) 47#define SYS_FS_CHANGED ((SYS_EVENT | ((long)9 << 27)))
48#define SYS_CHARGER_CONNECTED ((SYS_EVENT | ((long)10 << 27))) 48#define SYS_CHARGER_CONNECTED ((SYS_EVENT | ((long)10 << 27)))
diff --git a/firmware/export/pp5024.h b/firmware/export/pp5024.h
index e7758b9ce5..5e2de17741 100644
--- a/firmware/export/pp5024.h
+++ b/firmware/export/pp5024.h
@@ -24,7 +24,7 @@
24#include "pp5020.h" 24#include "pp5020.h"
25 25
26#undef GPIO_IRQ 26#undef GPIO_IRQ
27/* Ports A, ?? */ 27/* Ports A, B, ?? */
28#define GPIO0_IRQ (32+0) 28#define GPIO0_IRQ (32+0)
29/* Ports F, H, ?? */ 29/* Ports F, H, ?? */
30#define GPIO1_IRQ (32+1) 30#define GPIO1_IRQ (32+1)
diff --git a/firmware/hotswap.c b/firmware/hotswap.c
new file mode 100644
index 0000000000..5620edf10b
--- /dev/null
+++ b/firmware/hotswap.c
@@ -0,0 +1,58 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include <stdbool.h>
20#include "config.h"
21#ifdef TARGET_TREE
22#include "hotswap-target.h"
23#else
24#include "ata_mmc.h"
25#endif
26
27/* helper function to extract n (<=32) bits from an arbitrary position.
28 counting from MSB to LSB */
29unsigned long card_extract_bits(
30 const unsigned long *p, /* the start of the bitfield array */
31 unsigned int start, /* bit no. to start reading */
32 unsigned int size) /* how many bits to read */
33{
34 unsigned int long_index = start / 32;
35 unsigned int bit_index = start % 32;
36 unsigned long result;
37
38 result = p[long_index] << bit_index;
39
40 if (bit_index + size > 32) /* crossing longword boundary */
41 result |= p[long_index+1] >> (32 - bit_index);
42
43 result >>= 32 - size;
44
45 return result;
46}
47
48#ifdef TARGET_TREE
49bool card_detect(void)
50{
51 return card_detect_target();
52}
53
54tCardInfo *card_get_info(int card_no)
55{
56 return card_get_info_target(card_no);
57}
58#endif
diff --git a/firmware/include/dir.h b/firmware/include/dir.h
index c354082bec..020b24a502 100644
--- a/firmware/include/dir.h
+++ b/firmware/include/dir.h
@@ -71,6 +71,10 @@ typedef struct {
71#endif 71#endif
72} DIR; 72} DIR;
73 73
74#ifdef HAVE_HOTSWAP
75char *get_volume_name(int volume);
76#endif
77
74#ifndef DIRFUNCTIONS_DEFINED 78#ifndef DIRFUNCTIONS_DEFINED
75 79
76extern DIR* opendir(const char* name); 80extern DIR* opendir(const char* name);
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
index 8eccdfb729..fea6773ac9 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
@@ -17,14 +17,16 @@
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "ata.h" 19#include "ata.h"
20#include "hotswap-target.h"
20#include "ata-target.h" 21#include "ata-target.h"
21#include "ata_idle_notify.h" 22#include "ata_idle_notify.h"
22#include "system.h" 23#include "system.h"
23#include <string.h> 24#include <string.h>
24#include "thread.h" 25#include "thread.h"
26#include "led.h"
27#include "disk.h"
25#include "pp5024.h" 28#include "pp5024.h"
26 29#include "panic.h"
27#define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */
28 30
29#define BLOCK_SIZE (512) 31#define BLOCK_SIZE (512)
30#define SECTOR_SIZE (512) 32#define SECTOR_SIZE (512)
@@ -48,6 +50,7 @@
48#define DATA_DONE (1 << 12) 50#define DATA_DONE (1 << 12)
49#define CMD_DONE (1 << 13) 51#define CMD_DONE (1 << 13)
50#define ERROR_BITS (0x3f) 52#define ERROR_BITS (0x3f)
53#define READY_FOR_DATA (1 << 8)
51#define FIFO_FULL (1 << 7) 54#define FIFO_FULL (1 << 7)
52#define FIFO_EMPTY (1 << 6) 55#define FIFO_EMPTY (1 << 6)
53 56
@@ -65,370 +68,481 @@
65#define FIFO_SIZE 16 /* FIFO is 16 words deep */ 68#define FIFO_SIZE 16 /* FIFO is 16 words deep */
66 69
67/* SD Commands */ 70/* SD Commands */
68#define GO_IDLE_STATE 0 71#define GO_IDLE_STATE 0
69#define ALL_SEND_CID 2 72#define ALL_SEND_CID 2
70#define SEND_RELATIVE_ADDR 3 73#define SEND_RELATIVE_ADDR 3
71#define SET_DSR 4 74#define SET_DSR 4
72#define SWITCH_FUNC 6 75#define SWITCH_FUNC 6
73#define SELECT_CARD 7 76#define SELECT_CARD 7
74#define DESELECT_CARD 7 77#define DESELECT_CARD 7
75#define SEND_CSD 9 78#define SEND_CSD 9
76#define SEND_CID 10 79#define SEND_CID 10
77#define STOP_TRANSMISSION 12 80#define STOP_TRANSMISSION 12
78#define SEND_STATUS 13 81#define SEND_STATUS 13
79#define GO_INACTIVE_STATE 15 82#define GO_INACTIVE_STATE 15
80#define SET_BLOCKLEN 16 83#define SET_BLOCKLEN 16
81#define READ_SINGLE_BLOCK 17 84#define READ_SINGLE_BLOCK 17
82#define READ_MULTIPLE_BLOCK 18 85#define READ_MULTIPLE_BLOCK 18
83#define WRITE_BLOCK 24 86#define SEND_NUM_WR_BLOCKS 22
84#define WRITE_MULTIPLE_BLOCK 25 87#define WRITE_BLOCK 24
85#define ERASE_WR_BLK_START 32 88#define WRITE_MULTIPLE_BLOCK 25
86#define ERASE_WR_BLK_END 33 89#define ERASE_WR_BLK_START 32
87#define ERASE 38 90#define ERASE_WR_BLK_END 33
91#define ERASE 38
92#define APP_CMD 55
93
94#define EC_POWER_UP 1 /* error code */
95#define EC_READ_TIMEOUT 2 /* error code */
96#define EC_WRITE_TIMEOUT 3 /* error code */
97#define EC_TRAN_SEL_BANK 4 /* error code */
98#define EC_TRAN_READ_ENTRY 5 /* error code */
99#define EC_TRAN_READ_EXIT 6 /* error code */
100#define EC_TRAN_WRITE_ENTRY 7 /* error code */
101#define EC_TRAN_WRITE_EXIT 8 /* error code */
102#define DO_PANIC 32 /* marker */
103#define NO_PANIC 0 /* marker */
104#define EC_COMMAND 10 /* error code */
105#define EC_FIFO_SEL_BANK_EMPTY 11 /* error code */
106#define EC_FIFO_SEL_BANK_DONE 12 /* error code */
107#define EC_FIFO_ENA_BANK_EMPTY 13 /* error code */
108#define EC_FIFO_READ_FULL 14 /* error code */
109#define EC_FIFO_WR_EMPTY 15 /* error code */
110#define EC_FIFO_WR_DONE 16 /* error code */
88 111
89/* Application Specific commands */ 112/* Application Specific commands */
90#define SET_BUS_WIDTH 6 113#define SET_BUS_WIDTH 6
91#define SD_APP_OP_COND 41 114#define SD_APP_OP_COND 41
92 115
93#define READ_TIMEOUT 5*HZ 116/* for compatibility */
94#define WRITE_TIMEOUT 0.5*HZ
95
96static unsigned short identify_info[SECTOR_SIZE];
97int ata_spinup_time = 0; 117int ata_spinup_time = 0;
118
98long last_disk_activity = -1; 119long last_disk_activity = -1;
99static bool initialized = false;
100 120
101static unsigned char current_bank = 0; /* The bank that we are working with */ 121static bool initialized = false;
122static int sd1_status = 0x00; /* 0x00:inserted, 0x80:not inserted */
102 123
103static tSDCardInfo card_info[2]; 124static tSDCardInfo card_info[2];
125static tSDCardInfo *currcard; /* current active card */
104 126
105/* For multi volume support */ 127/* Shoot for around 75% usage */
106static int current_card = 0; 128static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
107 129static const char sd_thread_name[] = "ata/sd";
108static struct mutex sd_mtx; 130static struct mutex sd_mtx;
109
110static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x800)/sizeof(long)];
111
112static const char sd_thread_name[] = "sd";
113static struct event_queue sd_queue; 131static struct event_queue sd_queue;
114 132
133/* Posted when card plugged status has changed */
134#define SD_HOTSWAP 1
115 135
116/* Private Functions */ 136/* Private Functions */
117 137
118bool sd_send_command(unsigned int cmd, unsigned long arg1, unsigned int arg2) 138static unsigned int check_time[10];
139
140static inline void sd_check_timeout(unsigned int timeout, int id)
119{ 141{
120 bool result = false; 142 if (USEC_TIMER > check_time[id] + timeout)
121 do 143 panicf("Error SDCard: %d", id);
144}
145
146static inline bool sd_poll_status(unsigned int trigger, unsigned int timeout,
147 int id)
148{
149 unsigned int t = USEC_TIMER;
150
151 while ((STATUS_REG & trigger) == 0)
122 { 152 {
123 CMD_REG0 = cmd; 153 if (USEC_TIMER > t + timeout)
124 CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16);
125 CMD_REG2 = (unsigned int)((arg1 & 0xffff));
126 UNKNOWN = arg2;
127 while ((STATUS_REG & CMD_DONE) == 0)
128 { 154 {
129 /* Busy wait */ 155 if(id & DO_PANIC)
156 panicf("Error SDCard: %d", id & 31);
157
158 return false;
130 } 159 }
131 if ((STATUS_REG & ERROR_BITS) == 0) 160 }
132 { 161
133 result = true; 162 return true;
134 }
135 } while ((STATUS_REG & ERROR_BITS) != 0);
136 return result;
137} 163}
138 164
139void sd_read_response(unsigned int *response, int type) 165static bool sd_command(unsigned int cmd, unsigned long arg1,
166 unsigned int *response, unsigned int type)
140{ 167{
141 int i; 168 int i, words; /* Number of 16 bit words to read from RESPONSE_REG */
142 int words; /* Number of 16 bit words to read from RESPONSE_REG */ 169 unsigned int data[9];
143 unsigned int response_from_card[9]; 170
144 if(type == 2) 171 while (1)
145 { 172 {
146 words = 9; /* R2 types are 8.5 16-bit words long */ 173 CMD_REG0 = cmd;
147 } else { 174 CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16);
148 words = 3; 175 CMD_REG2 = (unsigned int)((arg1 & 0xffff));
176 UNKNOWN = type;
177
178 sd_poll_status(CMD_DONE, 100000, EC_COMMAND | DO_PANIC);
179
180 if ((STATUS_REG & ERROR_BITS) == 0)
181 break;
182
183 priority_yield();
149 } 184 }
150 185
186 if (cmd == GO_IDLE_STATE) return true; /* no response here */
187
188 words = (type == 2) ? 9 : 3;
189
151 for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */ 190 for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */
152 { 191 {
153 response_from_card[i] = RESPONSE_REG; /* Read most significant 16-bit word */ 192 data[i] = RESPONSE_REG; /* Read most significant 16-bit word */
154 } 193 }
155 194
156 switch (type) 195 if (type == 2)
157 { 196 {
158 case 1: 197 /* Response type 2 has the following structure:
159 /* Response type 1 has the following structure: 198 * [135:135] Start Bit - '0'
160 Start bit 199 * [134:134] Transmission bit - '0'
161 Transmission bit 200 * [133:128] Reserved - '111111'
162 Command index (6 bits) 201 * [127:001] CID or CSD register including internal CRC7
163 Card Status (32 bits) 202 * [000:000] End Bit - '1'
164 CRC7 (7 bits) 203 */
165 Stop bit 204 response[3] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8);
166 */ 205 response[2] = (data[2]<<24) + (data[3]<<8) + ((data[4]&0xff00)>>8);
167 /* TODO: Sanity checks */ 206 response[1] = (data[4]<<24) + (data[5]<<8) + ((data[6]&0xff00)>>8);
168 response[0] = ((response_from_card[0] & 0xff) << 24) 207 response[0] = (data[6]<<24) + (data[7]<<8) + ((data[8]&0xff00)>>8);
169 + (response_from_card[1] << 8) 208 }
170 + ((response_from_card[2] & 0xff00) >> 8); 209 else
171 break; 210 {
172 case 2: 211 /* Response types 1, 1b, 3, 6 have the following structure:
173 /* Response type 2 has the following structure: 212 * Types 4 and 5 are not supported.
174 Start bit 213 *
175 Transmission bit 214 * [47] Start bit - '0'
176 Reserved (6 bits) 215 * [46] Transmission bit - '0'
177 CSD/CID register (127 bits) 216 * [45:40] R1, R1b, R6: Command index
178 Stop bit 217 * R3: Reserved - '111111'
179 */ 218 * [39:8] R1, R1b: Card Status
180 response[3] = ((response_from_card[0]&0xff)<<24) + 219 * R3: OCR Register
181 (response_from_card[1]<<8) + 220 * R6: [31:16] RCA
182 ((response_from_card[2]&0xff00)>>8); 221 * [15: 0] Card Status Bits 23, 22, 19, 12:0
183 response[2] = ((response_from_card[2]&0xff)<<24) + 222 * [23] COM_CRC_ERROR
184 (response_from_card[3]<<8) + 223 * [22] ILLEGAL_COMMAND
185 ((response_from_card[4]&0xff00)>>8); 224 * [19] ERROR
186 response[1] = ((response_from_card[4]&0xff)<<24) + 225 * [12:9] CURRENT_STATE
187 (response_from_card[5]<<8) + 226 * [8] READY_FOR_DATA
188 ((response_from_card[6]&0xff00)>>8); 227 * [7:6]
189 response[0] = ((response_from_card[6]&0xff)<<24) + 228 * [5] APP_CMD
190 (response_from_card[7]<<8) + 229 * [4]
191 ((response_from_card[8]&0xff00)>>8); 230 * [3] AKE_SEQ_ERROR
192 break; 231 * [2] Reserved
193 case 3: 232 * [1:0] Reserved for test mode
194 /* Response type 3 has the following structure: 233 * [7:1] R1, R1b: CRC7
195 Start bit 234 * R3: Reserved - '1111111'
196 Transmission bit 235 * [0] End Bit - '1'
197 Reserved (6 bits) 236 */
198 OCR register (32 bits) 237 response[0] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8);
199 Reserved (7 bits)
200 Stop bit
201 */
202 response[0] = ((response_from_card[0] & 0xff) << 24)
203 + (response_from_card[1] << 8)
204 + ((response_from_card[2] & 0xff00) >> 8);
205 /* Types 4-6 not supported yet */
206 } 238 }
207}
208 239
209bool sd_send_acommand(unsigned int cmd, unsigned long arg1, unsigned int arg2)
210{
211 unsigned int returncode;
212 if (sd_send_command(55, (card_info[current_card].rca)<<16, 1) == false)
213 return false;
214 sd_read_response(&returncode, 1);
215 if (sd_send_command(cmd, arg1, arg2) == false)
216 return false;
217 return true; 240 return true;
218} 241}
219 242
220void sd_wait_for_state(tSDCardInfo* card, unsigned int state) 243static void sd_wait_for_state(unsigned int state, unsigned int id)
221{ 244{
222 unsigned int response = 0; 245 unsigned int response = 0;
223 while(((response >> 9) & 0xf) != state) 246
247 check_time[id] = USEC_TIMER;
248
249 while (1)
224 { 250 {
225 sd_send_command(SEND_STATUS, (card->rca) << 16, 1); 251 sd_command(SEND_STATUS, currcard->rca, &response, 1);
252 sd_check_timeout(0x80000, id);
253
254 if (((response >> 9) & 0xf) == state)
255 break;
256
226 priority_yield(); 257 priority_yield();
227 sd_read_response(&response, 1);
228 /* TODO: Add a timeout and error handling */
229 } 258 }
259
230 SD_STATE_REG = state; 260 SD_STATE_REG = state;
231} 261}
232 262
233 263static inline void copy_read_sectors_fast(unsigned char **buf)
234STATICIRAM void copy_read_sectors(unsigned char* buf, int wordcount)
235 NOINLINE_ATTR ICODE_ATTR;
236
237STATICIRAM void copy_read_sectors(unsigned char* buf, int wordcount)
238{ 264{
239 unsigned int tmp = 0; 265 /* Copy one chunk of 16 words using best method for start alignment */
240 266 switch ( (intptr_t)*buf & 3 )
241 if ( (unsigned long)buf & 1) 267 {
242 { /* not 16-bit aligned, copy byte by byte */ 268 case 0:
243 unsigned char* bufend = buf + wordcount*2; 269 asm volatile (
244 do 270 "ldmia %[data], { r2-r9 } \r\n"
245 { 271 "orr r2, r2, r3, lsl #16 \r\n"
246 tmp = DATA_REG; 272 "orr r4, r4, r5, lsl #16 \r\n"
247 *buf++ = tmp & 0xff; 273 "orr r6, r6, r7, lsl #16 \r\n"
248 *buf++ = tmp >> 8; 274 "orr r8, r8, r9, lsl #16 \r\n"
249 } while (buf < bufend); /* tail loop is faster */ 275 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
250 } 276 "ldmia %[data], { r2-r9 } \r\n"
251 else 277 "orr r2, r2, r3, lsl #16 \r\n"
252 { /* 16-bit aligned, can do faster copy */ 278 "orr r4, r4, r5, lsl #16 \r\n"
253 unsigned short* wbuf = (unsigned short*)buf; 279 "orr r6, r6, r7, lsl #16 \r\n"
254 unsigned short* wbufend = wbuf + wordcount; 280 "orr r8, r8, r9, lsl #16 \r\n"
255 do 281 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
256 { 282 : [buf]"+&r"(*buf)
257 *wbuf = DATA_REG; 283 : [data]"r"(&DATA_REG)
258 } while (++wbuf < wbufend); /* tail loop is faster */ 284 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
285 );
286 break;
287 case 1:
288 asm volatile (
289 "ldmia %[data], { r2-r9 } \r\n"
290 "orr r3, r2, r3, lsl #16 \r\n"
291 "strb r3, [%[buf]], #1 \r\n"
292 "mov r3, r3, lsr #8 \r\n"
293 "strh r3, [%[buf]], #2 \r\n"
294 "mov r3, r3, lsr #16 \r\n"
295 "orr r3, r3, r4, lsl #8 \r\n"
296 "orr r3, r3, r5, lsl #24 \r\n"
297 "mov r5, r5, lsr #8 \r\n"
298 "orr r5, r5, r6, lsl #8 \r\n"
299 "orr r5, r5, r7, lsl #24 \r\n"
300 "mov r7, r7, lsr #8 \r\n"
301 "orr r7, r7, r8, lsl #8 \r\n"
302 "orr r7, r7, r9, lsl #24 \r\n"
303 "mov r2, r9, lsr #8 \r\n"
304 "stmia %[buf]!, { r3, r5, r7 } \r\n"
305 "ldmia %[data], { r3-r10 } \r\n"
306 "orr r2, r2, r3, lsl #8 \r\n"
307 "orr r2, r2, r4, lsl #24 \r\n"
308 "mov r4, r4, lsr #8 \r\n"
309 "orr r4, r4, r5, lsl #8 \r\n"
310 "orr r4, r4, r6, lsl #24 \r\n"
311 "mov r6, r6, lsr #8 \r\n"
312 "orr r6, r6, r7, lsl #8 \r\n"
313 "orr r6, r6, r8, lsl #24 \r\n"
314 "mov r8, r8, lsr #8 \r\n"
315 "orr r8, r8, r9, lsl #8 \r\n"
316 "orr r8, r8, r10, lsl #24 \r\n"
317 "mov r10, r10, lsr #8 \r\n"
318 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
319 "strb r10, [%[buf]], #1 \r\n"
320 : [buf]"+&r"(*buf)
321 : [data]"r"(&DATA_REG)
322 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
323 );
324 break;
325 case 2:
326 asm volatile (
327 "ldmia %[data], { r2-r9 } \r\n"
328 "strh r2, [%[buf]], #2 \r\n"
329 "orr r3, r3, r4, lsl #16 \r\n"
330 "orr r5, r5, r6, lsl #16 \r\n"
331 "orr r7, r7, r8, lsl #16 \r\n"
332 "stmia %[buf]!, { r3, r5, r7 } \r\n"
333 "ldmia %[data], { r2-r8, r10 } \r\n"
334 "orr r2, r9, r2, lsl #16 \r\n"
335 "orr r3, r3, r4, lsl #16 \r\n"
336 "orr r5, r5, r6, lsl #16 \r\n"
337 "orr r7, r7, r8, lsl #16 \r\n"
338 "stmia %[buf]!, { r2, r3, r5, r7 } \r\n"
339 "strh r10, [%[buf]], #2 \r\n"
340 : [buf]"+&r"(*buf)
341 : [data]"r"(&DATA_REG)
342 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
343 );
344 break;
345 case 3:
346 asm volatile (
347 "ldmia %[data], { r2-r9 } \r\n"
348 "orr r3, r2, r3, lsl #16 \r\n"
349 "strb r3, [%[buf]], #1 \r\n"
350 "mov r3, r3, lsr #8 \r\n"
351 "orr r3, r3, r4, lsl #24 \r\n"
352 "mov r4, r4, lsr #8 \r\n"
353 "orr r5, r4, r5, lsl #8 \r\n"
354 "orr r5, r5, r6, lsl #24 \r\n"
355 "mov r6, r6, lsr #8 \r\n"
356 "orr r7, r6, r7, lsl #8 \r\n"
357 "orr r7, r7, r8, lsl #24 \r\n"
358 "mov r8, r8, lsr #8 \r\n"
359 "orr r2, r8, r9, lsl #8 \r\n"
360 "stmia %[buf]!, { r3, r5, r7 } \r\n"
361 "ldmia %[data], { r3-r10 } \r\n"
362 "orr r2, r2, r3, lsl #24 \r\n"
363 "mov r3, r3, lsr #8 \r\n"
364 "orr r4, r3, r4, lsl #8 \r\n"
365 "orr r4, r4, r5, lsl #24 \r\n"
366 "mov r5, r5, lsr #8 \r\n"
367 "orr r6, r5, r6, lsl #8 \r\n"
368 "orr r6, r6, r7, lsl #24 \r\n"
369 "mov r7, r7, lsr #8 \r\n"
370 "orr r8, r7, r8, lsl #8 \r\n"
371 "orr r8, r8, r9, lsl #24 \r\n"
372 "mov r9, r9, lsr #8 \r\n"
373 "orr r10, r9, r10, lsl #8 \r\n"
374 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
375 "strh r10, [%[buf]], #2 \r\n"
376 "mov r10, r10, lsr #16 \r\n"
377 "strb r10, [%[buf]], #1 \r\n"
378 : [buf]"+&r"(*buf)
379 : [data]"r"(&DATA_REG)
380 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
381 );
382 break;
259 } 383 }
260} 384}
261 385
262STATICIRAM void copy_write_sectors(const unsigned char* buf, int wordcount) 386static inline void copy_read_sectors_slow(unsigned char** buf)
263 NOINLINE_ATTR ICODE_ATTR; 387{
388 int cnt = FIFO_SIZE;
389 int t;
390
391 /* Copy one chunk of 16 words */
392 asm volatile (
393 "1: \r\n"
394 "ldrh %[t], [%[data]] \r\n"
395 "strb %[t], [%[buf]], #1 \r\n"
396 "mov %[t], %[t], lsr #8 \r\n"
397 "strb %[t], [%[buf]], #1 \r\n"
398 "subs %[cnt], %[cnt], #1 \r\n"
399 "bgt 1b \r\n"
400 : [cnt]"+&r"(cnt), [buf]"+&r"(*buf),
401 [t]"=&r"(t)
402 : [data]"r"(&DATA_REG)
403 );
404}
264 405
265STATICIRAM void copy_write_sectors(const unsigned char* buf, int wordcount) 406/* Writes have to be kept slow for now */
407static inline void copy_write_sectors(const unsigned char* buf)
266{ 408{
267 unsigned short tmp = 0; 409 unsigned short tmp = 0;
268 const unsigned char* bufend = buf + wordcount*2; 410 const unsigned char* bufend = buf + FIFO_SIZE*2;
411
269 do 412 do
270 { 413 {
271 tmp = (unsigned short) *buf++; 414 tmp = (unsigned short) *buf++;
272 tmp |= (unsigned short) *buf++ << 8; 415 tmp |= (unsigned short) *buf++ << 8;
273 DATA_REG = tmp; 416 DATA_REG = tmp;
274 } while (buf < bufend); /* tail loop is faster */ 417 } while (buf < bufend); /* tail loop is faster */
275} 418}
276 419
277 420static void sd_select_bank(unsigned char bank)
278void sd_select_bank(unsigned char bank)
279{ 421{
280 unsigned int response; 422 unsigned int response;
281 unsigned char card_data[512]; 423 unsigned char card_data[512];
282 unsigned char* write_buf; 424 unsigned char* write_buf;
283 int i; 425 int i;
284 tSDCardInfo *card = &card_info[0]; /* Bank selection will only be done on
285 the onboard flash */
286 if (current_bank != bank)
287 {
288 memset(card_data, 0, 512);
289 sd_wait_for_state(card, TRAN);
290 BLOCK_SIZE_REG = 512;
291 BLOCK_COUNT_REG = 1;
292 sd_send_command(35, 0, 0x1c0d); /* CMD35 is vendor specific */
293 sd_read_response(&response, 1);
294 SD_STATE_REG = PRG;
295 426
296 card_data[0] = bank; 427 memset(card_data, 0, 512);
428 sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK);
429 BLOCK_SIZE_REG = 512;
430 BLOCK_COUNT_REG = 1;
431 sd_command(35, 0, &response, 0x1c0d); /* CMD35 is vendor specific */
432 SD_STATE_REG = PRG;
297 433
298 /* Write the card data */ 434 card_data[0] = bank;
299 write_buf = card_data;
300 for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE)
301 {
302 /* Wait for the FIFO to be empty */
303 while((STATUS_REG & FIFO_EMPTY) == 0) {} /* Erm... is this right? */
304 435
305 copy_write_sectors(write_buf, FIFO_SIZE); 436 /* Write the card data */
437 write_buf = card_data;
438 for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE)
439 {
440 /* Wait for the FIFO to empty */
441 sd_poll_status(FIFO_EMPTY, 10000, EC_FIFO_SEL_BANK_EMPTY | DO_PANIC);
306 442
307 write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ 443 copy_write_sectors(write_buf); /* Copy one chunk of 16 words */
308 }
309 444
310 while((STATUS_REG & DATA_DONE) == 0) {} 445 write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */
311 current_bank = bank;
312 } 446 }
447
448 sd_poll_status(DATA_DONE, 10000, EC_FIFO_SEL_BANK_DONE | DO_PANIC);
449
450 currcard->current_bank = bank;
313} 451}
314 452
315void sd_init_device(void) 453/* lock must already be aquired */
454static void sd_init_device(int card_no)
316{ 455{
317/* SD Protocol registers */ 456/* SD Protocol registers */
318 unsigned int dummy; 457 unsigned int i, dummy;
319 int i; 458 unsigned int c_size = 0;
320 459 unsigned long c_mult = 0;
321 static unsigned int read_bl_len = 0;
322 static unsigned int c_size = 0;
323 static unsigned int c_size_mult = 0;
324 static unsigned long mult = 0;
325
326 unsigned char carddata[512]; 460 unsigned char carddata[512];
327 unsigned char *dataptr; 461 unsigned char *dataptr;
328 tSDCardInfo *card = &card_info[0]; /* Init onboard flash only */
329
330/* Initialise card data as blank */
331 card->initialized = false;
332 card->ocr = 0;
333 card->csd[0] = 0;
334 card->csd[1] = 0;
335 card->csd[2] = 0;
336 card->cid[0] = 0;
337 card->cid[1] = 0;
338 card->cid[2] = 0;
339 card->rca = 0;
340
341 card->capacity = 0;
342 card->numblocks = 0;
343 card->block_size = 0;
344 card->block_exp = 0;
345 462
346/* Enable and initialise controller */ 463/* Enable and initialise controller */
347 GPIOG_ENABLE |= (0x3 << 5);
348 GPIOG_OUTPUT_EN |= (0x3 << 5);
349 GPIOG_OUTPUT_VAL |= (0x3 << 5);
350 outl(inl(0x70000088) & ~(0x4), 0x70000088);
351 outl(inl(0x7000008c) & ~(0x4), 0x7000008c);
352 outl(inl(0x70000080) | 0x4, 0x70000080);
353 outl(inl(0x70000084) | 0x4, 0x70000084);
354 REG_1 = 6; 464 REG_1 = 6;
355 outl(inl(0x70000014) & ~(0x3ffff), 0x70000014);
356 outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014);
357 outl(0x1010, 0x70000034);
358
359 GPIOA_ENABLE |= (1 << 7);
360 GPIOA_OUTPUT_EN &= ~(1 << 7);
361 GPIOD_ENABLE |= (0x1f);
362 GPIOD_OUTPUT_EN |= (0x1f);
363 GPIOD_OUTPUT_VAL |= (0x1f);
364 DEV_EN |= DEV_ATA; /* Enable controller */
365 DEV_RS |= DEV_ATA; /* Reset controller */
366 DEV_RS &=~DEV_ATA; /* Clear Reset */
367 465
368/* Init NAND */ 466 currcard = &card_info[card_no];
369 REG_11 |= (1 << 15); 467
370 REG_12 |= (1 << 15); 468/* Initialise card data as blank */
469 memset(currcard, 0, sizeof(*currcard));
470
471 if (card_no == 0)
472 {
473 outl(inl(0x70000080) | 0x4, 0x70000080);
474
475 GPIOA_ENABLE &= ~0x7a;
476 GPIOA_OUTPUT_EN &= ~0x7a;
477 GPIOD_ENABLE |= 0x1f;
478 GPIOD_OUTPUT_VAL |= 0x1f;
479 GPIOD_OUTPUT_EN |= 0x1f;
480
481 outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014);
482 }
483 else
484 {
485 outl(inl(0x70000080) & ~0x4, 0x70000080);
486
487 GPIOD_ENABLE &= ~0x1f;
488 GPIOD_OUTPUT_EN &= ~0x1f;
489 GPIOA_ENABLE |= 0x7a;
490 GPIOA_OUTPUT_VAL |= 0x7a;
491 GPIOA_OUTPUT_EN |= 0x7a;
492
493 outl(inl(0x70000014) & ~(0x3ffff), 0x70000014);
494 }
495
496 /* Init NAND */
497 REG_11 |= (1 << 15);
498 REG_12 |= (1 << 15);
371 REG_12 &= ~(3 << 12); 499 REG_12 &= ~(3 << 12);
372 REG_12 |= (1 << 13); 500 REG_12 |= (1 << 13);
373 REG_11 &= ~(3 << 12); 501 REG_11 &= ~(3 << 12);
374 REG_11 |= (1 << 13); 502 REG_11 |= (1 << 13);
503
504 DEV_EN |= DEV_ATA; /* Enable controller */
505 DEV_RS |= DEV_ATA; /* Reset controller */
506 DEV_RS &=~DEV_ATA; /* Clear Reset */
375 507
376 SD_STATE_REG = TRAN; 508 SD_STATE_REG = TRAN;
377 REG_5 = 0xf;
378 509
379 sd_send_command(GO_IDLE_STATE, 0, 256); 510 REG_5 = 0xf;
380 while ((card->ocr & (1 << 31)) == 0) /* Loop until the card is powered up */ 511 sd_command(GO_IDLE_STATE, 0, &dummy, 256);
512 check_time[EC_POWER_UP] = USEC_TIMER;
513 while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */
381 { 514 {
382 sd_send_acommand(SD_APP_OP_COND, 0x100000, 3); 515 sd_command(APP_CMD, currcard->rca, &dummy, 1);
383 sd_read_response(&(card->ocr), 3); 516 sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3);
384 517 sd_check_timeout(5000000, EC_POWER_UP);
385 if (card->ocr == 0)
386 {
387 /* TODO: Handle failure */
388 while (1) {};
389 }
390 } 518 }
391 519
392 sd_send_command(ALL_SEND_CID, 0, 2); 520 sd_command(ALL_SEND_CID, 0, currcard->cid, 2);
393 sd_read_response(card->cid, 2); 521 sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1);
394 sd_send_command(SEND_RELATIVE_ADDR, 0, 1); 522 sd_command(SEND_CSD, currcard->rca, currcard->csd, 2);
395 sd_read_response(&card->rca, 1);
396 card->rca >>= 16; /* The Relative Card Address is the top 16 bits of the
397 32 bits returned. Whenever it is used, it gets
398 shifted left by 16 bits, so this step could possibly
399 be skipped. */
400 523
401 sd_send_command(SEND_CSD, card->rca << 16, 2);
402 sd_read_response(card->csd, 2);
403
404 /* Parse disk geometry */
405 /* These calculations come from the Sandisk SD card product manual */ 524 /* These calculations come from the Sandisk SD card product manual */
406 read_bl_len = ((card->csd[2] >> 16) & 0xf); 525 c_size = ((currcard->csd[2] & 0x3ff) << 2) + (currcard->csd[1] >> 30) + 1;
407 c_size = ((card->csd[2] & (0x3ff)) << 2) + 526 c_mult = 4 << ((currcard->csd[1] >> 15) & 7);
408 ((card->csd[1] & (0xc0000000)) >> 30); 527 currcard->max_read_bl_len = 1 << ((currcard->csd[2] >> 16) & 15);
409 c_size_mult = ((card->csd[1] >> 15) & 0x7); 528 currcard->block_size = BLOCK_SIZE; /* Always use 512 byte blocks */
410 mult = (1<<(c_size_mult + 2)); 529 currcard->numblocks = c_size * c_mult * (currcard->max_read_bl_len / 512);
411 card->max_read_bl_len = (1<<read_bl_len); 530 currcard->capacity = currcard->numblocks * currcard->block_size;
412 card->block_size = BLOCK_SIZE; /* Always use 512 byte blocks */
413 card->numblocks = (c_size + 1) * mult * (card->max_read_bl_len / 512);
414 card->capacity = card->numblocks * card->block_size;
415 531
416 REG_1 = 0; 532 REG_1 = 0;
417 sd_send_command(SELECT_CARD, card->rca << 16, 129); 533
418 sd_read_response(&dummy, 1); /* I don't think we use the result from this */ 534 sd_command(SELECT_CARD, currcard->rca , &dummy, 129);
419 sd_send_acommand(SET_BUS_WIDTH, (card->rca << 16) | 2, 1); 535 sd_command(APP_CMD, currcard->rca , &dummy, 1);
420 sd_read_response(&dummy, 1); /* 4 bit wide bus */ 536 sd_command(SET_BUS_WIDTH, currcard->rca | 2 , &dummy, 1); /* 4 bit */
421 sd_send_command(SET_BLOCKLEN, card->block_size, 1); 537 sd_command(SET_BLOCKLEN, currcard->block_size, &dummy, 1);
422 sd_read_response(&dummy, 1); 538 BLOCK_SIZE_REG = currcard->block_size;
423 BLOCK_SIZE_REG = card->block_size;
424 539
425 /* If this card is > 4Gb, then we need to enable bank switching */ 540 /* If this card is > 4Gb, then we need to enable bank switching */
426 if(card->numblocks >= BLOCKS_PER_BANK) 541 if(currcard->numblocks >= BLOCKS_PER_BANK)
427 { 542 {
428 SD_STATE_REG = TRAN; 543 SD_STATE_REG = TRAN;
429 BLOCK_COUNT_REG = 1; 544 BLOCK_COUNT_REG = 1;
430 sd_send_command(SWITCH_FUNC, 0x80ffffef, 0x1c05); 545 sd_command(SWITCH_FUNC, 0x80ffffef, &dummy, 0x1c05);
431 sd_read_response(&dummy, 1);
432 /* Read 512 bytes from the card. 546 /* Read 512 bytes from the card.
433 The first 512 bits contain the status information 547 The first 512 bits contain the status information
434 TODO: Do something useful with this! */ 548 TODO: Do something useful with this! */
@@ -436,206 +550,216 @@ void sd_init_device(void)
436 for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE) 550 for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE)
437 { 551 {
438 /* Wait for the FIFO to be full */ 552 /* Wait for the FIFO to be full */
439 while((STATUS_REG & FIFO_FULL) == 0) {} 553 sd_poll_status(FIFO_FULL, 100000,
440 554 EC_FIFO_ENA_BANK_EMPTY | DO_PANIC);
441 copy_read_sectors(dataptr, FIFO_SIZE); 555 copy_read_sectors_slow(&dataptr);
442
443 dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */
444 } 556 }
445 } 557 }
446 spinlock_init(&sd_mtx); 558
559 currcard->initialized = true;
447} 560}
448 561
449/* API Functions */ 562/* API Functions */
450 563
451void ata_led(bool onoff) 564void ata_led(bool onoff)
452{ 565{
453 (void)onoff; 566 led(onoff);
454} 567}
455 568
456int ata_read_sectors(IF_MV2(int drive,) 569int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount,
457 unsigned long start,
458 int incount,
459 void* inbuf) 570 void* inbuf)
460{ 571{
461 int ret = 0; 572 int ret = 0;
462 long timeout; 573 unsigned char *buf, *buf_end;
463 int count;
464 void* buf;
465 long spinup_start;
466 unsigned int dummy; 574 unsigned int dummy;
467 unsigned int response; 575 int bank;
468 unsigned int i; 576
469 tSDCardInfo *card = &card_info[current_card];
470
471 /* TODO: Add DMA support. */ 577 /* TODO: Add DMA support. */
472 578
473#ifdef HAVE_MULTIVOLUME
474 (void)drive; /* unused for now */
475#endif
476 spinlock_lock(&sd_mtx); 579 spinlock_lock(&sd_mtx);
477 580
478 last_disk_activity = current_tick;
479 spinup_start = current_tick;
480
481 ata_enable(true);
482 ata_led(true); 581 ata_led(true);
483 582
484 timeout = current_tick + READ_TIMEOUT; 583 if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0)
485
486 /* TODO: Select device */
487 if(current_card == 0)
488 { 584 {
489 if(start >= BLOCKS_PER_BANK) 585 /* no external sd-card inserted */
490 { 586 ret = -9;
491 sd_select_bank(1); 587 goto ata_read_error;
492 start -= BLOCKS_PER_BANK;
493 } else {
494 sd_select_bank(0);
495 }
496 } 588 }
497 589
498 buf = inbuf; 590 if (&card_info[drive] != currcard || !card_info[drive].initialized)
499 count = incount; 591 sd_init_device(drive);
500 while (TIME_BEFORE(current_tick, timeout)) {
501 ret = 0;
502 last_disk_activity = current_tick;
503 592
504 SD_STATE_REG = TRAN; 593 last_disk_activity = current_tick;
505 BLOCK_COUNT_REG = count;
506 sd_send_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, 0x1c25);
507 sd_read_response(&dummy, 1);
508 /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */
509 594
510 for (i = 0; i < count * card->block_size / 2; i += FIFO_SIZE) 595 bank = start / BLOCKS_PER_BANK;
511 {
512 /* Wait for the FIFO to be full */
513 while((STATUS_REG & FIFO_FULL) == 0) {}
514 596
515 copy_read_sectors(buf, FIFO_SIZE); 597 if (currcard->current_bank != bank)
598 sd_select_bank(bank);
516 599
517 buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ 600 start -= bank * BLOCKS_PER_BANK;
518 601
519 /* TODO: Switch bank if necessary */ 602 sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY);
603 BLOCK_COUNT_REG = incount;
604 sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &dummy, 0x1c25);
605 /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */
520 606
521 last_disk_activity = current_tick; 607 buf_end = (unsigned char *)inbuf + incount * currcard->block_size;
522 } 608 for (buf = inbuf; buf < buf_end;)
523 udelay(75); 609 {
524 sd_send_command(STOP_TRANSMISSION, 0, 1); 610 /* Wait for the FIFO to be full */
525 sd_read_response(&dummy, 1); 611 sd_poll_status(FIFO_FULL, 0x80000, EC_FIFO_READ_FULL | DO_PANIC);
612 copy_read_sectors_fast(&buf); /* Copy one chunk of 16 words */
526 613
527 response = 0; 614 /* TODO: Switch bank if necessary */
528 sd_wait_for_state(card, TRAN);
529 break;
530 } 615 }
616
617 last_disk_activity = current_tick;
618#if 0
619 udelay(75);
620#endif
621 sd_command(STOP_TRANSMISSION, 0, &dummy, 1);
622 sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT);
623
624ata_read_error:
531 ata_led(false); 625 ata_led(false);
532 ata_enable(false);
533 626
534 spinlock_unlock(&sd_mtx); 627 spinlock_unlock(&sd_mtx);
535 628
536 return ret; 629 return ret;
537} 630}
538 631
539 632int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count,
540int ata_write_sectors(IF_MV2(int drive,) 633 const void* outbuf)
541 unsigned long start,
542 int count,
543 const void* buf)
544{ 634{
545/* Write support is not finished yet */ 635/* Write support is not finished yet */
546/* TODO: The standard suggests using ACMD23 prior to writing multiple blocks 636/* TODO: The standard suggests using ACMD23 prior to writing multiple blocks
547 to improve performance */ 637 to improve performance */
548 unsigned int response; 638 unsigned int response;
549 void const* write_buf; 639 void const* buf, *buf_end;
550 int ret = 0; 640 int ret = 0;
551 unsigned int i; 641 int bank;
552 long timeout;
553 tSDCardInfo *card = &card_info[current_card];
554 642
555 spinlock_lock(&sd_mtx); 643 spinlock_lock(&sd_mtx);
556 ata_enable(true); 644
557 ata_led(true); 645 ata_led(true);
558 if(current_card == 0) 646
647 if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0)
559 { 648 {
560 if(start < BLOCKS_PER_BANK) 649 /* no external sd-card inserted */
561 { 650 ret = -9;
562 sd_select_bank(0); 651 goto error;
563 } else {
564 sd_select_bank(1);
565 start -= BLOCKS_PER_BANK;
566 }
567 } 652 }
568 653
569retry: 654 if (&card_info[drive] != currcard || !card_info[drive].initialized)
570 sd_wait_for_state(card, TRAN); 655 sd_init_device(drive);
656
657 bank = start / BLOCKS_PER_BANK;
658
659 if (currcard->current_bank != bank)
660 sd_select_bank(bank);
661
662 start -= bank * BLOCKS_PER_BANK;
663
664 check_time[EC_WRITE_TIMEOUT] = USEC_TIMER;
665 sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY);
571 BLOCK_COUNT_REG = count; 666 BLOCK_COUNT_REG = count;
572 sd_send_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, 0x1c2d); 667 sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, &response, 0x1c2d);
573 sd_read_response(&response, 1); 668
574 write_buf = buf; 669 buf_end = outbuf + count * currcard->block_size;
575 for (i = 0; i < count * card->block_size / 2; i += FIFO_SIZE) 670 for (buf = outbuf; buf < buf_end; buf += 2 * FIFO_SIZE)
576 { 671 {
577 if(i >= (count * card->block_size / 2)-FIFO_SIZE) 672 if (buf >= buf_end - 2 * FIFO_SIZE)
578 { 673 {
579 /* Set SD_STATE_REG to PRG for the last buffer fill */ 674 /* Set SD_STATE_REG to PRG for the last buffer fill */
580 SD_STATE_REG = PRG; 675 SD_STATE_REG = PRG;
581 } 676 }
582 677
583 /* Wait for the FIFO to be empty */ 678 udelay(2); /* needed here (loop is too fast :-) */
584 while((STATUS_REG & FIFO_EMPTY) == 0) {}
585 /* Perhaps we could use bit 8 of card status (READY_FOR_DATA)? */
586 679
587 copy_write_sectors(write_buf, FIFO_SIZE); 680 /* Wait for the FIFO to empty */
681 sd_poll_status(FIFO_EMPTY, 0x80000, EC_FIFO_WR_EMPTY | DO_PANIC);
588 682
589 write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ 683 copy_write_sectors(buf); /* Copy one chunk of 16 words */
590 /* TODO: Switch bank if necessary */
591 684
592 last_disk_activity = current_tick; 685 /* TODO: Switch bank if necessary */
593 } 686 }
594 687
595 timeout = current_tick + WRITE_TIMEOUT; 688 last_disk_activity = current_tick;
596 689
597 while((STATUS_REG & DATA_DONE) == 0) { 690 sd_poll_status(DATA_DONE, 0x80000, EC_FIFO_WR_DONE | DO_PANIC);
598 if(current_tick >= timeout) 691 sd_check_timeout(0x80000, EC_WRITE_TIMEOUT);
599 { 692
600 sd_send_command(STOP_TRANSMISSION, 0, 1); 693 sd_command(STOP_TRANSMISSION, 0, &response, 1);
601 sd_read_response(&response, 1); 694 sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT);
602 goto retry;
603 }
604 }
605 sd_send_command(STOP_TRANSMISSION, 0, 1);
606 sd_read_response(&response, 1);
607 695
608 sd_wait_for_state(card, TRAN); 696 error:
609 ata_led(false); 697 ata_led(false);
610 ata_enable(false);
611 spinlock_unlock(&sd_mtx); 698 spinlock_unlock(&sd_mtx);
612 699
613 return ret; 700 return ret;
614} 701}
615 702
703static void sd_thread(void) __attribute__((noreturn));
616static void sd_thread(void) 704static void sd_thread(void)
617{ 705{
618 struct event ev; 706 struct event ev;
619 bool idle_notified = false; 707 bool idle_notified = false;
620 708
621 while (1) { 709 while (1)
710 {
622 queue_wait_w_tmo(&sd_queue, &ev, HZ); 711 queue_wait_w_tmo(&sd_queue, &ev, HZ);
712
623 switch ( ev.id ) 713 switch ( ev.id )
624 { 714 {
625 default: 715 case SD_HOTSWAP:
626 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) 716 {
627 { 717 int status = 0;
628 idle_notified = false; 718 enum { SD_UNMOUNTED = 0x1, SD_MOUNTED = 0x2 };
629 } 719
630 else 720 /* Delay on insert and remove to prevent reading state if it is
631 { 721 just bouncing back and forth while card is sliding - delay on
632 if (!idle_notified) 722 insert is also required for the card to stabilize and accept
633 { 723 commands */
634 call_ata_idle_notifys(false); 724 sleep(HZ/10);
635 idle_notified = true; 725
636 } 726 /* Lock to keep us from messing with this variable while an init
637 } 727 may be in progress */
638 break; 728 spinlock_lock(&sd_mtx);
729 card_info[1].initialized = false;
730 spinlock_unlock(&sd_mtx);
731
732 /* Either unmount because the card was pulled or unmount and
733 remount if already mounted since multiple messages may be
734 generated for the same event - like someone inserting a new
735 card before anything detects the old one pulled :) */
736 if (disk_unmount(1) != 0) /* release "by force" */
737 status |= SD_UNMOUNTED;
738
739 if (card_detect_target() && disk_mount(1) != 0) /* mount SD-CARD */
740 status |= SD_MOUNTED;
741
742 if (status & SD_UNMOUNTED)
743 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
744
745 if (status & SD_MOUNTED)
746 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
747
748 if (status)
749 queue_broadcast(SYS_FS_CHANGED, 0);
750 break;
751 } /* SD_HOTSWAP */
752 case SYS_TIMEOUT:
753 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
754 {
755 idle_notified = false;
756 }
757 else if (!idle_notified)
758 {
759 call_ata_idle_notifys(false);
760 idle_notified = true;
761 }
762 break;
639 } 763 }
640 } 764 }
641} 765}
@@ -648,7 +772,7 @@ void ata_spindown(int seconds)
648 772
649bool ata_disk_is_active(void) 773bool ata_disk_is_active(void)
650{ 774{
651 return 0; 775 return 0;
652} 776}
653 777
654void ata_sleep(void) 778void ata_sleep(void)
@@ -662,12 +786,12 @@ void ata_spin(void)
662/* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */ 786/* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */
663int ata_hard_reset(void) 787int ata_hard_reset(void)
664{ 788{
665 return 0; 789 return 0;
666} 790}
667 791
668int ata_soft_reset(void) 792int ata_soft_reset(void)
669{ 793{
670 return 0; 794 return 0;
671} 795}
672 796
673void ata_enable(bool on) 797void ata_enable(bool on)
@@ -682,22 +806,113 @@ void ata_enable(bool on)
682 } 806 }
683} 807}
684 808
685unsigned short* ata_get_identify(void)
686{
687 return identify_info;
688}
689
690int ata_init(void) 809int ata_init(void)
691{ 810{
692 sd_init_device(); 811 ata_led(false);
693 if ( !initialized ) 812
813 /* NOTE: This init isn't dual core safe */
814 if (!initialized)
694 { 815 {
695 queue_init(&sd_queue, true);
696 create_thread(sd_thread, sd_stack,
697 sizeof(sd_stack), sd_thread_name IF_PRIO(, PRIORITY_SYSTEM)
698 IF_COP(, CPU, false));
699 initialized = true; 816 initialized = true;
817
818 spinlock_init(&sd_mtx);
819
820 spinlock_lock(&sd_mtx);
821
822 /* init controller */
823 outl(inl(0x70000088) & ~(0x4), 0x70000088);
824 outl(inl(0x7000008c) & ~(0x4), 0x7000008c);
825 outl(inl(0x70000084) | 0x4, 0x70000084);
826 outl(0x1010, 0x70000034);
827
828 GPIOG_ENABLE |= (0x3 << 5);
829 GPIOG_OUTPUT_EN |= (0x3 << 5);
830 GPIOG_OUTPUT_VAL |= (0x3 << 5);
831
832 /* enable card detection port - mask interrupt first */
833 GPIOA_INT_EN &= ~0x80;
834
835 GPIOA_OUTPUT_EN &= ~0x80;
836 GPIOA_ENABLE |= 0x80;
837
838 sd_init_device(0);
839
840 queue_init(&sd_queue, true);
841 create_thread(sd_thread, sd_stack, sizeof(sd_stack),
842 sd_thread_name IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU, false));
843
844 /* enable interupt for the mSD card */
845 sleep(HZ/10);
846
847 CPU_INT_EN = HI_MASK;
848 CPU_HI_INT_EN = GPIO0_MASK;
849
850 sd1_status = GPIOA_INPUT_VAL & 0x80;
851 GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (sd1_status ^ 0x80);
852
853 GPIOA_INT_CLR = 0x80;
854 GPIOA_INT_EN |= 0x80;
855
856 spinlock_unlock(&sd_mtx);
700 } 857 }
701 858
702 return 0; 859 return 0;
703} 860}
861
862/* move the sd-card info to mmc struct */
863tCardInfo *card_get_info_target(int card_no)
864{
865 int i, temp;
866 static tCardInfo card;
867 static const char mantissa[] = { /* *10 */
868 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
869 static const int exponent[] = { /* use varies */
870 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 };
871
872 card.initialized = card_info[card_no].initialized;
873 card.ocr = card_info[card_no].ocr;
874 for(i=0; i<4; i++) card.csd[i] = card_info[card_no].csd[3-i];
875 for(i=0; i<4; i++) card.cid[i] = card_info[card_no].cid[3-i];
876 card.numblocks = card_info[card_no].numblocks;
877 card.blocksize = card_info[card_no].block_size;
878 card.size = card_info[card_no].capacity < 0xffffffff ?
879 card_info[card_no].capacity : 0xffffffff;
880 card.block_exp = card_info[card_no].block_exp;
881 temp = card_extract_bits(card.csd, 29, 3);
882 card.speed = mantissa[card_extract_bits(card.csd, 25, 4)]
883 * exponent[temp > 2 ? 7 : temp + 4];
884 card.nsac = 100 * card_extract_bits(card.csd, 16, 8);
885 temp = card_extract_bits(card.csd, 13, 3);
886 card.tsac = mantissa[card_extract_bits(card.csd, 9, 4)]
887 * exponent[temp] / 10;
888 card.cid[0] = htobe32(card.cid[0]); /* ascii chars here */
889 card.cid[1] = htobe32(card.cid[1]); /* ascii chars here */
890 temp = *((char*)card.cid+13); /* adjust year<=>month, 1997 <=> 2000 */
891 *((char*)card.cid+13) = (unsigned char)((temp >> 4) | (temp << 4)) + 3;
892
893 return &card;
894}
895
896bool card_detect_target(void)
897{
898 /* 0x00:inserted, 0x80:not inserted */
899 return (GPIOA_INPUT_VAL & 0x80) == 0;
900}
901
902/* called on insertion/removal interrupt */
903void microsd_int(void)
904{
905 int status = GPIOA_INPUT_VAL & 0x80;
906
907 GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (status ^ 0x80);
908 GPIOA_INT_CLR = 0x80;
909
910 if (status == sd1_status)
911 return;
912
913 sd1_status = status;
914
915 /* Take final state only - insert/remove is bouncy */
916 queue_remove_from_head(&sd_queue, SD_HOTSWAP);
917 queue_post(&sd_queue, SD_HOTSWAP, status);
918}
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-target.h b/firmware/target/arm/sandisk/sansa-e200/ata-target.h
index dfdd3fe6ae..61884e0864 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-target.h
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-target.h
@@ -19,25 +19,4 @@
19#ifndef ATA_TARGET_H 19#ifndef ATA_TARGET_H
20#define ATA_TARGET_H 20#define ATA_TARGET_H
21 21
22#include "inttypes.h"
23
24typedef struct
25{
26 bool initialized;
27
28 unsigned int ocr; /* OCR register */
29 unsigned int csd[4]; /* CSD register */
30 unsigned int cid[4]; /* CID register */
31 unsigned int rca;
32
33 uint64_t capacity; /* size in bytes */
34 unsigned long numblocks; /* size in flash blocks */
35 unsigned int block_size; /* block size in bytes */
36 unsigned int max_read_bl_len;/* max read data block length */
37 unsigned int block_exp; /* block size exponent */
38} tSDCardInfo;
39
40tSDCardInfo *sd_card_info(int card_no);
41bool sd_touched(void);
42
43#endif 22#endif
diff --git a/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h b/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h
new file mode 100644
index 0000000000..95cb26d2f7
--- /dev/null
+++ b/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h
@@ -0,0 +1,45 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Antonius Hellmann
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef HOTSWAP_TARGET_H
20#define HOTSWAP_TARGET_H
21
22#include "inttypes.h"
23#include "hotswap.h"
24
25typedef struct
26{
27 bool initialized;
28
29 unsigned int ocr; /* OCR register */
30 unsigned int csd[4]; /* CSD register */
31 unsigned int cid[4]; /* CID register */
32 unsigned int rca;
33
34 uint64_t capacity; /* size in bytes */
35 unsigned long numblocks; /* size in flash blocks */
36 unsigned int block_size; /* block size in bytes */
37 unsigned int max_read_bl_len;/* max read data block length */
38 unsigned int block_exp; /* block size exponent */
39 unsigned char current_bank; /* The bank that we are working with */
40} tSDCardInfo;
41
42tCardInfo *card_get_info_target(int card_no);
43bool card_detect_target(void);
44
45#endif
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index ef0c62dcf5..49ffdd300b 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -56,8 +56,11 @@ void irq(void)
56/* TODO: this should really be in the target tree, but moving it there caused 56/* TODO: this should really be in the target tree, but moving it there caused
57 crt0.S not to find it while linking */ 57 crt0.S not to find it while linking */
58/* TODO: Even if it isn't in the target tree, this should be the default case */ 58/* TODO: Even if it isn't in the target tree, this should be the default case */
59#ifdef SANSA_E200
59extern void button_int(void); 60extern void button_int(void);
60extern void clickwheel_int(void); 61extern void clickwheel_int(void);
62extern void microsd_int(void);
63#endif
61 64
62void irq(void) 65void irq(void)
63{ 66{
@@ -65,11 +68,15 @@ void irq(void)
65 if (CPU_INT_STAT & TIMER1_MASK) { 68 if (CPU_INT_STAT & TIMER1_MASK) {
66 TIMER1(); 69 TIMER1();
67 } 70 }
68 else if (CPU_INT_STAT & TIMER2_MASK) 71 else if (CPU_INT_STAT & TIMER2_MASK) {
69 TIMER2(); 72 TIMER2();
73 }
70#ifdef SANSA_E200 74#ifdef SANSA_E200
71 else if (CPU_HI_INT_STAT & GPIO1_MASK) 75 else if (CPU_HI_INT_STAT & GPIO0_MASK) {
72 { 76 if (GPIOA_INT_STAT & 0x80)
77 microsd_int();
78 }
79 else if (CPU_HI_INT_STAT & GPIO1_MASK) {
73 if (GPIOF_INT_STAT & 0xff) 80 if (GPIOF_INT_STAT & 0xff)
74 button_int(); 81 button_int();
75 if (GPIOH_INT_STAT & 0xc0) 82 if (GPIOH_INT_STAT & 0xc0)
diff --git a/firmware/usb.c b/firmware/usb.c
index 217aaf8b84..9e9cb77919 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -255,8 +255,8 @@ static void usb_thread(void)
255 break; 255 break;
256 256
257#ifdef HAVE_MMC 257#ifdef HAVE_MMC
258 case SYS_MMC_INSERTED: 258 case SYS_HOTSWAP_INSERTED:
259 case SYS_MMC_EXTRACTED: 259 case SYS_HOTSWAP_EXTRACTED:
260 if(usb_state == USB_INSERTED) 260 if(usb_state == USB_INSERTED)
261 { 261 {
262 usb_enable(false); 262 usb_enable(false);