diff options
Diffstat (limited to 'hw/sd/sd.c')
-rw-r--r-- | hw/sd/sd.c | 2020 |
1 files changed, 1260 insertions, 760 deletions
@@ -2,6 +2,8 @@ * SD Memory Card emulation as defined in the "SD Memory Card Physical * layer specification, Version 2.00." * + * eMMC emulation defined in "JEDEC Standard No. 84-A43" + * * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> * Copyright (c) 2007 CodeSourcery * Copyright (c) 2018 Philippe Mathieu-Daudé <f4bug@amsat.org> @@ -35,9 +37,8 @@ #include "qemu/cutils.h" #include "hw/irq.h" #include "hw/registerfields.h" -#include "sysemu/block-backend.h" +#include "system/block-backend.h" #include "hw/sd/sd.h" -#include "hw/sd/sdcard_legacy.h" #include "migration/vmstate.h" #include "qapi/error.h" #include "qemu/bitmap.h" @@ -46,6 +47,7 @@ #include "qemu/error-report.h" #include "qemu/timer.h" #include "qemu/log.h" +#include "qemu/guest-random.h" #include "qemu/module.h" #include "sdmmc-internal.h" #include "trace.h" @@ -68,6 +70,14 @@ typedef enum { sd_illegal = -2, } sd_rsp_type_t; +typedef enum { + sd_spi, + sd_bc, /* broadcast -- no response */ + sd_bcr, /* broadcast with response */ + sd_ac, /* addressed -- no data transfer */ + sd_adtc, /* addressed with data transfer */ +} sd_cmd_type_t; + enum SDCardModes { sd_inactive, sd_card_identification_mode, @@ -75,33 +85,40 @@ enum SDCardModes { }; enum SDCardStates { - sd_inactive_state = -1, - sd_idle_state = 0, - sd_ready_state, - sd_identification_state, - sd_standby_state, - sd_transfer_state, - sd_sendingdata_state, - sd_receivingdata_state, - sd_programming_state, - sd_disconnect_state, + sd_waitirq_state = -2, /* emmc */ + sd_inactive_state = -1, + + sd_idle_state = 0, + sd_ready_state = 1, + sd_identification_state = 2, + sd_standby_state = 3, + sd_transfer_state = 4, + sd_sendingdata_state = 5, + sd_receivingdata_state = 6, + sd_programming_state = 7, + sd_disconnect_state = 8, + sd_bus_test_state = 9, /* emmc */ + sd_sleep_state = 10, /* emmc */ + sd_io_state = 15 /* sd */ }; +#define SDMMC_CMD_MAX 64 + typedef sd_rsp_type_t (*sd_cmd_handler)(SDState *sd, SDRequest req); typedef struct SDProto { const char *name; - sd_cmd_handler cmd[SDMMC_CMD_MAX]; - sd_cmd_handler acmd[SDMMC_CMD_MAX]; + struct { + const unsigned class; + const sd_cmd_type_t type; + const char *name; + sd_cmd_handler handler; + } cmd[SDMMC_CMD_MAX], acmd[SDMMC_CMD_MAX]; } SDProto; struct SDState { DeviceState parent_obj; - /* If true, created by sd_init() for a non-qdevified caller */ - /* TODO purge them with fire */ - bool me_no_qdev_me_kill_mammoth_with_rocks; - /* SD Memory Card Registers */ uint32_t ocr; uint8_t scr[8]; @@ -110,11 +127,22 @@ struct SDState { uint16_t rca; uint32_t card_status; uint8_t sd_status[64]; + union { + uint8_t ext_csd[512]; + struct { + uint8_t ext_csd_rw[192]; /* Modes segment */ + uint8_t ext_csd_ro[320]; /* Properties segment */ + }; + }; /* Static properties */ uint8_t spec_version; + uint64_t boot_part_size; BlockBackend *blk; + uint8_t boot_config; + + const SDProto *proto; /* Runtime changeables */ @@ -133,36 +161,35 @@ struct SDState { uint32_t pwd_len; uint8_t function_group[6]; uint8_t current_cmd; + const char *last_cmd_name; /* True if we will handle the next command as an ACMD. Note that this does * *not* track the APP_CMD status bit! */ bool expecting_acmd; uint32_t blk_written; + uint64_t data_start; uint32_t data_offset; + size_t data_size; uint8_t data[512]; - qemu_irq readonly_cb; - qemu_irq inserted_cb; QEMUTimer *ocr_power_timer; - bool enable; uint8_t dat_lines; bool cmd_line; }; static void sd_realize(DeviceState *dev, Error **errp); -static const struct SDProto *sd_proto(SDState *sd) -{ - SDCardClass *sc = SD_CARD_GET_CLASS(sd); - - return sc->proto; -} - static const SDProto sd_proto_spi; +static const SDProto sd_proto_emmc; static bool sd_is_spi(SDState *sd) { - return sd_proto(sd) == &sd_proto_spi; + return sd->proto == &sd_proto_spi; +} + +static bool sd_is_emmc(SDState *sd) +{ + return sd->proto == &sd_proto_emmc; } static const char *sd_version_str(enum SDPhySpecificationVersion version) @@ -198,13 +225,19 @@ static const char *sd_state_name(enum SDCardStates state) [sd_standby_state] = "standby", [sd_transfer_state] = "transfer", [sd_sendingdata_state] = "sendingdata", + [sd_bus_test_state] = "bus-test", [sd_receivingdata_state] = "receivingdata", [sd_programming_state] = "programming", [sd_disconnect_state] = "disconnect", + [sd_sleep_state] = "sleep", + [sd_io_state] = "i/o" }; if (state == sd_inactive_state) { return "inactive"; } + if (state == sd_waitirq_state) { + return "wait-irq"; + } assert(state < ARRAY_SIZE(state_name)); return state_name[state]; } @@ -230,14 +263,40 @@ static const char *sd_response_name(sd_rsp_type_t rsp) return response_name[rsp]; } +static const char *sd_cmd_name(SDState *sd, uint8_t cmd) +{ + static const char *cmd_abbrev[SDMMC_CMD_MAX] = { + [18] = "READ_MULTIPLE_BLOCK", + [25] = "WRITE_MULTIPLE_BLOCK", + }; + const SDProto *sdp = sd->proto; + + if (sdp->cmd[cmd].handler) { + assert(!cmd_abbrev[cmd]); + return sdp->cmd[cmd].name; + } + return cmd_abbrev[cmd] ? cmd_abbrev[cmd] : "UNKNOWN_CMD"; +} + +static const char *sd_acmd_name(SDState *sd, uint8_t cmd) +{ + const SDProto *sdp = sd->proto; + + if (sdp->acmd[cmd].handler) { + return sdp->acmd[cmd].name; + } + + return "UNKNOWN_ACMD"; +} + static uint8_t sd_get_dat_lines(SDState *sd) { - return sd->enable ? sd->dat_lines : 0; + return sd->dat_lines; } static bool sd_get_cmd_line(SDState *sd) { - return sd->enable ? sd->cmd_line : false; + return sd->cmd_line; } static void sd_set_voltage(SDState *sd, uint16_t millivolts) @@ -278,27 +337,6 @@ static void sd_set_mode(SDState *sd) } } -static const sd_cmd_type_t sd_cmd_type[SDMMC_CMD_MAX] = { - sd_bc, sd_none, sd_bcr, sd_bcr, sd_none, sd_none, sd_none, sd_ac, - sd_bcr, sd_ac, sd_ac, sd_adtc, sd_ac, sd_ac, sd_none, sd_ac, - /* 16 */ - sd_ac, sd_adtc, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, - sd_adtc, sd_adtc, sd_adtc, sd_adtc, sd_ac, sd_ac, sd_adtc, sd_none, - /* 32 */ - sd_ac, sd_ac, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_none, - sd_none, sd_none, sd_bc, sd_none, sd_none, sd_none, sd_none, sd_none, - /* 48 */ - sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac, - sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, -}; - -static const int sd_cmd_class[SDMMC_CMD_MAX] = { - 0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, - 5, 5, 10, 10, 10, 10, 5, 9, 9, 9, 7, 7, 7, 7, 7, 7, - 7, 7, 10, 7, 9, 9, 9, 8, 8, 10, 8, 8, 8, 8, 8, 8, -}; - static uint8_t sd_crc7(const void *message, size_t width) { int i, bit; @@ -417,6 +455,23 @@ static void sd_set_cid(SDState *sd) sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; } +static void emmc_set_cid(SDState *sd) +{ + sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ + sd->cid[1] = 0b01; /* CBX: soldered BGA */ + sd->cid[2] = OID[0]; /* OEM/Application ID (OID) */ + sd->cid[3] = PNM[0]; /* Fake product name (PNM) */ + sd->cid[4] = PNM[1]; + sd->cid[5] = PNM[2]; + sd->cid[6] = PNM[3]; + sd->cid[7] = PNM[4]; + sd->cid[8] = PNM[4]; + sd->cid[9] = PRV; /* Fake product revision (PRV) */ + stl_be_p(&sd->cid[10], 0xdeadbeef); /* Fake serial number (PSN) */ + sd->cid[14] = (MDT_MON << 4) | (MDT_YR - 1997); /* Manufacture date (MDT) */ + sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; +} + /* Card-Specific Data register */ #define HWBLOCK_SHIFT 9 /* 512 bytes */ @@ -430,6 +485,79 @@ static const uint8_t sd_csd_rw_mask[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, }; +static void emmc_set_ext_csd(SDState *sd, uint64_t size) +{ + uint32_t sectcount = size >> HWBLOCK_SHIFT; + + memset(sd->ext_csd, 0, sizeof(sd->ext_csd)); /* FIXME only RW at reset */ + + /* Properties segment (RO) */ + sd->ext_csd[EXT_CSD_S_CMD_SET] = 0b1; /* supported command sets */ + sd->ext_csd[EXT_CSD_BOOT_INFO] = 0x0; /* Boot information */ + /* Boot partition size. 128KB unit */ + sd->ext_csd[EXT_CSD_BOOT_MULT] = sd->boot_part_size / (128 * KiB); + sd->ext_csd[EXT_CSD_ACC_SIZE] = 0x1; /* Access size */ + sd->ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] = 0x01; /* HC Erase unit size */ + sd->ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT] = 0x01; /* HC erase timeout */ + sd->ext_csd[EXT_CSD_REL_WR_SEC_C] = 0x1; /* Reliable write sector count */ + sd->ext_csd[EXT_CSD_HC_WP_GRP_SIZE] = 0x01; /* HC write protect group size */ + sd->ext_csd[EXT_CSD_S_C_VCC] = 0x01; /* Sleep current VCC */ + sd->ext_csd[EXT_CSD_S_C_VCCQ] = 0x01; /* Sleep current VCCQ */ + sd->ext_csd[EXT_CSD_S_A_TIMEOUT] = 0x01; /* Sleep/Awake timeout */ + stl_le_p(&sd->ext_csd[EXT_CSD_SEC_CNT], sectcount); /* Sector count */ + sd->ext_csd[210] = 0x46; /* Min write perf for 8bit@52Mhz */ + sd->ext_csd[209] = 0x46; /* Min read perf for 8bit@52Mhz */ + sd->ext_csd[208] = 0x46; /* Min write perf for 4bit@52Mhz */ + sd->ext_csd[207] = 0x46; /* Min read perf for 4bit@52Mhz */ + sd->ext_csd[206] = 0x46; /* Min write perf for 4bit@26Mhz */ + sd->ext_csd[205] = 0x46; /* Min read perf for 4bit@26Mhz */ + sd->ext_csd[EXT_CSD_CARD_TYPE] = 0b11; + sd->ext_csd[EXT_CSD_STRUCTURE] = 2; + sd->ext_csd[EXT_CSD_REV] = 3; + + /* Mode segment (RW) */ + sd->ext_csd[EXT_CSD_PART_CONFIG] = sd->boot_config; +} + +static void emmc_set_csd(SDState *sd, uint64_t size) +{ + int hwblock_shift = HWBLOCK_SHIFT; + uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1; + uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1; + + sd->csd[0] = (3 << 6) | (4 << 2); /* Spec v4.3 with EXT_CSD */ + sd->csd[1] = (1 << 3) | 6; /* Asynchronous data access time: 1ms */ + sd->csd[2] = 0x00; + sd->csd[3] = (1 << 3) | 3;; /* Maximum bus clock frequency: 100MHz */ + sd->csd[4] = 0x0f; + if (size <= 2 * GiB) { + /* use 1k blocks */ + uint32_t csize1k = (size >> (CMULT_SHIFT + 10)) - 1; + sd->csd[5] = 0x5a; + sd->csd[6] = 0x80 | ((csize1k >> 10) & 0xf); + sd->csd[7] = (csize1k >> 2) & 0xff; + } else { /* >= 2GB : size stored in ext CSD, block addressing */ + sd->csd[5] = 0x59; + sd->csd[6] = 0x8f; + sd->csd[7] = 0xff; + sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1); + } + sd->csd[8] = 0xff; + sd->csd[9] = 0xfc | /* Max. write current */ + ((CMULT_SHIFT - 2) >> 1); + sd->csd[10] = 0x40 | /* Erase sector size */ + (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1); + sd->csd[11] = 0x00 | /* Write protect group size */ + ((sectsize << 7) & 0x80) | wpsize; + sd->csd[12] = 0x90 | /* Write speed factor */ + (hwblock_shift >> 2); + sd->csd[13] = 0x20 | /* Max. write data block length */ + ((hwblock_shift << 6) & 0xc0); + sd->csd[14] = 0x00; + sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1; + emmc_set_ext_csd(sd, size); +} + static void sd_set_csd(SDState *sd, uint64_t size) { int hwblock_shift = HWBLOCK_SHIFT; @@ -490,17 +618,27 @@ static void sd_set_csd(SDState *sd, uint64_t size) /* Relative Card Address register */ -static void sd_set_rca(SDState *sd) +static void sd_set_rca(SDState *sd, uint16_t value) { - sd->rca += 0x4567; + trace_sdcard_set_rca(value); + sd->rca = value; } static uint16_t sd_req_get_rca(SDState *s, SDRequest req) { - if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc) { + switch (s->proto->cmd[req.cmd].type) { + case sd_ac: + case sd_adtc: return req.arg >> 16; + case sd_spi: + default: + g_assert_not_reached(); } - return 0; +} + +static bool sd_req_rca_same(SDState *s, SDRequest req) +{ + return sd_req_get_rca(s, req) == s->rca; } /* Card Status register */ @@ -508,6 +646,7 @@ static uint16_t sd_req_get_rca(SDState *s, SDRequest req) FIELD(CSR, AKE_SEQ_ERROR, 3, 1) FIELD(CSR, APP_CMD, 5, 1) FIELD(CSR, FX_EVENT, 6, 1) +FIELD(CSR, SWITCH_ERROR, 7, 1) FIELD(CSR, READY_FOR_DATA, 8, 1) FIELD(CSR, CURRENT_STATE, 9, 4) FIELD(CSR, ERASE_RESET, 13, 1) @@ -558,7 +697,7 @@ FIELD(CSR, OUT_OF_RANGE, 31, 1) static void sd_set_cardstatus(SDState *sd) { - sd->card_status = 0x00000100; + sd->card_status = READY_FOR_DATA; } static void sd_set_sdstatus(SDState *sd) @@ -566,6 +705,21 @@ static void sd_set_sdstatus(SDState *sd) memset(sd->sd_status, 0, 64); } +static const uint8_t sd_tuning_block_pattern4[64] = { + /* + * See: Physical Layer Simplified Specification Version 3.01, + * Table 4-2. + */ + 0xff, 0x0f, 0xff, 0x00, 0x0f, 0xfc, 0xc3, 0xcc, + 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, + 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, + 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, + 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, + 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, + 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, + 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde +}; + static int sd_req_crc_validate(SDRequest *req) { uint8_t buffer[5]; @@ -605,12 +759,52 @@ static void sd_response_r7_make(SDState *sd, uint8_t *response) stl_be_p(response, sd->vhs); } +static uint32_t sd_blk_len(SDState *sd) +{ + if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) { + return 1 << HWBLOCK_SHIFT; + } + return sd->blk_len; +} + +/* + * This requires a disk image that has two boot partitions inserted at the + * beginning of it. The size of the boot partitions is the "boot-size" + * property. + */ +static uint32_t sd_bootpart_offset(SDState *sd) +{ + unsigned partition_access; + + if (!sd->boot_part_size || !sd_is_emmc(sd)) { + return 0; + } + + partition_access = sd->ext_csd[EXT_CSD_PART_CONFIG] + & EXT_CSD_PART_CONFIG_ACC_MASK; + switch (partition_access) { + case EXT_CSD_PART_CONFIG_ACC_DEFAULT: + return sd->boot_part_size * 2; + case EXT_CSD_PART_CONFIG_ACC_BOOT0: + return 0; + case EXT_CSD_PART_CONFIG_ACC_BOOT0 + 1: + return sd->boot_part_size * 1; + default: + g_assert_not_reached(); + } +} + static uint64_t sd_req_get_address(SDState *sd, SDRequest req) { + uint64_t addr; + if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) { - return (uint64_t) req.arg << HWBLOCK_SHIFT; + addr = (uint64_t) req.arg << HWBLOCK_SHIFT; + } else { + addr = req.arg; } - return req.arg; + trace_sdcard_req_addr(req.arg, addr); + return addr; } static inline uint64_t sd_addr_to_wpnum(uint64_t addr) @@ -620,7 +814,8 @@ static inline uint64_t sd_addr_to_wpnum(uint64_t addr) static void sd_reset(DeviceState *dev) { - SDState *sd = SD_CARD(dev); + SDState *sd = SDMMC_COMMON(dev); + SDCardClass *sc = SDMMC_COMMON_GET_CLASS(sd); uint64_t size; uint64_t sect; @@ -631,18 +826,21 @@ static void sd_reset(DeviceState *dev) sect = 0; } size = sect << HWBLOCK_SHIFT; + if (sd_is_emmc(sd)) { + size -= sd->boot_part_size * 2; + } sect = sd_addr_to_wpnum(size) + 1; sd->state = sd_idle_state; /* card registers */ - sd->rca = 0x0000; + sd->rca = sd_is_emmc(sd) ? 0x0001 : 0x0000; sd->size = size; sd_set_ocr(sd); sd_set_scr(sd); - sd_set_cid(sd); - sd_set_csd(sd, size); + sc->set_cid(sd); + sc->set_csd(sd, size); sd_set_cardstatus(sd); sd_set_sdstatus(sd); @@ -686,17 +884,10 @@ static void sd_cardchange(void *opaque, bool load, Error **errp) trace_sdcard_ejected(); } - if (sd->me_no_qdev_me_kill_mammoth_with_rocks) { - qemu_set_irq(sd->inserted_cb, inserted); - if (inserted) { - qemu_set_irq(sd->readonly_cb, readonly); - } - } else { - sdbus = SD_BUS(qdev_get_parent_bus(dev)); - sdbus_set_inserted(sdbus, inserted); - if (inserted) { - sdbus_set_readonly(sdbus, readonly); - } + sdbus = SD_BUS(qdev_get_parent_bus(dev)); + sdbus_set_inserted(sdbus, inserted); + if (inserted) { + sdbus_set_readonly(sdbus, readonly); } } @@ -724,6 +915,24 @@ static const VMStateDescription sd_ocr_vmstate = { }, }; +static bool vmstate_needed_for_emmc(void *opaque) +{ + SDState *sd = opaque; + + return sd_is_emmc(sd); +} + +static const VMStateDescription emmc_extcsd_vmstate = { + .name = "sd-card/ext_csd_modes-state", + .version_id = 1, + .minimum_version_id = 1, + .needed = vmstate_needed_for_emmc, + .fields = (const VMStateField[]) { + VMSTATE_UINT8_ARRAY(ext_csd_rw, SDState, 192), + VMSTATE_END_OF_LIST() + }, +}; + static int sd_vmstate_pre_load(void *opaque) { SDState *sd = opaque; @@ -766,60 +975,20 @@ static const VMStateDescription sd_vmstate = { VMSTATE_UINT32(data_offset, SDState), VMSTATE_UINT8_ARRAY(data, SDState, 512), VMSTATE_UNUSED_V(1, 512), - VMSTATE_BOOL(enable, SDState), + VMSTATE_UNUSED(1), VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * const []) { &sd_ocr_vmstate, + &emmc_extcsd_vmstate, NULL }, }; -/* Legacy initialization function for use by non-qdevified callers */ -SDState *sd_init(BlockBackend *blk, bool is_spi) -{ - Object *obj; - DeviceState *dev; - SDState *sd; - Error *err = NULL; - - obj = object_new(is_spi ? TYPE_SD_CARD_SPI : TYPE_SD_CARD); - dev = DEVICE(obj); - if (!qdev_prop_set_drive_err(dev, "drive", blk, &err)) { - error_reportf_err(err, "sd_init failed: "); - return NULL; - } - - /* - * Realizing the device properly would put it into the QOM - * composition tree even though it is not plugged into an - * appropriate bus. That's a no-no. Hide the device from - * QOM/qdev, and call its qdev realize callback directly. - */ - object_ref(obj); - object_unparent(obj); - sd_realize(dev, &err); - if (err) { - error_reportf_err(err, "sd_init failed: "); - return NULL; - } - - sd = SD_CARD(dev); - sd->me_no_qdev_me_kill_mammoth_with_rocks = true; - return sd; -} - -void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert) -{ - sd->readonly_cb = readonly; - sd->inserted_cb = insert; - qemu_set_irq(readonly, sd->blk ? !blk_is_writable(sd->blk) : 0); - qemu_set_irq(insert, sd->blk ? blk_is_inserted(sd->blk) : 0); -} - static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) { trace_sdcard_read_block(addr, len); + addr += sd_bootpart_offset(sd); if (!sd->blk || blk_pread(sd->blk, addr, len, sd->data, 0) < 0) { fprintf(stderr, "sd_blk_read: read error on host side\n"); } @@ -828,14 +997,12 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) { trace_sdcard_write_block(addr, len); + addr += sd_bootpart_offset(sd); if (!sd->blk || blk_pwrite(sd->blk, addr, len, sd->data, 0) < 0) { fprintf(stderr, "sd_blk_write: write error on host side\n"); } } -#define APP_READ_BLOCK(a, len) memset(sd->data, 0xec, len) -#define APP_WRITE_BLOCK(a, len) - static void sd_erase(SDState *sd) { uint64_t erase_start = sd->erase_start; @@ -912,6 +1079,47 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) return ret; } +enum ExtCsdAccessMode { + EXT_CSD_ACCESS_MODE_COMMAND_SET = 0, + EXT_CSD_ACCESS_MODE_SET_BITS = 1, + EXT_CSD_ACCESS_MODE_CLEAR_BITS = 2, + EXT_CSD_ACCESS_MODE_WRITE_BYTE = 3 +}; + +static void emmc_function_switch(SDState *sd, uint32_t arg) +{ + uint8_t access = extract32(arg, 24, 2); + uint8_t index = extract32(arg, 16, 8); + uint8_t value = extract32(arg, 8, 8); + uint8_t b = sd->ext_csd[index]; + + trace_sdcard_switch(access, index, value, extract32(arg, 0, 2)); + + if (index >= 192) { + qemu_log_mask(LOG_GUEST_ERROR, "MMC switching illegal offset\n"); + sd->card_status |= R_CSR_SWITCH_ERROR_MASK; + return; + } + + switch (access) { + case EXT_CSD_ACCESS_MODE_COMMAND_SET: + qemu_log_mask(LOG_UNIMP, "MMC Command set switching not supported\n"); + return; + case EXT_CSD_ACCESS_MODE_SET_BITS: + b |= value; + break; + case EXT_CSD_ACCESS_MODE_CLEAR_BITS: + b &= ~value; + break; + case EXT_CSD_ACCESS_MODE_WRITE_BYTE: + b = value; + break; + } + + trace_sdcard_ext_csd_update(index, sd->ext_csd[index], b); + sd->ext_csd[index] = b; +} + static void sd_function_switch(SDState *sd, uint32_t arg) { int i, mode, new_func; @@ -1035,7 +1243,7 @@ static bool address_in_range(SDState *sd, const char *desc, static sd_rsp_type_t sd_invalid_state_for_cmd(SDState *sd, SDRequest req) { qemu_log_mask(LOG_GUEST_ERROR, "%s: CMD%i in a wrong state: %s (spec %s)\n", - sd_proto(sd)->name, req.cmd, sd_state_name(sd->state), + sd->proto->name, req.cmd, sd_state_name(sd->state), sd_version_str(sd->spec_version)); return sd_illegal; @@ -1044,7 +1252,7 @@ static sd_rsp_type_t sd_invalid_state_for_cmd(SDState *sd, SDRequest req) static sd_rsp_type_t sd_invalid_mode_for_cmd(SDState *sd, SDRequest req) { qemu_log_mask(LOG_GUEST_ERROR, "%s: CMD%i in a wrong mode: %s (spec %s)\n", - sd_proto(sd)->name, req.cmd, sd_mode_name(sd->mode), + sd->proto->name, req.cmd, sd_mode_name(sd->mode), sd_version_str(sd->spec_version)); return sd_illegal; @@ -1053,25 +1261,78 @@ static sd_rsp_type_t sd_invalid_mode_for_cmd(SDState *sd, SDRequest req) static sd_rsp_type_t sd_cmd_illegal(SDState *sd, SDRequest req) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown CMD%i for spec %s\n", - sd_proto(sd)->name, req.cmd, + sd->proto->name, req.cmd, sd_version_str(sd->spec_version)); return sd_illegal; } /* Commands that are recognised but not yet implemented. */ -__attribute__((unused)) static sd_rsp_type_t sd_cmd_unimplemented(SDState *sd, SDRequest req) { qemu_log_mask(LOG_UNIMP, "%s: CMD%i not implemented\n", - sd_proto(sd)->name, req.cmd); + sd->proto->name, req.cmd); return sd_illegal; } +static sd_rsp_type_t sd_cmd_optional(SDState *sd, SDRequest req) +{ + qemu_log_mask(LOG_UNIMP, "%s: Optional CMD%i not implemented\n", + sd->proto->name, req.cmd); + + return sd_illegal; +} + +/* Configure fields for following sd_generic_write_byte() calls */ +static sd_rsp_type_t sd_cmd_to_receivingdata(SDState *sd, SDRequest req, + uint64_t start, size_t size) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + sd->state = sd_receivingdata_state; + sd->data_start = start; + sd->data_offset = 0; + /* sd->data[] used as receive buffer */ + sd->data_size = size ?: sizeof(sd->data); + return sd_r1; +} + +/* Configure fields for following sd_generic_read_byte() calls */ +static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req, + uint64_t start, + const void *data, size_t size) +{ + if (sd->state != sd_transfer_state) { + sd_invalid_state_for_cmd(sd, req); + } + + sd->state = sd_sendingdata_state; + sd->data_start = start; + sd->data_offset = 0; + if (data) { + assert(size > 0 && size <= sizeof(sd->data)); + memcpy(sd->data, data, size); + } + if (size) { + sd->data_size = size; + } + return sd_r1; +} + /* CMD0 */ static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, SDRequest req) { + if (sd->state == sd_sleep_state) { + switch (req.arg) { + case 0x00000000: + case 0xf0f0f0f0: + break; + default: + return sd_r0; + } + } if (sd->state != sd_inactive_state) { sd->state = sd_idle_state; sd_reset(DEVICE(sd)); @@ -1103,11 +1364,14 @@ static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, SDRequest req) /* CMD3 */ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req) { + uint16_t random_rca; + switch (sd->state) { case sd_identification_state: case sd_standby_state: sd->state = sd_standby_state; - sd_set_rca(sd); + qemu_guest_getrandom_nofail(&random_rca, sizeof(random_rca)); + sd_set_rca(sd, random_rca); return sd_r6; default: @@ -1115,23 +1379,295 @@ static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req) } } -/* CMD19 */ -static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req) +static sd_rsp_type_t emmc_cmd_SET_RELATIVE_ADDR(SDState *sd, SDRequest req) { - if (sd->spec_version < SD_PHY_SPECv3_01_VERS) { + switch (sd->state) { + case sd_identification_state: + case sd_standby_state: + sd->state = sd_standby_state; + sd_set_rca(sd, req.arg >> 16); + return sd_r1; + + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + +/* CMD5 */ +static sd_rsp_type_t emmc_cmd_sleep_awake(SDState *sd, SDRequest req) +{ + bool do_sleep = extract32(req.arg, 15, 1); + + switch (sd->state) { + case sd_sleep_state: + if (!do_sleep) { + /* Awake */ + sd->state = sd_standby_state; + } + return sd_r1b; + + case sd_standby_state: + if (do_sleep) { + sd->state = sd_sleep_state; + } + return sd_r1b; + + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + +/* CMD6 */ +static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, SDRequest req) +{ + if (sd->mode != sd_data_transfer_mode) { + return sd_invalid_mode_for_cmd(sd, req); + } + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + + sd_function_switch(sd, req.arg); + return sd_cmd_to_sendingdata(sd, req, 0, NULL, 64); +} + +static sd_rsp_type_t emmc_cmd_SWITCH(SDState *sd, SDRequest req) +{ + switch (sd->state) { + case sd_transfer_state: + sd->state = sd_programming_state; + emmc_function_switch(sd, req.arg); + sd->state = sd_transfer_state; + return sd_r1b; + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + +/* CMD7 */ +static sd_rsp_type_t sd_cmd_DE_SELECT_CARD(SDState *sd, SDRequest req) +{ + bool same_rca = sd_req_rca_same(sd, req); + + switch (sd->state) { + case sd_standby_state: + if (!same_rca) { + return sd_r0; + } + sd->state = sd_transfer_state; + return sd_r1b; + + case sd_transfer_state: + case sd_sendingdata_state: + if (same_rca) { + break; + } + sd->state = sd_standby_state; + return sd_r1b; + + case sd_disconnect_state: + if (!same_rca) { + return sd_r0; + } + sd->state = sd_programming_state; + return sd_r1b; + + case sd_programming_state: + if (same_rca) { + break; + } + sd->state = sd_disconnect_state; + return sd_r1b; + + default: + break; + } + return sd_invalid_state_for_cmd(sd, req); +} + +/* CMD8 */ +static sd_rsp_type_t sd_cmd_SEND_IF_COND(SDState *sd, SDRequest req) +{ + if (sd->spec_version < SD_PHY_SPECv2_00_VERS) { return sd_cmd_illegal(sd, req); } + if (sd->state != sd_idle_state) { + return sd_invalid_state_for_cmd(sd, req); + } + sd->vhs = 0; + + /* No response if not exactly one VHS bit is set. */ + if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { + return sd_is_spi(sd) ? sd_r7 : sd_r0; + } + + /* Accept. */ + sd->vhs = req.arg; + return sd_r7; +} +/* CMD8 */ +static sd_rsp_type_t emmc_cmd_SEND_EXT_CSD(SDState *sd, SDRequest req) +{ if (sd->state != sd_transfer_state) { return sd_invalid_state_for_cmd(sd, req); } - sd->state = sd_sendingdata_state; - sd->data_offset = 0; + return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req), + sd->ext_csd, sizeof(sd->ext_csd)); +} + +/* CMD9 */ +static sd_rsp_type_t spi_cmd_SEND_CSD(SDState *sd, SDRequest req) +{ + if (sd->state != sd_standby_state) { + return sd_invalid_state_for_cmd(sd, req); + } + return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req), + sd->csd, 16); +} + +static sd_rsp_type_t sd_cmd_SEND_CSD(SDState *sd, SDRequest req) +{ + if (sd->state != sd_standby_state) { + return sd_invalid_state_for_cmd(sd, req); + } + + return sd_req_rca_same(sd, req) ? sd_r2_s : sd_r0; +} + +/* CMD10 */ +static sd_rsp_type_t spi_cmd_SEND_CID(SDState *sd, SDRequest req) +{ + if (sd->state != sd_standby_state) { + return sd_invalid_state_for_cmd(sd, req); + } + return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req), + sd->cid, 16); +} + +static sd_rsp_type_t sd_cmd_SEND_CID(SDState *sd, SDRequest req) +{ + if (sd->state != sd_standby_state) { + return sd_invalid_state_for_cmd(sd, req); + } + + return sd_req_rca_same(sd, req) ? sd_r2_i : sd_r0; +} + +/* CMD12 */ +static sd_rsp_type_t sd_cmd_STOP_TRANSMISSION(SDState *sd, SDRequest req) +{ + switch (sd->state) { + case sd_sendingdata_state: + sd->state = sd_transfer_state; + return sd_r1b; + case sd_receivingdata_state: + sd->state = sd_programming_state; + /* Bzzzzzzztt .... Operation complete. */ + sd->state = sd_transfer_state; + return sd_r1; + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + +/* CMD13 */ +static sd_rsp_type_t sd_cmd_SEND_STATUS(SDState *sd, SDRequest req) +{ + if (sd->mode != sd_data_transfer_mode) { + return sd_invalid_mode_for_cmd(sd, req); + } + + switch (sd->state) { + case sd_standby_state: + case sd_transfer_state: + case sd_sendingdata_state: + case sd_receivingdata_state: + case sd_programming_state: + case sd_disconnect_state: + break; + default: + return sd_invalid_state_for_cmd(sd, req); + } + + if (sd_is_spi(sd)) { + return sd_r2_s; + } + + return sd_req_rca_same(sd, req) ? sd_r1 : sd_r0; +} + +/* CMD15 */ +static sd_rsp_type_t sd_cmd_GO_INACTIVE_STATE(SDState *sd, SDRequest req) +{ + if (sd->mode != sd_data_transfer_mode) { + return sd_invalid_mode_for_cmd(sd, req); + } + switch (sd->state) { + case sd_standby_state: + case sd_transfer_state: + case sd_sendingdata_state: + case sd_receivingdata_state: + case sd_programming_state: + case sd_disconnect_state: + break; + default: + return sd_invalid_state_for_cmd(sd, req); + } + if (sd_req_rca_same(sd, req)) { + sd->state = sd_inactive_state; + } + + return sd_r0; +} + +/* CMD16 */ +static sd_rsp_type_t sd_cmd_SET_BLOCKLEN(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + if (req.arg > (1 << HWBLOCK_SHIFT)) { + sd->card_status |= BLOCK_LEN_ERROR; + } else { + trace_sdcard_set_blocklen(req.arg); + sd->blk_len = req.arg; + } return sd_r1; } +/* CMD17 */ +static sd_rsp_type_t sd_cmd_READ_SINGLE_BLOCK(SDState *sd, SDRequest req) +{ + uint64_t addr; + + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + + addr = sd_req_get_address(sd, req); + if (!address_in_range(sd, "READ_SINGLE_BLOCK", addr, sd->blk_len)) { + return sd_r1; + } + + sd_blk_read(sd, addr, sd->blk_len); + return sd_cmd_to_sendingdata(sd, req, addr, NULL, sd->blk_len); +} + +/* CMD19 */ +static sd_rsp_type_t sd_cmd_SEND_TUNING_BLOCK(SDState *sd, SDRequest req) +{ + if (sd->spec_version < SD_PHY_SPECv3_01_VERS) { + return sd_cmd_illegal(sd, req); + } + + return sd_cmd_to_sendingdata(sd, req, 0, + sd_tuning_block_pattern4, + sizeof(sd_tuning_block_pattern4)); +} + /* CMD23 */ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, SDRequest req) { @@ -1144,225 +1680,348 @@ static sd_rsp_type_t sd_cmd_SET_BLOCK_COUNT(SDState *sd, SDRequest req) } sd->multi_blk_cnt = req.arg; + if (sd_is_emmc(sd)) { + sd->multi_blk_cnt &= 0xffff; + } trace_sdcard_set_block_count(sd->multi_blk_cnt); return sd_r1; } -static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) +/* CMD24 */ +static sd_rsp_type_t sd_cmd_WRITE_SINGLE_BLOCK(SDState *sd, SDRequest req) { - uint16_t rca; uint64_t addr; - /* CMD55 precedes an ACMD, so we are not interested in tracing it. - * However there is no ACMD55, so we want to trace this particular case. - */ - if (req.cmd != 55 || sd->expecting_acmd) { - trace_sdcard_normal_command(sd_proto(sd)->name, - sd_cmd_name(req.cmd), req.cmd, - req.arg, sd_state_name(sd->state)); + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); } - /* Not interpreting this as an app command */ - sd->card_status &= ~APP_CMD; + addr = sd_req_get_address(sd, req); + if (!address_in_range(sd, "WRITE_SINGLE_BLOCK", addr, sd->blk_len)) { + return sd_r1; + } - /* CMD23 (set block count) must be immediately followed by CMD18 or CMD25 - * if not, its effects are cancelled */ - if (sd->multi_blk_cnt != 0 && !(req.cmd == 18 || req.cmd == 25)) { - sd->multi_blk_cnt = 0; + if (sd->size <= SDSC_MAX_CAPACITY) { + if (sd_wp_addr(sd, addr)) { + sd->card_status |= WP_VIOLATION; + } + } + if (sd->csd[14] & 0x30) { + sd->card_status |= WP_VIOLATION; } - if (sd_cmd_class[req.cmd] == 6 && FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) { - /* Only Standard Capacity cards support class 6 commands */ + sd->blk_written = 0; + return sd_cmd_to_receivingdata(sd, req, addr, sd->blk_len); +} + +/* CMD26 */ +static sd_rsp_type_t emmc_cmd_PROGRAM_CID(SDState *sd, SDRequest req) +{ + return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid)); +} + +/* CMD27 */ +static sd_rsp_type_t sd_cmd_PROGRAM_CSD(SDState *sd, SDRequest req) +{ + return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->csd)); +} + +static sd_rsp_type_t sd_cmd_SET_CLR_WRITE_PROT(SDState *sd, SDRequest req, + bool is_write) +{ + uint64_t addr; + + if (sd->size > SDSC_MAX_CAPACITY) { return sd_illegal; } - if (sd_proto(sd)->cmd[req.cmd]) { - return sd_proto(sd)->cmd[req.cmd](sd, req); + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); } - switch (req.cmd) { - /* Basic commands (Class 0 and Class 1) */ - case 4: /* CMD4: SEND_DSR */ - switch (sd->state) { - case sd_standby_state: - break; + addr = sd_req_get_address(sd, req); + if (!address_in_range(sd, is_write ? "SET_WRITE_PROT" : "CLR_WRITE_PROT", + addr, 1)) { + return sd_r1b; + } - default: - break; - } - break; + sd->state = sd_programming_state; + if (is_write) { + set_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); + } else { + clear_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); + } + /* Bzzzzzzztt .... Operation complete. */ + sd->state = sd_transfer_state; + return sd_r1; +} - case 6: /* CMD6: SWITCH_FUNCTION */ - if (sd->mode != sd_data_transfer_mode) { - return sd_invalid_mode_for_cmd(sd, req); - } - sd_function_switch(sd, req.arg); - sd->state = sd_sendingdata_state; - sd->data_start = 0; - sd->data_offset = 0; - return sd_r1; +/* CMD28 */ +static sd_rsp_type_t sd_cmd_SET_WRITE_PROT(SDState *sd, SDRequest req) +{ + return sd_cmd_SET_CLR_WRITE_PROT(sd, req, true); +} - case 7: /* CMD7: SELECT/DESELECT_CARD */ - rca = sd_req_get_rca(sd, req); - switch (sd->state) { - case sd_standby_state: - if (sd->rca != rca) - return sd_r0; +/* CMD29 */ +static sd_rsp_type_t sd_cmd_CLR_WRITE_PROT(SDState *sd, SDRequest req) +{ + return sd_cmd_SET_CLR_WRITE_PROT(sd, req, false); +} - sd->state = sd_transfer_state; - return sd_r1b; +/* CMD30 */ +static sd_rsp_type_t sd_cmd_SEND_WRITE_PROT(SDState *sd, SDRequest req) +{ + uint64_t addr; + uint32_t data; - case sd_transfer_state: - case sd_sendingdata_state: - if (sd->rca == rca) - break; + if (sd->size > SDSC_MAX_CAPACITY) { + return sd_illegal; + } - sd->state = sd_standby_state; - return sd_r1b; + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } - case sd_disconnect_state: - if (sd->rca != rca) - return sd_r0; + addr = sd_req_get_address(sd, req); + if (!address_in_range(sd, "SEND_WRITE_PROT", addr, sd->blk_len)) { + return sd_r1; + } - sd->state = sd_programming_state; - return sd_r1b; + data = sd_wpbits(sd, req.arg); + return sd_cmd_to_sendingdata(sd, req, addr, &data, sizeof(data)); +} - case sd_programming_state: - if (sd->rca == rca) - break; +/* CMD32 */ +static sd_rsp_type_t sd_cmd_ERASE_WR_BLK_START(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + sd->erase_start = req.arg; + return sd_r1; +} - sd->state = sd_disconnect_state; - return sd_r1b; +/* CMD33 */ +static sd_rsp_type_t sd_cmd_ERASE_WR_BLK_END(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + sd->erase_end = req.arg; + return sd_r1; +} - default: - break; +/* CMD38 */ +static sd_rsp_type_t sd_cmd_ERASE(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + if (sd->csd[14] & 0x30) { + sd->card_status |= WP_VIOLATION; + return sd_r1b; + } + + sd->state = sd_programming_state; + sd_erase(sd); + /* Bzzzzzzztt .... Operation complete. */ + sd->state = sd_transfer_state; + return sd_r1b; +} + +/* CMD42 */ +static sd_rsp_type_t sd_cmd_LOCK_UNLOCK(SDState *sd, SDRequest req) +{ + return sd_cmd_to_receivingdata(sd, req, 0, 0); +} + +/* CMD55 */ +static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, SDRequest req) +{ + switch (sd->state) { + case sd_ready_state: + case sd_identification_state: + case sd_inactive_state: + case sd_sleep_state: + return sd_invalid_state_for_cmd(sd, req); + case sd_idle_state: + if (!sd_is_spi(sd) && sd_req_get_rca(sd, req) != 0x0000) { + qemu_log_mask(LOG_GUEST_ERROR, + "SD: illegal RCA 0x%04x for APP_CMD\n", req.cmd); } + /* fall-through */ + default: break; + } + if (!sd_is_spi(sd) && !sd_req_rca_same(sd, req)) { + return sd_r0; + } + sd->expecting_acmd = true; + sd->card_status |= APP_CMD; - case 8: /* CMD8: SEND_IF_COND */ - if (sd->spec_version < SD_PHY_SPECv2_00_VERS) { - break; - } - if (sd->state != sd_idle_state) { - break; - } - sd->vhs = 0; + return sd_r1; +} - /* No response if not exactly one VHS bit is set. */ - if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) { - return sd_is_spi(sd) ? sd_r7 : sd_r0; - } +/* CMD56 */ +static sd_rsp_type_t sd_cmd_GEN_CMD(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } - /* Accept. */ - sd->vhs = req.arg; - return sd_r7; + /* Vendor specific command: our model is RAZ/WI */ + if (req.arg & 1) { + memset(sd->data, 0, sizeof(sd->data)); + return sd_cmd_to_sendingdata(sd, req, 0, NULL, 0); + } else { + return sd_cmd_to_receivingdata(sd, req, 0, 0); + } +} - case 9: /* CMD9: SEND_CSD */ - rca = sd_req_get_rca(sd, req); - switch (sd->state) { - case sd_standby_state: - if (sd->rca != rca) - return sd_r0; +/* CMD58 */ +static sd_rsp_type_t spi_cmd_READ_OCR(SDState *sd, SDRequest req) +{ + return sd_r3; +} - return sd_r2_s; +/* CMD59 */ +static sd_rsp_type_t spi_cmd_CRC_ON_OFF(SDState *sd, SDRequest req) +{ + return sd_r1; +} - case sd_transfer_state: - if (!sd_is_spi(sd)) { - break; - } - sd->state = sd_sendingdata_state; - memcpy(sd->data, sd->csd, 16); - sd->data_start = sd_req_get_address(sd, req); - sd->data_offset = 0; - return sd_r1; +/* ACMD6 */ +static sd_rsp_type_t sd_acmd_SET_BUS_WIDTH(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } - default: - break; - } - break; + sd->sd_status[0] &= 0x3f; + sd->sd_status[0] |= (req.arg & 0x03) << 6; + return sd_r1; +} - case 10: /* CMD10: SEND_CID */ - rca = sd_req_get_rca(sd, req); - switch (sd->state) { - case sd_standby_state: - if (sd->rca != rca) - return sd_r0; +/* ACMD13 */ +static sd_rsp_type_t sd_acmd_SD_STATUS(SDState *sd, SDRequest req) +{ + return sd_cmd_to_sendingdata(sd, req, 0, + sd->sd_status, sizeof(sd->sd_status)); +} - return sd_r2_i; +/* ACMD22 */ +static sd_rsp_type_t sd_acmd_SEND_NUM_WR_BLOCKS(SDState *sd, SDRequest req) +{ + return sd_cmd_to_sendingdata(sd, req, 0, + &sd->blk_written, sizeof(sd->blk_written)); +} - case sd_transfer_state: - if (!sd_is_spi(sd)) { - break; - } - sd->state = sd_sendingdata_state; - memcpy(sd->data, sd->cid, 16); - sd->data_start = sd_req_get_address(sd, req); - sd->data_offset = 0; - return sd_r1; +/* ACMD23 */ +static sd_rsp_type_t sd_acmd_SET_WR_BLK_ERASE_COUNT(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } + return sd_r1; +} - default: - break; +/* ACMD41 */ +static sd_rsp_type_t sd_cmd_SEND_OP_COND(SDState *sd, SDRequest req) +{ + if (sd->state != sd_idle_state) { + return sd_invalid_state_for_cmd(sd, req); + } + + /* + * If it's the first ACMD41 since reset, we need to decide + * whether to power up. If this is not an enquiry ACMD41, + * we immediately report power on and proceed below to the + * ready state, but if it is, we set a timer to model a + * delay for power up. This works around a bug in EDK2 + * UEFI, which sends an initial enquiry ACMD41, but + * assumes that the card is in ready state as soon as it + * sees the power up bit set. + */ + if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) { + if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) { + timer_del(sd->ocr_power_timer); + sd_ocr_powerup(sd); + } else { + trace_sdcard_inquiry_cmd41(); + if (!timer_pending(sd->ocr_power_timer)) { + timer_mod_ns(sd->ocr_power_timer, + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + OCR_POWER_DELAY_NS)); + } } - break; + } - case 12: /* CMD12: STOP_TRANSMISSION */ - switch (sd->state) { - case sd_sendingdata_state: - sd->state = sd_transfer_state; - return sd_r1b; + if (FIELD_EX32(sd->ocr & req.arg, OCR, VDD_VOLTAGE_WINDOW)) { + /* + * We accept any voltage. 10000 V is nothing. + * + * Once we're powered up, we advance straight to ready state + * unless it's an enquiry ACMD41 (bits 23:0 == 0). + */ + sd->state = sd_ready_state; + } - case sd_receivingdata_state: - sd->state = sd_programming_state; - /* Bzzzzzzztt .... Operation complete. */ - sd->state = sd_transfer_state; - return sd_r1b; + return sd_r3; +} - default: - break; - } - break; +/* ACMD42 */ +static sd_rsp_type_t sd_acmd_SET_CLR_CARD_DETECT(SDState *sd, SDRequest req) +{ + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } - case 13: /* CMD13: SEND_STATUS */ - rca = sd_req_get_rca(sd, req); - if (sd->mode != sd_data_transfer_mode) { - return sd_invalid_mode_for_cmd(sd, req); - } - if (!sd_is_spi(sd) && sd->rca != rca) { - return sd_r0; - } + /* Bringing in the 50KOhm pull-up resistor... Done. */ + return sd_r1; +} - return sd_r1; +/* ACMD51 */ +static sd_rsp_type_t sd_acmd_SEND_SCR(SDState *sd, SDRequest req) +{ + return sd_cmd_to_sendingdata(sd, req, 0, sd->scr, sizeof(sd->scr)); +} - case 15: /* CMD15: GO_INACTIVE_STATE */ - if (sd->mode != sd_data_transfer_mode) { - return sd_invalid_mode_for_cmd(sd, req); - } - rca = sd_req_get_rca(sd, req); - if (sd->rca == rca) { - sd->state = sd_inactive_state; - } - return sd_r0; +static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) +{ + uint64_t addr; - /* Block read commands (Class 2) */ - case 16: /* CMD16: SET_BLOCKLEN */ - switch (sd->state) { - case sd_transfer_state: - if (req.arg > (1 << HWBLOCK_SHIFT)) { - sd->card_status |= BLOCK_LEN_ERROR; - } else { - trace_sdcard_set_blocklen(req.arg); - sd->blk_len = req.arg; - } + sd->last_cmd_name = sd_cmd_name(sd, req.cmd); + /* CMD55 precedes an ACMD, so we are not interested in tracing it. + * However there is no ACMD55, so we want to trace this particular case. + */ + if (req.cmd != 55 || sd->expecting_acmd) { + trace_sdcard_normal_command(sd->proto->name, + sd->last_cmd_name, req.cmd, + req.arg, sd_state_name(sd->state)); + } - return sd_r1; + /* Not interpreting this as an app command */ + sd->card_status &= ~APP_CMD; - default: - break; - } - break; + /* CMD23 (set block count) must be immediately followed by CMD18 or CMD25 + * if not, its effects are cancelled */ + if (sd->multi_blk_cnt != 0 && !(req.cmd == 18 || req.cmd == 25)) { + sd->multi_blk_cnt = 0; + } + + if (sd->proto->cmd[req.cmd].class == 6 && FIELD_EX32(sd->ocr, OCR, + CARD_CAPACITY)) { + /* Only Standard Capacity cards support class 6 commands */ + return sd_illegal; + } + + if (sd->proto->cmd[req.cmd].handler) { + return sd->proto->cmd[req.cmd].handler(sd, req); + } - case 17: /* CMD17: READ_SINGLE_BLOCK */ + switch (req.cmd) { + /* Block read commands (Class 2) */ case 18: /* CMD18: READ_MULTIPLE_BLOCK */ addr = sd_req_get_address(sd, req); switch (sd->state) { @@ -1383,7 +2042,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) break; /* Block write commands (Class 4) */ - case 24: /* CMD24: WRITE_SINGLE_BLOCK */ case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */ addr = sd_req_get_address(sd, req); switch (sd->state) { @@ -1413,202 +2071,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } break; - case 26: /* CMD26: PROGRAM_CID */ - switch (sd->state) { - case sd_transfer_state: - sd->state = sd_receivingdata_state; - sd->data_start = 0; - sd->data_offset = 0; - return sd_r1; - - default: - break; - } - break; - - case 27: /* CMD27: PROGRAM_CSD */ - switch (sd->state) { - case sd_transfer_state: - sd->state = sd_receivingdata_state; - sd->data_start = 0; - sd->data_offset = 0; - return sd_r1; - - default: - break; - } - break; - - /* Write protection (Class 6) */ - case 28: /* CMD28: SET_WRITE_PROT */ - if (sd->size > SDSC_MAX_CAPACITY) { - return sd_illegal; - } - addr = sd_req_get_address(sd, req); - switch (sd->state) { - case sd_transfer_state: - if (!address_in_range(sd, "SET_WRITE_PROT", addr, 1)) { - return sd_r1b; - } - - sd->state = sd_programming_state; - set_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); - /* Bzzzzzzztt .... Operation complete. */ - sd->state = sd_transfer_state; - return sd_r1b; - - default: - break; - } - break; - - case 29: /* CMD29: CLR_WRITE_PROT */ - if (sd->size > SDSC_MAX_CAPACITY) { - return sd_illegal; - } - addr = sd_req_get_address(sd, req); - switch (sd->state) { - case sd_transfer_state: - if (!address_in_range(sd, "CLR_WRITE_PROT", addr, 1)) { - return sd_r1b; - } - - sd->state = sd_programming_state; - clear_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); - /* Bzzzzzzztt .... Operation complete. */ - sd->state = sd_transfer_state; - return sd_r1b; - - default: - break; - } - break; - - case 30: /* CMD30: SEND_WRITE_PROT */ - if (sd->size > SDSC_MAX_CAPACITY) { - return sd_illegal; - } - addr = sd_req_get_address(sd, req); - switch (sd->state) { - case sd_transfer_state: - if (!address_in_range(sd, "SEND_WRITE_PROT", - req.arg, sd->blk_len)) { - return sd_r1; - } - - sd->state = sd_sendingdata_state; - *(uint32_t *) sd->data = sd_wpbits(sd, req.arg); - sd->data_start = addr; - sd->data_offset = 0; - return sd_r1; - - default: - break; - } - break; - - /* Erase commands (Class 5) */ - case 32: /* CMD32: ERASE_WR_BLK_START */ - switch (sd->state) { - case sd_transfer_state: - sd->erase_start = req.arg; - return sd_r1; - - default: - break; - } - break; - - case 33: /* CMD33: ERASE_WR_BLK_END */ - switch (sd->state) { - case sd_transfer_state: - sd->erase_end = req.arg; - return sd_r1; - - default: - break; - } - break; - - case 38: /* CMD38: ERASE */ - switch (sd->state) { - case sd_transfer_state: - if (sd->csd[14] & 0x30) { - sd->card_status |= WP_VIOLATION; - return sd_r1b; - } - - sd->state = sd_programming_state; - sd_erase(sd); - /* Bzzzzzzztt .... Operation complete. */ - sd->state = sd_transfer_state; - return sd_r1b; - - default: - break; - } - break; - - /* Lock card commands (Class 7) */ - case 42: /* CMD42: LOCK_UNLOCK */ - switch (sd->state) { - case sd_transfer_state: - sd->state = sd_receivingdata_state; - sd->data_start = 0; - sd->data_offset = 0; - return sd_r1; - - default: - break; - } - break; - - /* Application specific commands (Class 8) */ - case 55: /* CMD55: APP_CMD */ - rca = sd_req_get_rca(sd, req); - switch (sd->state) { - case sd_ready_state: - case sd_identification_state: - case sd_inactive_state: - return sd_illegal; - case sd_idle_state: - if (rca) { - qemu_log_mask(LOG_GUEST_ERROR, - "SD: illegal RCA 0x%04x for APP_CMD\n", req.cmd); - } - default: - break; - } - if (!sd_is_spi(sd)) { - if (sd->rca != rca) { - return sd_r0; - } - } - sd->expecting_acmd = true; - sd->card_status |= APP_CMD; - return sd_r1; - - case 56: /* CMD56: GEN_CMD */ - switch (sd->state) { - case sd_transfer_state: - sd->data_offset = 0; - if (req.arg & 1) - sd->state = sd_sendingdata_state; - else - sd->state = sd_receivingdata_state; - return sd_r1; - - default: - break; - } - break; - - case 58: /* CMD58: READ_OCR (SPI) */ - return sd_r3; - - case 59: /* CMD59: CRC_ON_OFF (SPI) */ - return sd_r1; - default: qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd); return sd_illegal; @@ -1620,126 +2082,16 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) static sd_rsp_type_t sd_app_command(SDState *sd, SDRequest req) { - trace_sdcard_app_command(sd_proto(sd)->name, sd_acmd_name(req.cmd), + sd->last_cmd_name = sd_acmd_name(sd, req.cmd); + trace_sdcard_app_command(sd->proto->name, sd->last_cmd_name, req.cmd, req.arg, sd_state_name(sd->state)); sd->card_status |= APP_CMD; - if (sd_proto(sd)->acmd[req.cmd]) { - return sd_proto(sd)->acmd[req.cmd](sd, req); + if (sd->proto->acmd[req.cmd].handler) { + return sd->proto->acmd[req.cmd].handler(sd, req); } switch (req.cmd) { - case 6: /* ACMD6: SET_BUS_WIDTH */ - switch (sd->state) { - case sd_transfer_state: - sd->sd_status[0] &= 0x3f; - sd->sd_status[0] |= (req.arg & 0x03) << 6; - return sd_r1; - - default: - break; - } - break; - - case 13: /* ACMD13: SD_STATUS */ - switch (sd->state) { - case sd_transfer_state: - sd->state = sd_sendingdata_state; - sd->data_start = 0; - sd->data_offset = 0; - return sd_r1; - - default: - break; - } - break; - - case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ - switch (sd->state) { - case sd_transfer_state: - *(uint32_t *) sd->data = sd->blk_written; - - sd->state = sd_sendingdata_state; - sd->data_start = 0; - sd->data_offset = 0; - return sd_r1; - - default: - break; - } - break; - - case 23: /* ACMD23: SET_WR_BLK_ERASE_COUNT */ - switch (sd->state) { - case sd_transfer_state: - return sd_r1; - - default: - break; - } - break; - - case 41: /* ACMD41: SD_APP_OP_COND */ - if (sd->state != sd_idle_state) { - break; - } - /* If it's the first ACMD41 since reset, we need to decide - * whether to power up. If this is not an enquiry ACMD41, - * we immediately report power on and proceed below to the - * ready state, but if it is, we set a timer to model a - * delay for power up. This works around a bug in EDK2 - * UEFI, which sends an initial enquiry ACMD41, but - * assumes that the card is in ready state as soon as it - * sees the power up bit set. */ - if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) { - if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) { - timer_del(sd->ocr_power_timer); - sd_ocr_powerup(sd); - } else { - trace_sdcard_inquiry_cmd41(); - if (!timer_pending(sd->ocr_power_timer)) { - timer_mod_ns(sd->ocr_power_timer, - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - + OCR_POWER_DELAY_NS)); - } - } - } - - if (FIELD_EX32(sd->ocr & req.arg, OCR, VDD_VOLTAGE_WINDOW)) { - /* We accept any voltage. 10000 V is nothing. - * - * Once we're powered up, we advance straight to ready state - * unless it's an enquiry ACMD41 (bits 23:0 == 0). - */ - sd->state = sd_ready_state; - } - - return sd_r3; - - case 42: /* ACMD42: SET_CLR_CARD_DETECT */ - switch (sd->state) { - case sd_transfer_state: - /* Bringing in the 50KOhm pull-up resistor... Done. */ - return sd_r1; - - default: - break; - } - break; - - case 51: /* ACMD51: SEND_SCR */ - switch (sd->state) { - case sd_transfer_state: - sd->state = sd_sendingdata_state; - sd->data_start = 0; - sd->data_offset = 0; - return sd_r1; - - default: - break; - } - break; - case 18: /* Reserved for SD security applications */ case 25: case 26: @@ -1763,6 +2115,8 @@ static sd_rsp_type_t sd_app_command(SDState *sd, static bool cmd_valid_while_locked(SDState *sd, unsigned cmd) { + unsigned cmd_class; + /* Valid commands in locked state: * basic class (0) * lock card class (7) @@ -1777,19 +2131,29 @@ static bool cmd_valid_while_locked(SDState *sd, unsigned cmd) if (cmd == 16 || cmd == 55) { return true; } - return sd_cmd_class[cmd] == 0 || sd_cmd_class[cmd] == 7; + if (!sd->proto->cmd[cmd].handler) { + return false; + } + cmd_class = sd->proto->cmd[cmd].class; + + return cmd_class == 0 || cmd_class == 7; } -int sd_do_command(SDState *sd, SDRequest *req, - uint8_t *response) { +static int sd_do_command(SDState *sd, SDRequest *req, + uint8_t *response) { int last_state; sd_rsp_type_t rtype; int rsplen; - if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) { + if (!sd->blk || !blk_is_inserted(sd->blk)) { return 0; } + if (sd->state == sd_inactive_state) { + rtype = sd_illegal; + goto send_response; + } + if (sd_req_crc_validate(req)) { sd->card_status |= COM_CRC_ERROR; rtype = sd_illegal; @@ -1802,6 +2166,12 @@ int sd_do_command(SDState *sd, SDRequest *req, req->cmd &= 0x3f; } + if (sd->state == sd_sleep_state && req->cmd) { + qemu_log_mask(LOG_GUEST_ERROR, "SD: Card is sleeping\n"); + rtype = sd_r0; + goto send_response; + } + if (sd->card_status & CARD_IS_LOCKED) { if (!cmd_valid_while_locked(sd, req->cmd)) { sd->card_status |= ILLEGAL_COMMAND; @@ -1828,7 +2198,6 @@ int sd_do_command(SDState *sd, SDRequest *req, /* Valid command, we can update the 'state before command' bits. * (Do this now so they appear in r1 responses.) */ - sd->current_cmd = req->cmd; sd->card_status = FIELD_DP32(sd->card_status, CSR, CURRENT_STATE, last_state); } @@ -1893,15 +2262,43 @@ send_response: qemu_hexdump(stderr, "Response", response, rsplen); #endif + sd->current_cmd = rtype == sd_illegal ? 0 : req->cmd; + return rsplen; } -void sd_write_byte(SDState *sd, uint8_t value) +/* Return true if buffer is consumed. Configured by sd_cmd_to_receivingdata() */ +static bool sd_generic_write_byte(SDState *sd, uint8_t value) +{ + sd->data[sd->data_offset] = value; + + if (++sd->data_offset >= sd->data_size) { + sd->state = sd_transfer_state; + return true; + } + return false; +} + +/* Return true when buffer is consumed. Configured by sd_cmd_to_sendingdata() */ +static bool sd_generic_read_byte(SDState *sd, uint8_t *value) +{ + *value = sd->data[sd->data_offset]; + + if (++sd->data_offset >= sd->data_size) { + sd->state = sd_transfer_state; + return true; + } + + return false; +} + +static void sd_write_byte(SDState *sd, uint8_t value) { int i; - if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) + if (!sd->blk || !blk_is_inserted(sd->blk)) { return; + } if (sd->state != sd_receivingdata_state) { qemu_log_mask(LOG_GUEST_ERROR, @@ -1912,13 +2309,12 @@ void sd_write_byte(SDState *sd, uint8_t value) if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) return; - trace_sdcard_write_data(sd_proto(sd)->name, - sd_acmd_name(sd->current_cmd), - sd->current_cmd, value); + trace_sdcard_write_data(sd->proto->name, + sd->last_cmd_name, + sd->current_cmd, sd->data_offset, value); switch (sd->current_cmd) { case 24: /* CMD24: WRITE_SINGLE_BLOCK */ - sd->data[sd->data_offset ++] = value; - if (sd->data_offset >= sd->blk_len) { + if (sd_generic_write_byte(sd, value)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; sd_blk_write(sd, sd->data_start, sd->data_offset); @@ -1967,8 +2363,7 @@ void sd_write_byte(SDState *sd, uint8_t value) break; case 26: /* CMD26: PROGRAM_CID */ - sd->data[sd->data_offset ++] = value; - if (sd->data_offset >= sizeof(sd->cid)) { + if (sd_generic_write_byte(sd, value)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; for (i = 0; i < sizeof(sd->cid); i ++) @@ -1986,8 +2381,7 @@ void sd_write_byte(SDState *sd, uint8_t value) break; case 27: /* CMD27: PROGRAM_CSD */ - sd->data[sd->data_offset ++] = value; - if (sd->data_offset >= sizeof(sd->csd)) { + if (sd_generic_write_byte(sd, value)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; for (i = 0; i < sizeof(sd->csd); i ++) @@ -2010,8 +2404,7 @@ void sd_write_byte(SDState *sd, uint8_t value) break; case 42: /* CMD42: LOCK_UNLOCK */ - sd->data[sd->data_offset ++] = value; - if (sd->data_offset >= sd->blk_len) { + if (sd_generic_write_byte(sd, value)) { /* TODO: Check CRC before committing */ sd->state = sd_programming_state; sd_lock_command(sd); @@ -2021,94 +2414,60 @@ void sd_write_byte(SDState *sd, uint8_t value) break; case 56: /* CMD56: GEN_CMD */ - sd->data[sd->data_offset ++] = value; - if (sd->data_offset >= sd->blk_len) { - APP_WRITE_BLOCK(sd->data_start, sd->data_offset); - sd->state = sd_transfer_state; - } + sd_generic_write_byte(sd, value); break; default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__); - break; + g_assert_not_reached(); } } -#define SD_TUNING_BLOCK_SIZE 64 - -static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { - /* See: Physical Layer Simplified Specification Version 3.01, Table 4-2 */ - 0xff, 0x0f, 0xff, 0x00, 0x0f, 0xfc, 0xc3, 0xcc, - 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, - 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, - 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, - 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, - 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, - 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, - 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, -}; - -uint8_t sd_read_byte(SDState *sd) +static uint8_t sd_read_byte(SDState *sd) { /* TODO: Append CRCs */ + const uint8_t dummy_byte = 0x00; uint8_t ret; uint32_t io_len; - if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) - return 0x00; + if (!sd->blk || !blk_is_inserted(sd->blk)) { + return dummy_byte; + } if (sd->state != sd_sendingdata_state) { qemu_log_mask(LOG_GUEST_ERROR, "%s: not in Sending-Data state\n", __func__); - return 0x00; + return dummy_byte; } - if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) - return 0x00; + if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) { + return dummy_byte; + } - io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len; + io_len = sd_blk_len(sd); - trace_sdcard_read_data(sd_proto(sd)->name, - sd_acmd_name(sd->current_cmd), - sd->current_cmd, io_len); + trace_sdcard_read_data(sd->proto->name, + sd->last_cmd_name, sd->current_cmd, + sd->data_offset, sd->data_size, io_len); switch (sd->current_cmd) { case 6: /* CMD6: SWITCH_FUNCTION */ - ret = sd->data[sd->data_offset ++]; - - if (sd->data_offset >= 64) - sd->state = sd_transfer_state; - break; - + case 8: /* CMD8: SEND_EXT_CSD */ case 9: /* CMD9: SEND_CSD */ - case 10: /* CMD10: SEND_CID */ - ret = sd->data[sd->data_offset ++]; - - if (sd->data_offset >= 16) - sd->state = sd_transfer_state; - break; - - case 13: /* ACMD13: SD_STATUS */ - ret = sd->sd_status[sd->data_offset ++]; - - if (sd->data_offset >= sizeof(sd->sd_status)) - sd->state = sd_transfer_state; - break; - - case 17: /* CMD17: READ_SINGLE_BLOCK */ - if (sd->data_offset == 0) { - sd_blk_read(sd, sd->data_start, io_len); - } - ret = sd->data[sd->data_offset ++]; - - if (sd->data_offset >= io_len) - sd->state = sd_transfer_state; + case 10: /* CMD10: SEND_CID */ + case 13: /* ACMD13: SD_STATUS */ + case 17: /* CMD17: READ_SINGLE_BLOCK */ + case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */ + case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ + case 30: /* CMD30: SEND_WRITE_PROT */ + case 51: /* ACMD51: SEND_SCR */ + case 56: /* CMD56: GEN_CMD */ + sd_generic_read_byte(sd, &ret); break; case 18: /* CMD18: READ_MULTIPLE_BLOCK */ if (sd->data_offset == 0) { if (!address_in_range(sd, "READ_MULTIPLE_BLOCK", sd->data_start, io_len)) { - return 0x00; + return dummy_byte; } sd_blk_read(sd, sd->data_start, io_len); } @@ -2128,46 +2487,10 @@ uint8_t sd_read_byte(SDState *sd) } break; - case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */ - if (sd->data_offset >= SD_TUNING_BLOCK_SIZE - 1) { - sd->state = sd_transfer_state; - } - ret = sd_tuning_block_pattern[sd->data_offset++]; - break; - - case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ - ret = sd->data[sd->data_offset ++]; - - if (sd->data_offset >= 4) - sd->state = sd_transfer_state; - break; - - case 30: /* CMD30: SEND_WRITE_PROT */ - ret = sd->data[sd->data_offset ++]; - - if (sd->data_offset >= 4) - sd->state = sd_transfer_state; - break; - - case 51: /* ACMD51: SEND_SCR */ - ret = sd->scr[sd->data_offset ++]; - - if (sd->data_offset >= sizeof(sd->scr)) - sd->state = sd_transfer_state; - break; - - case 56: /* CMD56: GEN_CMD */ - if (sd->data_offset == 0) - APP_READ_BLOCK(sd->data_start, sd->blk_len); - ret = sd->data[sd->data_offset ++]; - - if (sd->data_offset >= sd->blk_len) - sd->state = sd_transfer_state; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__); - return 0x00; + qemu_log_mask(LOG_GUEST_ERROR, "%s: DAT read illegal for command %s\n", + __func__, sd->last_cmd_name); + return dummy_byte; } return ret; @@ -2183,51 +2506,178 @@ static bool sd_data_ready(SDState *sd) return sd->state == sd_sendingdata_state; } -void sd_enable(SDState *sd, bool enable) -{ - sd->enable = enable; -} - static const SDProto sd_proto_spi = { .name = "SPI", .cmd = { - [0] = sd_cmd_GO_IDLE_STATE, - [1] = spi_cmd_SEND_OP_COND, + [0] = {0, sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE}, + [1] = {0, sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND}, + [5] = {9, sd_spi, "IO_SEND_OP_COND", sd_cmd_optional}, + [6] = {10, sd_spi, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION}, + [8] = {0, sd_spi, "SEND_IF_COND", sd_cmd_SEND_IF_COND}, + [9] = {0, sd_spi, "SEND_CSD", spi_cmd_SEND_CSD}, + [10] = {0, sd_spi, "SEND_CID", spi_cmd_SEND_CID}, + [12] = {0, sd_spi, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION}, + [13] = {0, sd_spi, "SEND_STATUS", sd_cmd_SEND_STATUS}, + [16] = {2, sd_spi, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN}, + [17] = {2, sd_spi, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK}, + [24] = {4, sd_spi, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK}, + [27] = {4, sd_spi, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD}, + [28] = {6, sd_spi, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT}, + [29] = {6, sd_spi, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT}, + [30] = {6, sd_spi, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT}, + [32] = {5, sd_spi, "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START}, + [33] = {5, sd_spi, "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END}, + [34] = {10, sd_spi, "READ_SEC_CMD", sd_cmd_optional}, + [35] = {10, sd_spi, "WRITE_SEC_CMD", sd_cmd_optional}, + [36] = {10, sd_spi, "SEND_PSI", sd_cmd_optional}, + [37] = {10, sd_spi, "CONTROL_ASSD_SYSTEM", sd_cmd_optional}, + [38] = {5, sd_spi, "ERASE", sd_cmd_ERASE}, + [42] = {7, sd_spi, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK}, + [50] = {10, sd_spi, "DIRECT_SECURE_READ", sd_cmd_optional}, + [52] = {9, sd_spi, "IO_RW_DIRECT", sd_cmd_optional}, + [53] = {9, sd_spi, "IO_RW_EXTENDED", sd_cmd_optional}, + [55] = {8, sd_spi, "APP_CMD", sd_cmd_APP_CMD}, + [56] = {8, sd_spi, "GEN_CMD", sd_cmd_GEN_CMD}, + [57] = {10, sd_spi, "DIRECT_SECURE_WRITE", sd_cmd_optional}, + [58] = {0, sd_spi, "READ_OCR", spi_cmd_READ_OCR}, + [59] = {0, sd_spi, "CRC_ON_OFF", spi_cmd_CRC_ON_OFF}, }, .acmd = { - [41] = spi_cmd_SEND_OP_COND, + [13] = {8, sd_spi, "SD_STATUS", sd_acmd_SD_STATUS}, + [22] = {8, sd_spi, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS}, + [23] = {8, sd_spi, "SET_WR_BLK_ERASE_COUNT", sd_acmd_SET_WR_BLK_ERASE_COUNT}, + [41] = {8, sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND}, + [42] = {8, sd_spi, "SET_CLR_CARD_DETECT", sd_acmd_SET_CLR_CARD_DETECT}, + [51] = {8, sd_spi, "SEND_SCR", sd_acmd_SEND_SCR}, }, }; static const SDProto sd_proto_sd = { .name = "SD", .cmd = { - [0] = sd_cmd_GO_IDLE_STATE, - [2] = sd_cmd_ALL_SEND_CID, - [3] = sd_cmd_SEND_RELATIVE_ADDR, - [19] = sd_cmd_SEND_TUNING_BLOCK, - [23] = sd_cmd_SET_BLOCK_COUNT, + [0] = {0, sd_bc, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE}, + [2] = {0, sd_bcr, "ALL_SEND_CID", sd_cmd_ALL_SEND_CID}, + [3] = {0, sd_bcr, "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR}, + [4] = {0, sd_bc, "SEND_DSR", sd_cmd_unimplemented}, + [5] = {9, sd_bc, "IO_SEND_OP_COND", sd_cmd_optional}, + [6] = {10, sd_adtc, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION}, + [7] = {0, sd_ac, "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD}, + [8] = {0, sd_bcr, "SEND_IF_COND", sd_cmd_SEND_IF_COND}, + [9] = {0, sd_ac, "SEND_CSD", sd_cmd_SEND_CSD}, + [10] = {0, sd_ac, "SEND_CID", sd_cmd_SEND_CID}, + [11] = {0, sd_ac, "VOLTAGE_SWITCH", sd_cmd_optional}, + [12] = {0, sd_ac, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION}, + [13] = {0, sd_ac, "SEND_STATUS", sd_cmd_SEND_STATUS}, + [15] = {0, sd_ac, "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE}, + [16] = {2, sd_ac, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN}, + [17] = {2, sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK}, + [19] = {2, sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK}, + [20] = {2, sd_ac, "SPEED_CLASS_CONTROL", sd_cmd_optional}, + [23] = {2, sd_ac, "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT}, + [24] = {4, sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK}, + [27] = {4, sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD}, + [28] = {6, sd_ac, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT}, + [29] = {6, sd_ac, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT}, + [30] = {6, sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT}, + [32] = {5, sd_ac, "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START}, + [33] = {5, sd_ac, "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END}, + [34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional}, + [35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional}, + [36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional}, + [37] = {10, sd_ac, "CONTROL_ASSD_SYSTEM", sd_cmd_optional}, + [38] = {5, sd_ac, "ERASE", sd_cmd_ERASE}, + [42] = {7, sd_adtc, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK}, + [43] = {1, sd_ac, "Q_MANAGEMENT", sd_cmd_optional}, + [44] = {1, sd_ac, "Q_TASK_INFO_A", sd_cmd_optional}, + [45] = {1, sd_ac, "Q_TASK_INFO_B", sd_cmd_optional}, + [46] = {1, sd_adtc, "Q_RD_TASK", sd_cmd_optional}, + [47] = {1, sd_adtc, "Q_WR_TASK", sd_cmd_optional}, + [48] = {1, sd_adtc, "READ_EXTR_SINGLE", sd_cmd_optional}, + [49] = {1, sd_adtc, "WRITE_EXTR_SINGLE", sd_cmd_optional}, + [50] = {10, sd_adtc, "DIRECT_SECURE_READ", sd_cmd_optional}, + [52] = {9, sd_bc, "IO_RW_DIRECT", sd_cmd_optional}, + [53] = {9, sd_bc, "IO_RW_EXTENDED", sd_cmd_optional}, + [55] = {8, sd_ac, "APP_CMD", sd_cmd_APP_CMD}, + [56] = {8, sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD}, + [57] = {10, sd_adtc, "DIRECT_SECURE_WRITE", sd_cmd_optional}, + [58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional}, + [59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional}, + }, + .acmd = { + [6] = {8, sd_ac, "SET_BUS_WIDTH", sd_acmd_SET_BUS_WIDTH}, + [13] = {8, sd_adtc, "SD_STATUS", sd_acmd_SD_STATUS}, + [22] = {8, sd_adtc, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS}, + [23] = {8, sd_ac, "SET_WR_BLK_ERASE_COUNT", sd_acmd_SET_WR_BLK_ERASE_COUNT}, + [41] = {8, sd_bcr, "SEND_OP_COND", sd_cmd_SEND_OP_COND}, + [42] = {8, sd_ac, "SET_CLR_CARD_DETECT", sd_acmd_SET_CLR_CARD_DETECT}, + [51] = {8, sd_adtc, "SEND_SCR", sd_acmd_SEND_SCR}, + }, +}; + +static const SDProto sd_proto_emmc = { + /* Only v4.3 is supported */ + .name = "eMMC", + .cmd = { + [0] = {0, sd_bc, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE}, + [1] = {0, sd_bcr, "SEND_OP_COND", sd_cmd_SEND_OP_COND}, + [2] = {0, sd_bcr, "ALL_SEND_CID", sd_cmd_ALL_SEND_CID}, + [3] = {0, sd_ac, "SET_RELATIVE_ADDR", emmc_cmd_SET_RELATIVE_ADDR}, + [4] = {0, sd_bc, "SEND_DSR", sd_cmd_unimplemented}, + [5] = {0, sd_ac, "SLEEP/AWAKE", emmc_cmd_sleep_awake}, + [6] = {10, sd_adtc, "SWITCH", emmc_cmd_SWITCH}, + [7] = {0, sd_ac, "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD}, + [8] = {0, sd_adtc, "SEND_EXT_CSD", emmc_cmd_SEND_EXT_CSD}, + [9] = {0, sd_ac, "SEND_CSD", sd_cmd_SEND_CSD}, + [10] = {0, sd_ac, "SEND_CID", sd_cmd_SEND_CID}, + [11] = {1, sd_adtc, "READ_DAT_UNTIL_STOP", sd_cmd_unimplemented}, + [12] = {0, sd_ac, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION}, + [13] = {0, sd_ac, "SEND_STATUS", sd_cmd_SEND_STATUS}, + [14] = {0, sd_adtc, "BUSTEST_R", sd_cmd_unimplemented}, + [15] = {0, sd_ac, "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE}, + [16] = {2, sd_ac, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN}, + [17] = {2, sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK}, + [19] = {0, sd_adtc, "BUSTEST_W", sd_cmd_unimplemented}, + [20] = {3, sd_adtc, "WRITE_DAT_UNTIL_STOP", sd_cmd_unimplemented}, + [23] = {2, sd_ac, "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT}, + [24] = {4, sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK}, + [26] = {4, sd_adtc, "PROGRAM_CID", emmc_cmd_PROGRAM_CID}, + [27] = {4, sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD}, + [28] = {6, sd_ac, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT}, + [29] = {6, sd_ac, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT}, + [30] = {6, sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT}, + [31] = {6, sd_adtc, "SEND_WRITE_PROT_TYPE", sd_cmd_unimplemented}, + [35] = {5, sd_ac, "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START}, + [36] = {5, sd_ac, "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END}, + [38] = {5, sd_ac, "ERASE", sd_cmd_ERASE}, + [39] = {9, sd_ac, "FAST_IO", sd_cmd_unimplemented}, + [40] = {9, sd_bcr, "GO_IRQ_STATE", sd_cmd_unimplemented}, + [42] = {7, sd_adtc, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK}, + [49] = {0, sd_adtc, "SET_TIME", sd_cmd_unimplemented}, + [55] = {8, sd_ac, "APP_CMD", sd_cmd_APP_CMD}, + [56] = {8, sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD}, }, }; static void sd_instance_init(Object *obj) { - SDState *sd = SD_CARD(obj); + SDState *sd = SDMMC_COMMON(obj); + SDCardClass *sc = SDMMC_COMMON_GET_CLASS(sd); - sd->enable = true; + sd->proto = sc->proto; + sd->last_cmd_name = "UNSET"; sd->ocr_power_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sd_ocr_powerup, sd); } static void sd_instance_finalize(Object *obj) { - SDState *sd = SD_CARD(obj); + SDState *sd = SDMMC_COMMON(obj); timer_free(sd->ocr_power_timer); } static void sd_realize(DeviceState *dev, Error **errp) { - SDState *sd = SD_CARD(dev); + SDState *sd = SDMMC_COMMON(dev); int ret; switch (sd->spec_version) { @@ -2278,26 +2728,37 @@ static void sd_realize(DeviceState *dev, Error **errp) } } -static Property sd_properties[] = { - DEFINE_PROP_UINT8("spec_version", SDState, - spec_version, SD_PHY_SPECv2_00_VERS), +static void emmc_realize(DeviceState *dev, Error **errp) +{ + SDState *sd = SDMMC_COMMON(dev); + + sd->spec_version = SD_PHY_SPECv3_01_VERS; /* Actually v4.3 */ + + sd_realize(dev, errp); +} + +static const Property sdmmc_common_properties[] = { DEFINE_PROP_DRIVE("drive", SDState, blk), - /* We do not model the chip select pin, so allow the board to select - * whether card should be in SSI or MMC/SD mode. It is also up to the - * board to ensure that ssi transfers only occur when the chip select - * is asserted. */ - DEFINE_PROP_END_OF_LIST() }; -static void sd_class_init(ObjectClass *klass, void *data) +static const Property sd_properties[] = { + DEFINE_PROP_UINT8("spec_version", SDState, + spec_version, SD_PHY_SPECv3_01_VERS), +}; + +static const Property emmc_properties[] = { + DEFINE_PROP_UINT64("boot-partition-size", SDState, boot_part_size, 0), + DEFINE_PROP_UINT8("boot-config", SDState, boot_config, 0x0), +}; + +static void sdmmc_common_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SDCardClass *sc = SD_CARD_CLASS(klass); + SDCardClass *sc = SDMMC_COMMON_CLASS(klass); - dc->realize = sd_realize; - device_class_set_props(dc, sd_properties); + device_class_set_props(dc, sdmmc_common_properties); dc->vmsd = &sd_vmstate; - dc->reset = sd_reset; + device_class_set_legacy_reset(dc, sd_reset); dc->bus_type = TYPE_SD_BUS; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); @@ -2309,9 +2770,20 @@ static void sd_class_init(ObjectClass *klass, void *data) sc->read_byte = sd_read_byte; sc->receive_ready = sd_receive_ready; sc->data_ready = sd_data_ready; - sc->enable = sd_enable; sc->get_inserted = sd_get_inserted; sc->get_readonly = sd_get_readonly; +} + +static void sd_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SDCardClass *sc = SDMMC_COMMON_CLASS(klass); + + dc->realize = sd_realize; + device_class_set_props(dc, sd_properties); + + sc->set_cid = sd_set_cid; + sc->set_csd = sd_set_csd; sc->proto = &sd_proto_sd; } @@ -2321,30 +2793,58 @@ static void sd_class_init(ObjectClass *klass, void *data) * board to ensure that ssi transfers only occur when the chip select * is asserted. */ -static void sd_spi_class_init(ObjectClass *klass, void *data) +static void sd_spi_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SDCardClass *sc = SD_CARD_CLASS(klass); + SDCardClass *sc = SDMMC_COMMON_CLASS(klass); dc->desc = "SD SPI"; sc->proto = &sd_proto_spi; } +static void emmc_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SDCardClass *sc = SDMMC_COMMON_CLASS(klass); + + dc->desc = "eMMC"; + dc->realize = emmc_realize; + device_class_set_props(dc, emmc_properties); + /* Reason: Soldered on board */ + dc->user_creatable = false; + + sc->proto = &sd_proto_emmc; + + sc->set_cid = emmc_set_cid; + sc->set_csd = emmc_set_csd; +} + static const TypeInfo sd_types[] = { { - .name = TYPE_SD_CARD, + .name = TYPE_SDMMC_COMMON, .parent = TYPE_DEVICE, + .abstract = true, .instance_size = sizeof(SDState), .class_size = sizeof(SDCardClass), - .class_init = sd_class_init, + .class_init = sdmmc_common_class_init, .instance_init = sd_instance_init, .instance_finalize = sd_instance_finalize, }, { + .name = TYPE_SD_CARD, + .parent = TYPE_SDMMC_COMMON, + .class_init = sd_class_init, + }, + { .name = TYPE_SD_CARD_SPI, .parent = TYPE_SD_CARD, .class_init = sd_spi_class_init, }, + { + .name = TYPE_EMMC, + .parent = TYPE_SDMMC_COMMON, + .class_init = emmc_class_init, + }, }; DEFINE_TYPES(sd_types) |