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

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

unix.superglobalmegacorp.com

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