qemu/hw/sd/ssi-sd.c
<<
>>
Prefs
   1/*
   2 * SSI to SD card adapter.
   3 *
   4 * Copyright (c) 2007-2009 CodeSourcery.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the GNU GPL v2.
   8 *
   9 * Contributions after 2012-01-13 are licensed under the terms of the
  10 * GNU GPL, version 2 or (at your option) any later version.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "sysemu/block-backend.h"
  15#include "sysemu/blockdev.h"
  16#include "hw/ssi/ssi.h"
  17#include "hw/sd/sd.h"
  18#include "qapi/error.h"
  19
  20//#define DEBUG_SSI_SD 1
  21
  22#ifdef DEBUG_SSI_SD
  23#define DPRINTF(fmt, ...) \
  24do { printf("ssi_sd: " fmt , ## __VA_ARGS__); } while (0)
  25#define BADF(fmt, ...) \
  26do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
  27#else
  28#define DPRINTF(fmt, ...) do {} while(0)
  29#define BADF(fmt, ...) \
  30do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0)
  31#endif
  32
  33typedef enum {
  34    SSI_SD_CMD = 0,
  35    SSI_SD_CMDARG,
  36    SSI_SD_RESPONSE,
  37    SSI_SD_DATA_START,
  38    SSI_SD_DATA_READ,
  39} ssi_sd_mode;
  40
  41typedef struct {
  42    SSISlave ssidev;
  43    uint32_t mode;
  44    int cmd;
  45    uint8_t cmdarg[4];
  46    uint8_t response[5];
  47    int32_t arglen;
  48    int32_t response_pos;
  49    int32_t stopping;
  50    SDState *sd;
  51} ssi_sd_state;
  52
  53/* State word bits.  */
  54#define SSI_SDR_LOCKED          0x0001
  55#define SSI_SDR_WP_ERASE        0x0002
  56#define SSI_SDR_ERROR           0x0004
  57#define SSI_SDR_CC_ERROR        0x0008
  58#define SSI_SDR_ECC_FAILED      0x0010
  59#define SSI_SDR_WP_VIOLATION    0x0020
  60#define SSI_SDR_ERASE_PARAM     0x0040
  61#define SSI_SDR_OUT_OF_RANGE    0x0080
  62#define SSI_SDR_IDLE            0x0100
  63#define SSI_SDR_ERASE_RESET     0x0200
  64#define SSI_SDR_ILLEGAL_COMMAND 0x0400
  65#define SSI_SDR_COM_CRC_ERROR   0x0800
  66#define SSI_SDR_ERASE_SEQ_ERROR 0x1000
  67#define SSI_SDR_ADDRESS_ERROR   0x2000
  68#define SSI_SDR_PARAMETER_ERROR 0x4000
  69
  70static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
  71{
  72    ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
  73
  74    /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data.  */
  75    if (s->mode == SSI_SD_DATA_READ && val == 0x4d) {
  76        s->mode = SSI_SD_CMD;
  77        /* There must be at least one byte delay before the card responds.  */
  78        s->stopping = 1;
  79    }
  80
  81    switch (s->mode) {
  82    case SSI_SD_CMD:
  83        if (val == 0xff) {
  84            DPRINTF("NULL command\n");
  85            return 0xff;
  86        }
  87        s->cmd = val & 0x3f;
  88        s->mode = SSI_SD_CMDARG;
  89        s->arglen = 0;
  90        return 0xff;
  91    case SSI_SD_CMDARG:
  92        if (s->arglen == 4) {
  93            SDRequest request;
  94            uint8_t longresp[16];
  95            /* FIXME: Check CRC.  */
  96            request.cmd = s->cmd;
  97            request.arg = (s->cmdarg[0] << 24) | (s->cmdarg[1] << 16)
  98                           | (s->cmdarg[2] << 8) | s->cmdarg[3];
  99            DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
 100            s->arglen = sd_do_command(s->sd, &request, longresp);
 101            if (s->arglen <= 0) {
 102                s->arglen = 1;
 103                s->response[0] = 4;
 104                DPRINTF("SD command failed\n");
 105            } else if (s->cmd == 58) {
 106                /* CMD58 returns R3 response (OCR)  */
 107                DPRINTF("Returned OCR\n");
 108                s->arglen = 5;
 109                s->response[0] = 1;
 110                memcpy(&s->response[1], longresp, 4);
 111            } else if (s->arglen != 4) {
 112                BADF("Unexpected response to cmd %d\n", s->cmd);
 113                /* Illegal command is about as near as we can get.  */
 114                s->arglen = 1;
 115                s->response[0] = 4;
 116            } else {
 117                /* All other commands return status.  */
 118                uint32_t cardstatus;
 119                uint16_t status;
 120                /* CMD13 returns a 2-byte statuse work. Other commands
 121                   only return the first byte.  */
 122                s->arglen = (s->cmd == 13) ? 2 : 1;
 123                cardstatus = (longresp[0] << 24) | (longresp[1] << 16)
 124                             | (longresp[2] << 8) | longresp[3];
 125                status = 0;
 126                if (((cardstatus >> 9) & 0xf) < 4)
 127                    status |= SSI_SDR_IDLE;
 128                if (cardstatus & ERASE_RESET)
 129                    status |= SSI_SDR_ERASE_RESET;
 130                if (cardstatus & ILLEGAL_COMMAND)
 131                    status |= SSI_SDR_ILLEGAL_COMMAND;
 132                if (cardstatus & COM_CRC_ERROR)
 133                    status |= SSI_SDR_COM_CRC_ERROR;
 134                if (cardstatus & ERASE_SEQ_ERROR)
 135                    status |= SSI_SDR_ERASE_SEQ_ERROR;
 136                if (cardstatus & ADDRESS_ERROR)
 137                    status |= SSI_SDR_ADDRESS_ERROR;
 138                if (cardstatus & CARD_IS_LOCKED)
 139                    status |= SSI_SDR_LOCKED;
 140                if (cardstatus & (LOCK_UNLOCK_FAILED | WP_ERASE_SKIP))
 141                    status |= SSI_SDR_WP_ERASE;
 142                if (cardstatus & SD_ERROR)
 143                    status |= SSI_SDR_ERROR;
 144                if (cardstatus & CC_ERROR)
 145                    status |= SSI_SDR_CC_ERROR;
 146                if (cardstatus & CARD_ECC_FAILED)
 147                    status |= SSI_SDR_ECC_FAILED;
 148                if (cardstatus & WP_VIOLATION)
 149                    status |= SSI_SDR_WP_VIOLATION;
 150                if (cardstatus & ERASE_PARAM)
 151                    status |= SSI_SDR_ERASE_PARAM;
 152                if (cardstatus & (OUT_OF_RANGE | CID_CSD_OVERWRITE))
 153                    status |= SSI_SDR_OUT_OF_RANGE;
 154                /* ??? Don't know what Parameter Error really means, so
 155                   assume it's set if the second byte is nonzero.  */
 156                if (status & 0xff)
 157                    status |= SSI_SDR_PARAMETER_ERROR;
 158                s->response[0] = status >> 8;
 159                s->response[1] = status;
 160                DPRINTF("Card status 0x%02x\n", status);
 161            }
 162            s->mode = SSI_SD_RESPONSE;
 163            s->response_pos = 0;
 164        } else {
 165            s->cmdarg[s->arglen++] = val;
 166        }
 167        return 0xff;
 168    case SSI_SD_RESPONSE:
 169        if (s->stopping) {
 170            s->stopping = 0;
 171            return 0xff;
 172        }
 173        if (s->response_pos < s->arglen) {
 174            DPRINTF("Response 0x%02x\n", s->response[s->response_pos]);
 175            return s->response[s->response_pos++];
 176        }
 177        if (sd_data_ready(s->sd)) {
 178            DPRINTF("Data read\n");
 179            s->mode = SSI_SD_DATA_START;
 180        } else {
 181            DPRINTF("End of command\n");
 182            s->mode = SSI_SD_CMD;
 183        }
 184        return 0xff;
 185    case SSI_SD_DATA_START:
 186        DPRINTF("Start read block\n");
 187        s->mode = SSI_SD_DATA_READ;
 188        return 0xfe;
 189    case SSI_SD_DATA_READ:
 190        val = sd_read_data(s->sd);
 191        if (!sd_data_ready(s->sd)) {
 192            DPRINTF("Data read end\n");
 193            s->mode = SSI_SD_CMD;
 194        }
 195        return val;
 196    }
 197    /* Should never happen.  */
 198    return 0xff;
 199}
 200
 201static int ssi_sd_post_load(void *opaque, int version_id)
 202{
 203    ssi_sd_state *s = (ssi_sd_state *)opaque;
 204
 205    if (s->mode > SSI_SD_DATA_READ) {
 206        return -EINVAL;
 207    }
 208    if (s->mode == SSI_SD_CMDARG &&
 209        (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
 210        return -EINVAL;
 211    }
 212    if (s->mode == SSI_SD_RESPONSE &&
 213        (s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
 214        (!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
 215        return -EINVAL;
 216    }
 217
 218    return 0;
 219}
 220
 221static const VMStateDescription vmstate_ssi_sd = {
 222    .name = "ssi_sd",
 223    .version_id = 2,
 224    .minimum_version_id = 2,
 225    .post_load = ssi_sd_post_load,
 226    .fields = (VMStateField []) {
 227        VMSTATE_UINT32(mode, ssi_sd_state),
 228        VMSTATE_INT32(cmd, ssi_sd_state),
 229        VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4),
 230        VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
 231        VMSTATE_INT32(arglen, ssi_sd_state),
 232        VMSTATE_INT32(response_pos, ssi_sd_state),
 233        VMSTATE_INT32(stopping, ssi_sd_state),
 234        VMSTATE_SSI_SLAVE(ssidev, ssi_sd_state),
 235        VMSTATE_END_OF_LIST()
 236    }
 237};
 238
 239static void ssi_sd_realize(SSISlave *d, Error **errp)
 240{
 241    ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
 242    DriveInfo *dinfo;
 243
 244    s->mode = SSI_SD_CMD;
 245    /* FIXME use a qdev drive property instead of drive_get_next() */
 246    dinfo = drive_get_next(IF_SD);
 247    s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true);
 248    if (s->sd == NULL) {
 249        error_setg(errp, "Device initialization failed.");
 250        return;
 251    }
 252}
 253
 254static void ssi_sd_class_init(ObjectClass *klass, void *data)
 255{
 256    DeviceClass *dc = DEVICE_CLASS(klass);
 257    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
 258
 259    k->realize = ssi_sd_realize;
 260    k->transfer = ssi_sd_transfer;
 261    k->cs_polarity = SSI_CS_LOW;
 262    dc->vmsd = &vmstate_ssi_sd;
 263}
 264
 265static const TypeInfo ssi_sd_info = {
 266    .name          = "ssi-sd",
 267    .parent        = TYPE_SSI_SLAVE,
 268    .instance_size = sizeof(ssi_sd_state),
 269    .class_init    = ssi_sd_class_init,
 270};
 271
 272static void ssi_sd_register_types(void)
 273{
 274    type_register_static(&ssi_sd_info);
 275}
 276
 277type_init(ssi_sd_register_types)
 278