~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to .pc/ubuntu/linaro/0003-sd-Allow-sd_init-callers-to-specify-whether-card-is-.patch/hw/sd/ssi-sd.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-04 12:13:08 UTC
  • mfrom: (10.1.45 sid)
  • Revision ID: package-import@ubuntu.com-20140204121308-1xq92lrfs75agw2g
Tags: 1.7.0+dfsg-3ubuntu1~ppa1
* Merge 1.7.0+dfsg-3 from debian.  Remaining changes:
  - debian/patches/ubuntu:
    * expose-vmx_qemu64cpu.patch
    * linaro (omap3) and arm64 patches
    * ubuntu/target-ppc-add-stubs-for-kvm-breakpoints: fix FTBFS
      on ppc
    * ubuntu/CVE-2013-4377.patch: fix denial of service via virtio
  - debian/qemu-system-x86.modprobe: set kvm_intel nested=1 options
  - debian/control:
    * add arm64 to Architectures
    * add qemu-common and qemu-system-aarch64 packages
  - debian/qemu-system-common.install: add debian/tmp/usr/lib
  - debian/qemu-system-common.preinst: add kvm group
  - debian/qemu-system-common.postinst: remove acl placed by udev,
    and add udevadm trigger.
  - qemu-system-x86.links: add eepro100.rom, remove pxe-virtio,
    pxe-e1000 and pxe-rtl8139.
  - add qemu-system-x86.qemu-kvm.upstart and .default
  - qemu-user-static.postinst-in: remove arm64 binfmt
  - debian/rules:
    * allow parallel build
    * add aarch64 to system_targets and sys_systems
    * add qemu-kvm-spice links
    * install qemu-system-x86.modprobe
  - add debian/qemu-system-common.links for OVMF.fd link
* Remove kvm-img, kvm-nbd, kvm-ifup and kvm-ifdown symlinks.

Show diffs side-by-side

added added

removed removed

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