Annotation of qemu/hw/ssi-sd.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.