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