diff --git a/diskio.c b/diskio.c index 9bd78eb..5c4dc1b 100644 --- a/diskio.c +++ b/diskio.c @@ -7,6 +7,7 @@ #include "diskio.h" #include "string.h" +#include "sdmmc.h" //#include "sdhc.h" #ifndef MEM2_BSS @@ -23,15 +24,11 @@ DSTATUS disk_initialize ( BYTE drv /* Physical drive nmuber (0..) */ ) { - s32 ret; - -// sd_init(&sdhci, 0); -// ret = sd_mount(&sdhci); - - if (ret < 0) + if (sdmmc_check_card(SDMMC_DEFAULT_DEVICE) == SDMMC_NO_CARD) return STA_NOINIT; - else - return disk_status(drv); + + sdmmc_ack_card(SDMMC_DEFAULT_DEVICE); + return disk_status(drv); } @@ -46,7 +43,10 @@ DSTATUS disk_status ( // if (sd_inserted(&sdhci) == 0) // return STA_NODISK; - return 0; + if (sdmmc_check_card(SDMMC_DEFAULT_DEVICE) == SDMMC_INSERTED) + return 0; + else + return STA_NODISK; } @@ -66,10 +66,10 @@ DRESULT disk_read ( res = RES_OK; for (i = 0; i < count; i++) { -/* if (sd_read(&sdhci, sector + i, 1, buffer) != 0) { + if (sdmmc_read(SDMMC_DEFAULT_DEVICE, sector+i, 1, buffer) != 0){ res = RES_ERROR; break; - }*/ + } memcpy(buff + i * 512, buffer, 512); } diff --git a/mini.ld b/mini.ld index acb27b1..ad74032 100644 --- a/mini.ld +++ b/mini.ld @@ -5,7 +5,7 @@ EXTERN(__ipc_info) ENTRY(_start) __stack_size = 0x800; -__irqstack_size = 0x400; /* blame the bsd's sdhc_intr function */ +__irqstack_size = 0x200; /* blame the bsd's sdhc_intr function */ __excstack_size = 0x100; MEMORY { diff --git a/sdhc.c b/sdhc.c index f63fa49..fc44b19 100644 --- a/sdhc.c +++ b/sdhc.c @@ -45,7 +45,7 @@ #include "utils.h" #include "ipc.h" -#define SDHC_DEBUG 0 +#define SDHC_DEBUG 1 #define SDHC_COMMAND_TIMEOUT 0 #define SDHC_BUFFER_TIMEOUT 0 @@ -159,7 +159,7 @@ void sdhc_read_data(struct sdhc_host *, u_char *, int); void sdhc_write_data(struct sdhc_host *, u_char *, int); #ifdef SDHC_DEBUG -int sdhcdebug = 0; +int sdhcdebug = 2; #define DPRINTF(n,s) do { if ((n) <= sdhcdebug) gecko_printf s; } while (0) void sdhc_dump_regs(struct sdhc_host *); #else @@ -972,8 +972,8 @@ sdhc_intr(void *arg) /* Acknowledge the interrupts we are about to handle. */ HWRITE2(hp, SDHC_NINTR_STATUS, status); - DPRINTF(2,("%s: interrupt status=%d\n", HDEVNAME(hp), - status)); +// DPRINTF(2,("%s: interrupt status=%d\n", HDEVNAME(hp), +// status)); /* Claim this interrupt. */ @@ -988,11 +988,11 @@ sdhc_intr(void *arg) /* Acknowledge error interrupts. */ error = HREAD2(hp, SDHC_EINTR_STATUS); HWRITE2(hp, SDHC_EINTR_STATUS, error); - DPRINTF(2,("%s: error interrupt, status=%d\n", - HDEVNAME(hp), error)); +// DPRINTF(2,("%s: error interrupt, status=%d\n", +// HDEVNAME(hp), error)); if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR| - SDHC_DATA_TIMEOUT_ERROR)) { + SDHC_DATA_TIMEOUT_ERROR)) { hp->intr_error_status |= error; hp->intr_status |= status; wakeup(&hp->intr_status); @@ -1004,7 +1004,7 @@ sdhc_intr(void *arg) * TODO: move request to slow queue to make sure that * we're not blocking other IRQs */ - if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) { + if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) { ipc_request req; memset(&req, 0, sizeof(req)); req.device = IPC_DEV_SD; @@ -1019,7 +1019,7 @@ sdhc_intr(void *arg) */ if (ISSET(status, SDHC_BUFFER_READ_READY| SDHC_BUFFER_WRITE_READY|SDHC_COMMAND_COMPLETE| - SDHC_TRANSFER_COMPLETE)) { + SDHC_TRANSFER_COMPLETE)) { hp->intr_status |= status; wakeup(&hp->intr_status); } @@ -1027,8 +1027,8 @@ sdhc_intr(void *arg) /* * Service SD card interrupts. */ - if (ISSET(status, SDHC_CARD_INTERRUPT)) { - DPRINTF(0,("%s: card interrupt\n", HDEVNAME(hp))); + if (ISSET(status, SDHC_CARD_INTERRUPT)) { +// DPRINTF(0,("%s: card interrupt\n", HDEVNAME(hp))); HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); // sdmmc_card_intr(hp->sdmmc); } @@ -1064,7 +1064,7 @@ sdhc_dump_regs(struct sdhc_host *hp) #endif #include "hollywood.h" -static struct sdhc_softc __softc; +static struct sdhc_softc __softc MEM2_BSS; void sdhc_irq(void) { diff --git a/sdmmc.c b/sdmmc.c index 6fdd365..dc96cd3 100644 --- a/sdmmc.c +++ b/sdmmc.c @@ -47,12 +47,14 @@ struct sdmmc_card { int no; int inserted; int sdhc_blockmode; + int selected; + int new_card; // set to 1 everytime a new card is inserted u32 cid; u16 rca; }; -static struct sdmmc_card cards[SDHC_MAX_HOSTS]; +static struct sdmmc_card cards[SDHC_MAX_HOSTS] MEM2_BSS; static int n_cards = 0; static inline int sdmmc_host_reset(struct sdmmc_card *card) @@ -129,6 +131,7 @@ void sdmmc_needs_discover(struct device *dev) DPRINTF(0, ("sdmmc: card %d needs discovery.\n", no)); sdmmc_host_reset(c); + c->new_card = 1; if (!sdmmc_host_card_detect(c)) { DPRINTF(1, ("sdmmc: card %d (no longer?) inserted.\n", no)); @@ -209,6 +212,11 @@ void sdmmc_needs_discover(struct device *dev) goto out_power; } + if (ISSET(MMC_R1(cmd.c_resp), SD_OCR_SDHC_CAP)) + c->sdhc_blockmode = 1; + else + c->sdhc_blockmode = 0; + DPRINTF(2, ("sdmmc: MMC_ALL_SEND_CID\n")); memset(&cmd, 0, sizeof(cmd)); cmd.c_opcode = MMC_ALL_SEND_CID; @@ -237,7 +245,23 @@ void sdmmc_needs_discover(struct device *dev) c->rca = MMC_R1(cmd.c_resp)>>16; DPRINTF(2, ("sdmmc: rca: %08x\n", c->rca)); + + c->selected = 0; c->inserted = 1; + + sdmmc_select(dev); + DPRINTF(2, ("sdmmc: MMC_SET_BLOCKLEN\n")); + memset(&cmd, 0, sizeof(cmd)); + cmd.c_opcode = MMC_SET_BLOCKLEN; + cmd.c_arg = SDMMC_DEFAULT_BLOCKLEN; + cmd.c_flags = SCF_RSP_R1; + sdmmc_host_exec_command(c, &cmd); + if (cmd.c_error) { + gecko_printf("sdmmc: MMC_SET_BLOCKLEN failed with %d for card %d\n", + cmd.c_error, no); + c->inserted = c->selected = 0; + goto out_clock; + } return; out_clock: @@ -286,3 +310,88 @@ out: #endif } +int sdmmc_select(struct device *dev) +{ + int no = (int)dev; + struct sdmmc_card *c = &cards[no]; + struct sdmmc_command cmd; + + DPRINTF(2, ("sdmmc: MMC_SELECT_CARD\n")); + memset(&cmd, 0, sizeof(cmd)); + cmd.c_opcode = MMC_SELECT_CARD; + cmd.c_arg = ((u32)c->rca)<<16;; + cmd.c_flags = SCF_RSP_R1; + sdmmc_host_exec_command(c, &cmd); + if (cmd.c_error) { + gecko_printf("sdmmc: MMC_SELECT card failed with %d for %d.\n", + cmd.c_error, no); + return -1; + } + + c->selected = 1; + return 0; +} + +int sdmmc_check_card(struct device *dev) +{ + int no = (int)dev; + struct sdmmc_card *c = &cards[no]; + if (c->inserted == 0) + return SDMMC_NO_CARD; + if (c->new_card == 1) + return SDMMC_NEW_CARD; + return SDMMC_INSERTED; +} + +void sdmmc_ack_card(struct device *dev) +{ + int no = (int)dev; + struct sdmmc_card *c = &cards[no]; + c->new_card = 0; +} + +int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data) +{ + int no = (int)dev; + struct sdmmc_card *c = &cards[no]; + struct sdmmc_command cmd; + + if (c->inserted == 0) { + gecko_printf("sdmmc: READ: no card inserted.\n"); + return -1; + } + + if (c->selected == 0) { + if (sdmmc_select(dev) < 0) { + gecko_printf("sdmmc: READ: cannot select card.\n"); + return -1; + } + } + + if (c->new_card == 1) { + gecko_printf("sdmmc: new card inserted but not acknowledged yet.\n"); + return -1; + } + + DPRINTF(2, ("sdmmc: MMC_READ_BLOCK_MULTIPLE\n")); + memset(&cmd, 0, sizeof(cmd)); + cmd.c_opcode = MMC_READ_BLOCK_MULTIPLE; + if (c->sdhc_blockmode) + cmd.c_arg = blk_start; + else + cmd.c_arg = blk_start * SDMMC_DEFAULT_BLOCKLEN; + cmd.c_data = data; + cmd.c_datalen = blk_count * SDMMC_DEFAULT_BLOCKLEN; + cmd.c_blklen = SDMMC_DEFAULT_BLOCKLEN; + cmd.c_flags = SCF_RSP_R1 | SCF_CMD_READ; + sdmmc_host_exec_command(c, &cmd); + + if (cmd.c_error) { + gecko_printf("sdmmc: MMC_READ_BLOCK_MULTIPLE failed for " + "card %d with %d", no, cmd.c_error); + return -1; + } + gecko_printf("success!!\n"); + + return 0; +} diff --git a/sdmmc.h b/sdmmc.h index 9ca8ec1..d98e9f9 100644 --- a/sdmmc.h +++ b/sdmmc.h @@ -22,12 +22,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef __SDMMC_H__ #define __SDMMC_H__ 1 -#include "sdmmcvar.h" +#include "bsdtypes.h" #include "sdmmcchip.h" +#include "sdmmcvar.h" #define SDMMC_DEFAULT_CLOCK 25000 +#define SDMMC_DEFAULT_BLOCKLEN 512 + +#define SDMMC_NO_CARD 1 +#define SDMMC_NEW_CARD 2 +#define SDMMC_INSERTED 3 + +// HACK +#define SDMMC_DEFAULT_DEVICE ((struct device *)0) struct device *sdmmc_attach(struct sdmmc_chip_functions *functions, sdmmc_chipset_handle_t handle, const char *name, int no); void sdmmc_needs_discover(struct device *dev); +int sdmmc_select(struct device *dev); +int sdmmc_check_card(struct device *dev); +void sdmmc_ack_card(struct device *dev); +int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data); #endif