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

« back to all changes in this revision

Viewing changes to .pc/linaro-patches/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: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

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
    register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
 
250
    return 0;
 
251
}
 
252
 
 
253
static void ssi_sd_class_init(ObjectClass *klass, void *data)
 
254
{
 
255
    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
 
256
 
 
257
    k->init = ssi_sd_init;
 
258
    k->transfer = ssi_sd_transfer;
 
259
    k->cs_polarity = SSI_CS_LOW;
 
260
}
 
261
 
 
262
static const TypeInfo ssi_sd_info = {
 
263
    .name          = "ssi-sd",
 
264
    .parent        = TYPE_SSI_SLAVE,
 
265
    .instance_size = sizeof(ssi_sd_state),
 
266
    .class_init    = ssi_sd_class_init,
 
267
};
 
268
 
 
269
static void ssi_sd_register_types(void)
 
270
{
 
271
    type_register_static(&ssi_sd_info);
 
272
}
 
273
 
 
274
type_init(ssi_sd_register_types)