static sd_rsp_type_t sd_normal_command(SDState *sd,
                                       SDRequest req)
{
    uint32_t rca = 0x0000;
    uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
    if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
        rca = req.arg >> 16;
    DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state);
    switch (req.cmd) {
    /* Basic commands (Class 0 and Class 1) */
    case 0:	/* CMD0:   GO_IDLE_STATE */
        switch (sd->state) {
        case sd_inactive_state:
            return sd->spi ? sd_r1 : sd_r0;
        default:
            sd->state = sd_idle_state;
            sd_reset(sd, sd->bdrv);
            return sd->spi ? sd_r1 : sd_r0;
        }
        break;
    case 1:	/* CMD1:   SEND_OP_CMD */
        if (!sd->spi)
            goto bad_cmd;
        sd->state = sd_transfer_state;
        return sd_r1;
    case 2:	/* CMD2:   ALL_SEND_CID */
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_ready_state:
            sd->state = sd_identification_state;
            return sd_r2_i;
        default:
            break;
        }
        break;
    case 3:	/* CMD3:   SEND_RELATIVE_ADDR */
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_identification_state:
        case sd_standby_state:
            sd->state = sd_standby_state;
            sd_set_rca(sd);
            return sd_r6;
        default:
            break;
        }
        break;
    case 4:	/* CMD4:   SEND_DSR */
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_standby_state:
            break;
        default:
            break;
        }
        break;
    case 5: /* CMD5: reserved for SDIO cards */
    case 6:	/* CMD6:   SWITCH_FUNCTION */
        if (sd->spi)
            goto bad_cmd;
        switch (sd->mode) {
        case sd_data_transfer_mode:
            sd_function_switch(sd, req.arg);
            sd->state = sd_sendingdata_state;
            sd->data_start = 0;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 7:	/* CMD7:   SELECT/DESELECT_CARD */
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            sd->state = sd_transfer_state;
            return sd_r1b;
        case sd_transfer_state:
        case sd_sendingdata_state:
            if (sd->rca == rca)
                break;
            sd->state = sd_standby_state;
            return sd_r1b;
        case sd_disconnect_state:
            if (sd->rca != rca)
            sd->state = sd_programming_state;
            return sd_r1b;
        case sd_programming_state:
            if (sd->rca == rca)
                break;
            sd->state = sd_disconnect_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 8:	/* CMD8:   SEND_IF_COND */
        /* Physical Layer Specification Version 2.00 command */
        switch (sd->state) {
        case sd_idle_state:
            sd->vhs = 0;
            /* No response if not exactly one VHS bit is set.  */
            if (!(req.arg >> 8) || (req.arg >> ffs(req.arg & ~0xff)))
                return sd->spi ? sd_r7 : sd_r0;
            /* Accept.  */
            sd->vhs = req.arg;
            return sd_r7;
        default:
            break;
        }
        break;
    case 9:	/* CMD9:   SEND_CSD */
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            return sd_r2_s;
        case sd_transfer_state:
            if (!sd->spi)
                break;
            sd->state = sd_sendingdata_state;
            memcpy(sd->data, sd->csd, 16);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 10:	/* CMD10:  SEND_CID */
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            return sd_r2_i;
        case sd_transfer_state:
            if (!sd->spi)
                break;
            sd->state = sd_sendingdata_state;
            memcpy(sd->data, sd->cid, 16);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 11:	/* CMD11:  READ_DAT_UNTIL_STOP */
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = req.arg;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
        default:
            break;
        }
        break;
    case 12:	/* CMD12:  STOP_TRANSMISSION */
        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_r1b;
        default:
            break;
        }
        break;
    case 13:	/* CMD13:  SEND_STATUS */
        switch (sd->mode) {
        case sd_data_transfer_mode:
            if (sd->rca != rca)
            return sd_r1;
        default:
            break;
        }
        break;
    case 15:	/* CMD15:  GO_INACTIVE_STATE */
        if (sd->spi)
            goto bad_cmd;
        switch (sd->mode) {
        case sd_data_transfer_mode:
            if (sd->rca != rca)
            sd->state = sd_inactive_state;
        default:
            break;
        }
        break;
    /* Block read commands (Classs 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
                sd->blk_len = req.arg;
            return sd_r1;
        default:
            break;
        }
        break;
    case 17:	/* CMD17:  READ_SINGLE_BLOCK */
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            return sd_r1;
        default:
            break;
        }
        break;
    case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            return sd_r1;
        default:
            break;
        }
        break;
    /* Block write commands (Class 4) */
    case 24:	/* CMD24:  WRITE_SINGLE_BLOCK */
        if (sd->spi)
            goto unimplemented_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            /* Writing in SPI mode not implemented.  */
            if (sd->spi)
                break;
            sd->state = sd_receivingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            sd->blk_written = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            if (sd_wp_addr(sd, sd->data_start))
                sd->card_status |= WP_VIOLATION;
            if (sd->csd[14] & 0x30)
                sd->card_status |= WP_VIOLATION;
            return sd_r1;
        default:
            break;
        }
        break;
    case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
        if (sd->spi)
            goto unimplemented_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            /* Writing in SPI mode not implemented.  */
            if (sd->spi)
                break;
            sd->state = sd_receivingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            sd->blk_written = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            if (sd_wp_addr(sd, sd->data_start))
                sd->card_status |= WP_VIOLATION;
            if (sd->csd[14] & 0x30)
                sd->card_status |= WP_VIOLATION;
            return sd_r1;
        default:
            break;
        }
        break;
    case 26:	/* CMD26:  PROGRAM_CID */
        if (sd->spi)
            goto bad_cmd;
        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 */
        if (sd->spi)
            goto unimplemented_cmd;
        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 */
        switch (sd->state) {
        case sd_transfer_state:
            if (addr >= sd->size) {
                sd->card_status = ADDRESS_ERROR;
                return sd_r1b;
            }
            sd->state = sd_programming_state;
            sd->wp_groups[addr >> (HWBLOCK_SHIFT +
                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 1;
            /* Bzzzzzzztt .... Operation complete.  */
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 29:	/* CMD29:  CLR_WRITE_PROT */
        switch (sd->state) {
        case sd_transfer_state:
            if (addr >= sd->size) {
                sd->card_status = ADDRESS_ERROR;
                return sd_r1b;
            }
            sd->state = sd_programming_state;
            sd->wp_groups[addr >> (HWBLOCK_SHIFT +
                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 0;
            /* Bzzzzzzztt .... Operation complete.  */
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 30:	/* CMD30:  SEND_WRITE_PROT */
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            *(uint32_t *) sd->data = sd_wpbits(sd, req.arg);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1b;
        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 */
        if (sd->spi)
            goto unimplemented_cmd;
        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 */
        if (sd->rca != rca)
        sd->card_status |= APP_CMD;
        return sd_r1;
    case 56:	/* CMD56:  GEN_CMD */
        fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
        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;
    default:
    bad_cmd:
        fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd);
    unimplemented_cmd:
        /* Commands that are recognised but not yet implemented in SPI mode.  */
        fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd);
    }
    fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd);
}
static sd_rsp_type_t sd_normal_command(SDState *sd,
                                       SDRequest req)
{
    uint32_t rca = 0x0000;
    uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
    if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
        rca = req.arg >> 16;
    DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state);
    switch (req.cmd) {
    
    case 0:	
        switch (sd->state) {
        case sd_inactive_state:
            return sd->spi ? sd_r1 : sd_r0;
        default:
            sd->state = sd_idle_state;
            sd_reset(sd, sd->bdrv);
            return sd->spi ? sd_r1 : sd_r0;
        }
        break;
    case 1:	
        if (!sd->spi)
            goto bad_cmd;
        sd->state = sd_transfer_state;
        return sd_r1;
    case 2:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_ready_state:
            sd->state = sd_identification_state;
            return sd_r2_i;
        default:
            break;
        }
        break;
    case 3:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_identification_state:
        case sd_standby_state:
            sd->state = sd_standby_state;
            sd_set_rca(sd);
            return sd_r6;
        default:
            break;
        }
        break;
    case 4:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_standby_state:
            break;
        default:
            break;
        }
        break;
    case 5: 
    case 6:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->mode) {
        case sd_data_transfer_mode:
            sd_function_switch(sd, req.arg);
            sd->state = sd_sendingdata_state;
            sd->data_start = 0;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 7:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            sd->state = sd_transfer_state;
            return sd_r1b;
        case sd_transfer_state:
        case sd_sendingdata_state:
            if (sd->rca == rca)
                break;
            sd->state = sd_standby_state;
            return sd_r1b;
        case sd_disconnect_state:
            if (sd->rca != rca)
            sd->state = sd_programming_state;
            return sd_r1b;
        case sd_programming_state:
            if (sd->rca == rca)
                break;
            sd->state = sd_disconnect_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 8:	
        
        switch (sd->state) {
        case sd_idle_state:
            sd->vhs = 0;
            
            if (!(req.arg >> 8) || (req.arg >> ffs(req.arg & ~0xff)))
                return sd->spi ? sd_r7 : sd_r0;
            
            sd->vhs = req.arg;
            return sd_r7;
        default:
            break;
        }
        break;
    case 9:	
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            return sd_r2_s;
        case sd_transfer_state:
            if (!sd->spi)
                break;
            sd->state = sd_sendingdata_state;
            memcpy(sd->data, sd->csd, 16);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 10:	
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            return sd_r2_i;
        case sd_transfer_state:
            if (!sd->spi)
                break;
            sd->state = sd_sendingdata_state;
            memcpy(sd->data, sd->cid, 16);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 11:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = req.arg;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
        default:
            break;
        }
        break;
    case 12:	
        switch (sd->state) {
        case sd_sendingdata_state:
            sd->state = sd_transfer_state;
            return sd_r1b;
        case sd_receivingdata_state:
            sd->state = sd_programming_state;
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 13:	
        switch (sd->mode) {
        case sd_data_transfer_mode:
            if (sd->rca != rca)
            return sd_r1;
        default:
            break;
        }
        break;
    case 15:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->mode) {
        case sd_data_transfer_mode:
            if (sd->rca != rca)
            sd->state = sd_inactive_state;
        default:
            break;
        }
        break;
    
    case 16:	
        switch (sd->state) {
        case sd_transfer_state:
            if (req.arg > (1 << HWBLOCK_SHIFT))
                sd->card_status |= BLOCK_LEN_ERROR;
            else
                sd->blk_len = req.arg;
            return sd_r1;
        default:
            break;
        }
        break;
    case 17:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            return sd_r1;
        default:
            break;
        }
        break;
    case 18:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            return sd_r1;
        default:
            break;
        }
        break;
    
    case 24:	
        if (sd->spi)
            goto unimplemented_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            
            if (sd->spi)
                break;
            sd->state = sd_receivingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            sd->blk_written = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            if (sd_wp_addr(sd, sd->data_start))
                sd->card_status |= WP_VIOLATION;
            if (sd->csd[14] & 0x30)
                sd->card_status |= WP_VIOLATION;
            return sd_r1;
        default:
            break;
        }
        break;
    case 25:	
        if (sd->spi)
            goto unimplemented_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            
            if (sd->spi)
                break;
            sd->state = sd_receivingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            sd->blk_written = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            if (sd_wp_addr(sd, sd->data_start))
                sd->card_status |= WP_VIOLATION;
            if (sd->csd[14] & 0x30)
                sd->card_status |= WP_VIOLATION;
            return sd_r1;
        default:
            break;
        }
        break;
    case 26:	
        if (sd->spi)
            goto bad_cmd;
        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:	
        if (sd->spi)
            goto unimplemented_cmd;
        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 28:	
        switch (sd->state) {
        case sd_transfer_state:
            if (addr >= sd->size) {
                sd->card_status = ADDRESS_ERROR;
                return sd_r1b;
            }
            sd->state = sd_programming_state;
            sd->wp_groups[addr >> (HWBLOCK_SHIFT +
                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 1;
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 29:	
        switch (sd->state) {
        case sd_transfer_state:
            if (addr >= sd->size) {
                sd->card_status = ADDRESS_ERROR;
                return sd_r1b;
            }
            sd->state = sd_programming_state;
            sd->wp_groups[addr >> (HWBLOCK_SHIFT +
                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 0;
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 30:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            *(uint32_t *) sd->data = sd_wpbits(sd, req.arg);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1b;
        default:
            break;
        }
        break;
    
    case 32:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->erase_start = req.arg;
            return sd_r1;
        default:
            break;
        }
        break;
    case 33:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->erase_end = req.arg;
            return sd_r1;
        default:
            break;
        }
        break;
    case 38:	
        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);
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    
    case 42:	
        if (sd->spi)
            goto unimplemented_cmd;
        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 55:	
        if (sd->rca != rca)
        sd->card_status |= APP_CMD;
        return sd_r1;
    case 56:	
        fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
        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;
    default:
    bad_cmd:
        fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd);
    unimplemented_cmd:
        
        fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd);
    }
    fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd);
}
static sd_rsp_type_t FUNC_0(SDState *sd,
                                       SDRequest req)
{
    uint32_t rca = 0x0000;
    uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
    if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
        rca = req.arg >> 16;
    DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state);
    switch (req.cmd) {
    
    case 0:	
        switch (sd->state) {
        case sd_inactive_state:
            return sd->spi ? sd_r1 : sd_r0;
        default:
            sd->state = sd_idle_state;
            sd_reset(sd, sd->bdrv);
            return sd->spi ? sd_r1 : sd_r0;
        }
        break;
    case 1:	
        if (!sd->spi)
            goto bad_cmd;
        sd->state = sd_transfer_state;
        return sd_r1;
    case 2:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_ready_state:
            sd->state = sd_identification_state;
            return sd_r2_i;
        default:
            break;
        }
        break;
    case 3:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_identification_state:
        case sd_standby_state:
            sd->state = sd_standby_state;
            sd_set_rca(sd);
            return sd_r6;
        default:
            break;
        }
        break;
    case 4:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_standby_state:
            break;
        default:
            break;
        }
        break;
    case 5: 
    case 6:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->mode) {
        case sd_data_transfer_mode:
            sd_function_switch(sd, req.arg);
            sd->state = sd_sendingdata_state;
            sd->data_start = 0;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 7:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            sd->state = sd_transfer_state;
            return sd_r1b;
        case sd_transfer_state:
        case sd_sendingdata_state:
            if (sd->rca == rca)
                break;
            sd->state = sd_standby_state;
            return sd_r1b;
        case sd_disconnect_state:
            if (sd->rca != rca)
            sd->state = sd_programming_state;
            return sd_r1b;
        case sd_programming_state:
            if (sd->rca == rca)
                break;
            sd->state = sd_disconnect_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 8:	
        
        switch (sd->state) {
        case sd_idle_state:
            sd->vhs = 0;
            
            if (!(req.arg >> 8) || (req.arg >> ffs(req.arg & ~0xff)))
                return sd->spi ? sd_r7 : sd_r0;
            
            sd->vhs = req.arg;
            return sd_r7;
        default:
            break;
        }
        break;
    case 9:	
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            return sd_r2_s;
        case sd_transfer_state:
            if (!sd->spi)
                break;
            sd->state = sd_sendingdata_state;
            memcpy(sd->data, sd->csd, 16);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 10:	
        switch (sd->state) {
        case sd_standby_state:
            if (sd->rca != rca)
            return sd_r2_i;
        case sd_transfer_state:
            if (!sd->spi)
                break;
            sd->state = sd_sendingdata_state;
            memcpy(sd->data, sd->cid, 16);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1;
        default:
            break;
        }
        break;
    case 11:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = req.arg;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
        default:
            break;
        }
        break;
    case 12:	
        switch (sd->state) {
        case sd_sendingdata_state:
            sd->state = sd_transfer_state;
            return sd_r1b;
        case sd_receivingdata_state:
            sd->state = sd_programming_state;
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 13:	
        switch (sd->mode) {
        case sd_data_transfer_mode:
            if (sd->rca != rca)
            return sd_r1;
        default:
            break;
        }
        break;
    case 15:	
        if (sd->spi)
            goto bad_cmd;
        switch (sd->mode) {
        case sd_data_transfer_mode:
            if (sd->rca != rca)
            sd->state = sd_inactive_state;
        default:
            break;
        }
        break;
    
    case 16:	
        switch (sd->state) {
        case sd_transfer_state:
            if (req.arg > (1 << HWBLOCK_SHIFT))
                sd->card_status |= BLOCK_LEN_ERROR;
            else
                sd->blk_len = req.arg;
            return sd_r1;
        default:
            break;
        }
        break;
    case 17:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            return sd_r1;
        default:
            break;
        }
        break;
    case 18:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            return sd_r1;
        default:
            break;
        }
        break;
    
    case 24:	
        if (sd->spi)
            goto unimplemented_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            
            if (sd->spi)
                break;
            sd->state = sd_receivingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            sd->blk_written = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            if (sd_wp_addr(sd, sd->data_start))
                sd->card_status |= WP_VIOLATION;
            if (sd->csd[14] & 0x30)
                sd->card_status |= WP_VIOLATION;
            return sd_r1;
        default:
            break;
        }
        break;
    case 25:	
        if (sd->spi)
            goto unimplemented_cmd;
        switch (sd->state) {
        case sd_transfer_state:
            
            if (sd->spi)
                break;
            sd->state = sd_receivingdata_state;
            sd->data_start = addr;
            sd->data_offset = 0;
            sd->blk_written = 0;
            if (sd->data_start + sd->blk_len > sd->size)
                sd->card_status |= ADDRESS_ERROR;
            if (sd_wp_addr(sd, sd->data_start))
                sd->card_status |= WP_VIOLATION;
            if (sd->csd[14] & 0x30)
                sd->card_status |= WP_VIOLATION;
            return sd_r1;
        default:
            break;
        }
        break;
    case 26:	
        if (sd->spi)
            goto bad_cmd;
        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:	
        if (sd->spi)
            goto unimplemented_cmd;
        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 28:	
        switch (sd->state) {
        case sd_transfer_state:
            if (addr >= sd->size) {
                sd->card_status = ADDRESS_ERROR;
                return sd_r1b;
            }
            sd->state = sd_programming_state;
            sd->wp_groups[addr >> (HWBLOCK_SHIFT +
                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 1;
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 29:	
        switch (sd->state) {
        case sd_transfer_state:
            if (addr >= sd->size) {
                sd->card_status = ADDRESS_ERROR;
                return sd_r1b;
            }
            sd->state = sd_programming_state;
            sd->wp_groups[addr >> (HWBLOCK_SHIFT +
                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 0;
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    case 30:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->state = sd_sendingdata_state;
            *(uint32_t *) sd->data = sd_wpbits(sd, req.arg);
            sd->data_start = addr;
            sd->data_offset = 0;
            return sd_r1b;
        default:
            break;
        }
        break;
    
    case 32:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->erase_start = req.arg;
            return sd_r1;
        default:
            break;
        }
        break;
    case 33:	
        switch (sd->state) {
        case sd_transfer_state:
            sd->erase_end = req.arg;
            return sd_r1;
        default:
            break;
        }
        break;
    case 38:	
        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);
            
            sd->state = sd_transfer_state;
            return sd_r1b;
        default:
            break;
        }
        break;
    
    case 42:	
        if (sd->spi)
            goto unimplemented_cmd;
        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 55:	
        if (sd->rca != rca)
        sd->card_status |= APP_CMD;
        return sd_r1;
    case 56:	
        fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
        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;
    default:
    bad_cmd:
        fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd);
    unimplemented_cmd:
        
        fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd);
    }
    fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd);
}
static sd_rsp_type_t FUNC_0(SDState *sd,
SDRequest req)
{ uint32_t rca = 0x0000; uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg; if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
rca = req.arg >> 16; DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state); switch (req.cmd) { case 0:
switch (sd->state) { case sd_inactive_state:
return sd->spi ? sd_r1 : sd_r0; default:
sd->state = sd_idle_state; sd_reset(sd, sd->bdrv); return sd->spi ? sd_r1 : sd_r0; } break; case 1:
if (!sd->spi)
goto bad_cmd; sd->state = sd_transfer_state; return sd_r1; case 2:
if (sd->spi)
goto bad_cmd; switch (sd->state) { case sd_ready_state:
sd->state = sd_identification_state; return sd_r2_i; default:
break; } break; case 3:
if (sd->spi)
goto bad_cmd; switch (sd->state) { case sd_identification_state:
case sd_standby_state:
sd->state = sd_standby_state; sd_set_rca(sd); return sd_r6; default:
break; } break; case 4:
if (sd->spi)
goto bad_cmd; switch (sd->state) { case sd_standby_state:
break; default:
break; } break; case 5:
case 6:
if (sd->spi)
goto bad_cmd; switch (sd->mode) { case sd_data_transfer_mode:
sd_function_switch(sd, req.arg); sd->state = sd_sendingdata_state; sd->data_start = 0; sd->data_offset = 0; return sd_r1; default:
break; } break; case 7:
if (sd->spi)
goto bad_cmd; switch (sd->state) { case sd_standby_state:
if (sd->rca != rca)
sd->state = sd_transfer_state; return sd_r1b; case sd_transfer_state:
case sd_sendingdata_state:
if (sd->rca == rca)
break; sd->state = sd_standby_state; return sd_r1b; case sd_disconnect_state:
if (sd->rca != rca)
sd->state = sd_programming_state; return sd_r1b; case sd_programming_state:
if (sd->rca == rca)
break; sd->state = sd_disconnect_state; return sd_r1b; default:
break; } break; case 8:
switch (sd->state) { case sd_idle_state:
sd->vhs = 0; if (!(req.arg >> 8) || (req.arg >> ffs(req.arg & ~0xff)))
return sd->spi ? sd_r7 : sd_r0; sd->vhs = req.arg; return sd_r7; default:
break; } break; case 9:
switch (sd->state) { case sd_standby_state:
if (sd->rca != rca)
return sd_r2_s; case sd_transfer_state:
if (!sd->spi)
break; sd->state = sd_sendingdata_state; memcpy(sd->data, sd->csd, 16); sd->data_start = addr; sd->data_offset = 0; return sd_r1; default:
break; } break; case 10:
switch (sd->state) { case sd_standby_state:
if (sd->rca != rca)
return sd_r2_i; case sd_transfer_state:
if (!sd->spi)
break; sd->state = sd_sendingdata_state; memcpy(sd->data, sd->cid, 16); sd->data_start = addr; sd->data_offset = 0; return sd_r1; default:
break; } break; case 11:
if (sd->spi)
goto bad_cmd; switch (sd->state) { case sd_transfer_state:
sd->state = sd_sendingdata_state; sd->data_start = req.arg; sd->data_offset = 0; if (sd->data_start + sd->blk_len > sd->size)
sd->card_status |= ADDRESS_ERROR; default:
break; } break; case 12:
switch (sd->state) { case sd_sendingdata_state:
sd->state = sd_transfer_state; return sd_r1b; case sd_receivingdata_state:
sd->state = sd_programming_state; sd->state = sd_transfer_state; return sd_r1b; default:
break; } break; case 13:
switch (sd->mode) { case sd_data_transfer_mode:
if (sd->rca != rca)
return sd_r1; default:
break; } break; case 15:
if (sd->spi)
goto bad_cmd; switch (sd->mode) { case sd_data_transfer_mode:
if (sd->rca != rca)
sd->state = sd_inactive_state; default:
break; } break; case 16:
switch (sd->state) { case sd_transfer_state:
if (req.arg > (1 << HWBLOCK_SHIFT))
sd->card_status |= BLOCK_LEN_ERROR; else
sd->blk_len = req.arg; return sd_r1; default:
break; } break; case 17:
switch (sd->state) { case sd_transfer_state:
sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; if (sd->data_start + sd->blk_len > sd->size)
sd->card_status |= ADDRESS_ERROR; return sd_r1; default:
break; } break; case 18:
switch (sd->state) { case sd_transfer_state:
sd->state = sd_sendingdata_state; sd->data_start = addr; sd->data_offset = 0; if (sd->data_start + sd->blk_len > sd->size)
sd->card_status |= ADDRESS_ERROR; return sd_r1; default:
break; } break; case 24:
if (sd->spi)
goto unimplemented_cmd; switch (sd->state) { case sd_transfer_state:
if (sd->spi)
break; sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; sd->blk_written = 0; if (sd->data_start + sd->blk_len > sd->size)
sd->card_status |= ADDRESS_ERROR; if (sd_wp_addr(sd, sd->data_start))
sd->card_status |= WP_VIOLATION; if (sd->csd[14] & 0x30)
sd->card_status |= WP_VIOLATION; return sd_r1; default:
break; } break; case 25:
if (sd->spi)
goto unimplemented_cmd; switch (sd->state) { case sd_transfer_state:
if (sd->spi)
break; sd->state = sd_receivingdata_state; sd->data_start = addr; sd->data_offset = 0; sd->blk_written = 0; if (sd->data_start + sd->blk_len > sd->size)
sd->card_status |= ADDRESS_ERROR; if (sd_wp_addr(sd, sd->data_start))
sd->card_status |= WP_VIOLATION; if (sd->csd[14] & 0x30)
sd->card_status |= WP_VIOLATION; return sd_r1; default:
break; } break; case 26:
if (sd->spi)
goto bad_cmd; 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:
if (sd->spi)
goto unimplemented_cmd; 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 28:
switch (sd->state) { case sd_transfer_state:
if (addr >= sd->size) { sd->card_status = ADDRESS_ERROR; return sd_r1b; } sd->state = sd_programming_state; sd->wp_groups[addr >> (HWBLOCK_SHIFT +
SECTOR_SHIFT + WPGROUP_SHIFT)] = 1; sd->state = sd_transfer_state; return sd_r1b; default:
break; } break; case 29:
switch (sd->state) { case sd_transfer_state:
if (addr >= sd->size) { sd->card_status = ADDRESS_ERROR; return sd_r1b; } sd->state = sd_programming_state; sd->wp_groups[addr >> (HWBLOCK_SHIFT +
SECTOR_SHIFT + WPGROUP_SHIFT)] = 0; sd->state = sd_transfer_state; return sd_r1b; default:
break; } break; case 30:
switch (sd->state) { case sd_transfer_state:
sd->state = sd_sendingdata_state; *(uint32_t *) sd->data = sd_wpbits(sd, req.arg); sd->data_start = addr; sd->data_offset = 0; return sd_r1b; default:
break; } break; case 32:
switch (sd->state) { case sd_transfer_state:
sd->erase_start = req.arg; return sd_r1; default:
break; } break; case 33:
switch (sd->state) { case sd_transfer_state:
sd->erase_end = req.arg; return sd_r1; default:
break; } break; case 38:
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); sd->state = sd_transfer_state; return sd_r1b; default:
break; } break; case 42:
if (sd->spi)
goto unimplemented_cmd; 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 55:
if (sd->rca != rca)
sd->card_status |= APP_CMD; return sd_r1; case 56:
fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg); 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; default:
bad_cmd:
fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd); unimplemented_cmd:
fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd); } fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd); }