/** * Erase a block range on the MMC * @param: dbc Pointer to doorbell command area. * @param: fd file descriptor of backing file. * @param: start start block number * @param: end end block number */ static void mmc_erase_group(struct doorbell_command_t *dbc, int fd, unsigned start, unsigned end) { unsigned char *buf; const off_t s = mmc_bounded_seek(dbc, fd, start, end + 1 - start); if (s <= (off_t)-1) { command_failure(dbc, dbc->device_id); return; } buf = malloc(mmc_blocklen); if (buf == NULL) { command_failure(dbc, dbc->device_id); return; } memset(buf, '\0', sizeof(buf)); while (dbc->result == 0 && start <= end) { mmc_write_block(dbc, fd, start, 1, buf); ++start; } free(buf); }
DRESULT diskWrite (BYTE disk __attribute__ ((unused)), const BYTE *buff, DWORD sector, BYTE count) { DWORD res = 0; int i; if (gDiskStatus & DSTATUS_NOINIT) return DRESULT_NOTRDY; if (gDiskStatus & DSTATUS_PROTECT) return DRESULT_WRPRT; if (!count) return DRESULT_PARERR; //printf("diskWrite ( %d , %d )\n", sector, count); for (i = 0; i < count; i++) { if (res == 0) memcpy(MMCWRData, buff + i*512, 512); else break; res = mmc_write_block(i+sector); print("write block "); printNum(i); print("\n"); } if (res == 0) return DRESULT_OK; else return DRESULT_ERROR; }
void mmc_command(struct doorbell_command_t *dbc) { /* See sandbox_mmc.c for the command_data[] layout. */ int fd; unsigned command = dbc->command_data[0]; fd = open_mmc_file(get_mmc_device(dbc)); if (fd == -1) { fprintf(stderr, "Unable to open/create '%s'\n", mmc_file[get_mmc_device(dbc)]); command_failure(dbc, dbc->device_id); return; } mmc_clear_results(dbc); switch (command) { case MMC_CMD_GO_IDLE_STATE: /* NOP */ break; case MMC_CMD_SEND_OP_COND: mmc_send_op_cond(dbc); break; case MMC_CMD_ALL_SEND_CID: mmc_send_cid_register(dbc); break; case MMC_CMD_SET_RELATIVE_ADDR: /* SD_CMD_SEND_RELATIVE_ADDR */ dbc->command_data[8] = 0x500; break; case MMC_CMD_SWITCH: /* NOP */ break; case MMC_CMD_SELECT_CARD: dbc->command_data[8] = MMC_STATUS_RDY_FOR_DATA | MMC_STATUS; break; case MMC_CMD_SEND_EXT_CSD: if (dbc->command_data[4] == 0) /* SD_CMD_SEND_IF_COND */ command_timeout(dbc, dbc->device_id); else /* MMC_CMD_SEND_EXT_CSD */ mmc_send_ext_csd_register(dbc); break; case MMC_CMD_SEND_CSD: mmc_send_csd_register(dbc); break; case MMC_CMD_STOP_TRANSMISSION: verbose("%s: ignored '%d' command\n", __func__, command); break; case MMC_CMD_SEND_STATUS: dbc->command_data[8] = MMC_STATUS_RDY_FOR_DATA | MMC_STATUS; break; case MMC_CMD_SET_BLOCKLEN: mmc_set_blocklen(dbc, dbc->command_data[2]); break; case MMC_CMD_READ_SINGLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; mmc_read_block(dbc, fd, start, 1, buf); break; } case MMC_CMD_READ_MULTIPLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; const unsigned len = dbc->command_data[6]; mmc_read_block(dbc, fd, start, len, buf); break; } case MMC_CMD_WRITE_SINGLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; mmc_write_block(dbc, fd, start, 1, buf); break; } case MMC_CMD_WRITE_MULTIPLE_BLOCK: { const unsigned start = dbc->command_data[2]; void *buf = (void *)(uintptr_t)dbc->command_data[4]; const unsigned len = dbc->command_data[6]; mmc_write_block(dbc, fd, start, len, buf); break; } case MMC_CMD_ERASE_GROUP_START: mmc_erase_group_start(dbc, dbc->command_data[2]); break; case MMC_CMD_ERASE_GROUP_END: mmc_erase_group_end(dbc, dbc->command_data[2]); break; case MMC_CMD_ERASE: mmc_erase_group(dbc, fd, mmc_erase_group_start_block, mmc_erase_group_end_block); break; case SD_CMD_APP_SEND_OP_COND: dbc->command_data[8] = 0; command_timeout(dbc, dbc->device_id); break; case SD_CMD_APP_SEND_SCR: /* Do not support higher clock speeds */ command_failure(dbc, dbc->device_id); break; case MMC_CMD_APP_CMD: dbc->command_data[8] = OCR_BUSY | OCR_HCS; break; default: mmc_unknown_command(dbc, command); break; } close(fd); }