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

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: 
        !           193: void *ssi_sd_init(BlockDriverState *bs)
        !           194: {
        !           195:     ssi_sd_state *s;
        !           196: 
        !           197:     s = (ssi_sd_state *)qemu_mallocz(sizeof(ssi_sd_state));
        !           198:     s->mode = SSI_SD_CMD;
        !           199:     s->sd = sd_init(bs, 1);
        !           200:     return s;
        !           201: }
        !           202: 

unix.superglobalmegacorp.com

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