Statistics
| Branch: | Revision:

root / hw / virtio-scsi.c @ 9a3a8895

History | View | Annotate | Download (21.6 kB)

1 973abc7f Stefan Hajnoczi
/*
2 973abc7f Stefan Hajnoczi
 * Virtio SCSI HBA
3 973abc7f Stefan Hajnoczi
 *
4 973abc7f Stefan Hajnoczi
 * Copyright IBM, Corp. 2010
5 973abc7f Stefan Hajnoczi
 * Copyright Red Hat, Inc. 2011
6 973abc7f Stefan Hajnoczi
 *
7 973abc7f Stefan Hajnoczi
 * Authors:
8 973abc7f Stefan Hajnoczi
 *   Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
9 973abc7f Stefan Hajnoczi
 *   Paolo Bonzini      <pbonzini@redhat.com>
10 973abc7f Stefan Hajnoczi
 *
11 973abc7f Stefan Hajnoczi
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
12 973abc7f Stefan Hajnoczi
 * See the COPYING file in the top-level directory.
13 973abc7f Stefan Hajnoczi
 *
14 973abc7f Stefan Hajnoczi
 */
15 973abc7f Stefan Hajnoczi
16 973abc7f Stefan Hajnoczi
#include "virtio-scsi.h"
17 973abc7f Stefan Hajnoczi
#include <hw/scsi.h>
18 973abc7f Stefan Hajnoczi
#include <hw/scsi-defs.h>
19 973abc7f Stefan Hajnoczi
20 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_VQ_SIZE     128
21 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_CDB_SIZE    32
22 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_SENSE_SIZE  96
23 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_MAX_CHANNEL 0
24 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_MAX_TARGET  255
25 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_MAX_LUN     16383
26 973abc7f Stefan Hajnoczi
27 973abc7f Stefan Hajnoczi
/* Response codes */
28 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_OK                       0
29 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_OVERRUN                  1
30 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_ABORTED                  2
31 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_BAD_TARGET               3
32 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_RESET                    4
33 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_BUSY                     5
34 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
35 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_TARGET_FAILURE           7
36 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
37 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_FAILURE                  9
38 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
39 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
40 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_S_INCORRECT_LUN            12
41 973abc7f Stefan Hajnoczi
42 973abc7f Stefan Hajnoczi
/* Controlq type codes.  */
43 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF                      0
44 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_AN_QUERY                 1
45 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
46 973abc7f Stefan Hajnoczi
47 973abc7f Stefan Hajnoczi
/* Valid TMF subtypes.  */
48 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
49 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
50 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
51 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
52 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
53 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
54 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
55 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
56 973abc7f Stefan Hajnoczi
57 973abc7f Stefan Hajnoczi
/* Events.  */
58 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
59 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_NO_EVENT                 0
60 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
61 973abc7f Stefan Hajnoczi
#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
62 feda01e4 Paolo Bonzini
#define VIRTIO_SCSI_T_PARAM_CHANGE             3
63 973abc7f Stefan Hajnoczi
64 b6866fee Cong Meng
/* Reasons for transport reset event */
65 b6866fee Cong Meng
#define VIRTIO_SCSI_EVT_RESET_HARD             0
66 b6866fee Cong Meng
#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
67 b6866fee Cong Meng
#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
68 b6866fee Cong Meng
69 973abc7f Stefan Hajnoczi
/* SCSI command request, followed by data-out */
70 973abc7f Stefan Hajnoczi
typedef struct {
71 973abc7f Stefan Hajnoczi
    uint8_t lun[8];              /* Logical Unit Number */
72 973abc7f Stefan Hajnoczi
    uint64_t tag;                /* Command identifier */
73 973abc7f Stefan Hajnoczi
    uint8_t task_attr;           /* Task attribute */
74 973abc7f Stefan Hajnoczi
    uint8_t prio;
75 973abc7f Stefan Hajnoczi
    uint8_t crn;
76 973abc7f Stefan Hajnoczi
    uint8_t cdb[];
77 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSICmdReq;
78 973abc7f Stefan Hajnoczi
79 973abc7f Stefan Hajnoczi
/* Response, followed by sense data and data-in */
80 973abc7f Stefan Hajnoczi
typedef struct {
81 973abc7f Stefan Hajnoczi
    uint32_t sense_len;          /* Sense data length */
82 973abc7f Stefan Hajnoczi
    uint32_t resid;              /* Residual bytes in data buffer */
83 973abc7f Stefan Hajnoczi
    uint16_t status_qualifier;   /* Status qualifier */
84 973abc7f Stefan Hajnoczi
    uint8_t status;              /* Command completion status */
85 973abc7f Stefan Hajnoczi
    uint8_t response;            /* Response values */
86 973abc7f Stefan Hajnoczi
    uint8_t sense[];
87 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSICmdResp;
88 973abc7f Stefan Hajnoczi
89 973abc7f Stefan Hajnoczi
/* Task Management Request */
90 973abc7f Stefan Hajnoczi
typedef struct {
91 973abc7f Stefan Hajnoczi
    uint32_t type;
92 973abc7f Stefan Hajnoczi
    uint32_t subtype;
93 973abc7f Stefan Hajnoczi
    uint8_t lun[8];
94 973abc7f Stefan Hajnoczi
    uint64_t tag;
95 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSICtrlTMFReq;
96 973abc7f Stefan Hajnoczi
97 973abc7f Stefan Hajnoczi
typedef struct {
98 973abc7f Stefan Hajnoczi
    uint8_t response;
99 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSICtrlTMFResp;
100 973abc7f Stefan Hajnoczi
101 973abc7f Stefan Hajnoczi
/* Asynchronous notification query/subscription */
102 973abc7f Stefan Hajnoczi
typedef struct {
103 973abc7f Stefan Hajnoczi
    uint32_t type;
104 973abc7f Stefan Hajnoczi
    uint8_t lun[8];
105 973abc7f Stefan Hajnoczi
    uint32_t event_requested;
106 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSICtrlANReq;
107 973abc7f Stefan Hajnoczi
108 973abc7f Stefan Hajnoczi
typedef struct {
109 973abc7f Stefan Hajnoczi
    uint32_t event_actual;
110 973abc7f Stefan Hajnoczi
    uint8_t response;
111 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSICtrlANResp;
112 973abc7f Stefan Hajnoczi
113 973abc7f Stefan Hajnoczi
typedef struct {
114 973abc7f Stefan Hajnoczi
    uint32_t event;
115 973abc7f Stefan Hajnoczi
    uint8_t lun[8];
116 973abc7f Stefan Hajnoczi
    uint32_t reason;
117 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSIEvent;
118 973abc7f Stefan Hajnoczi
119 973abc7f Stefan Hajnoczi
typedef struct {
120 973abc7f Stefan Hajnoczi
    uint32_t num_queues;
121 973abc7f Stefan Hajnoczi
    uint32_t seg_max;
122 973abc7f Stefan Hajnoczi
    uint32_t max_sectors;
123 973abc7f Stefan Hajnoczi
    uint32_t cmd_per_lun;
124 973abc7f Stefan Hajnoczi
    uint32_t event_info_size;
125 973abc7f Stefan Hajnoczi
    uint32_t sense_size;
126 973abc7f Stefan Hajnoczi
    uint32_t cdb_size;
127 973abc7f Stefan Hajnoczi
    uint16_t max_channel;
128 973abc7f Stefan Hajnoczi
    uint16_t max_target;
129 973abc7f Stefan Hajnoczi
    uint32_t max_lun;
130 973abc7f Stefan Hajnoczi
} QEMU_PACKED VirtIOSCSIConfig;
131 973abc7f Stefan Hajnoczi
132 973abc7f Stefan Hajnoczi
typedef struct {
133 973abc7f Stefan Hajnoczi
    VirtIODevice vdev;
134 973abc7f Stefan Hajnoczi
    DeviceState *qdev;
135 973abc7f Stefan Hajnoczi
    VirtIOSCSIConf *conf;
136 973abc7f Stefan Hajnoczi
137 2ccdcd8d Paolo Bonzini
    SCSIBus bus;
138 973abc7f Stefan Hajnoczi
    uint32_t sense_size;
139 973abc7f Stefan Hajnoczi
    uint32_t cdb_size;
140 06114d72 Paolo Bonzini
    int resetting;
141 64f64855 Paolo Bonzini
    bool events_dropped;
142 d2ad7dd4 Paolo Bonzini
    VirtQueue *ctrl_vq;
143 d2ad7dd4 Paolo Bonzini
    VirtQueue *event_vq;
144 d2ad7dd4 Paolo Bonzini
    VirtQueue *cmd_vqs[0];
145 973abc7f Stefan Hajnoczi
} VirtIOSCSI;
146 973abc7f Stefan Hajnoczi
147 326799c0 Stefan Hajnoczi
typedef struct VirtIOSCSIReq {
148 326799c0 Stefan Hajnoczi
    VirtIOSCSI *dev;
149 326799c0 Stefan Hajnoczi
    VirtQueue *vq;
150 326799c0 Stefan Hajnoczi
    VirtQueueElement elem;
151 326799c0 Stefan Hajnoczi
    QEMUSGList qsgl;
152 326799c0 Stefan Hajnoczi
    SCSIRequest *sreq;
153 326799c0 Stefan Hajnoczi
    union {
154 326799c0 Stefan Hajnoczi
        char                  *buf;
155 326799c0 Stefan Hajnoczi
        VirtIOSCSICmdReq      *cmd;
156 326799c0 Stefan Hajnoczi
        VirtIOSCSICtrlTMFReq  *tmf;
157 326799c0 Stefan Hajnoczi
        VirtIOSCSICtrlANReq   *an;
158 326799c0 Stefan Hajnoczi
    } req;
159 326799c0 Stefan Hajnoczi
    union {
160 326799c0 Stefan Hajnoczi
        char                  *buf;
161 326799c0 Stefan Hajnoczi
        VirtIOSCSICmdResp     *cmd;
162 326799c0 Stefan Hajnoczi
        VirtIOSCSICtrlTMFResp *tmf;
163 326799c0 Stefan Hajnoczi
        VirtIOSCSICtrlANResp  *an;
164 326799c0 Stefan Hajnoczi
        VirtIOSCSIEvent       *event;
165 326799c0 Stefan Hajnoczi
    } resp;
166 326799c0 Stefan Hajnoczi
} VirtIOSCSIReq;
167 326799c0 Stefan Hajnoczi
168 2ccdcd8d Paolo Bonzini
static inline int virtio_scsi_get_lun(uint8_t *lun)
169 2ccdcd8d Paolo Bonzini
{
170 2ccdcd8d Paolo Bonzini
    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
171 2ccdcd8d Paolo Bonzini
}
172 2ccdcd8d Paolo Bonzini
173 2ccdcd8d Paolo Bonzini
static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
174 2ccdcd8d Paolo Bonzini
{
175 2ccdcd8d Paolo Bonzini
    if (lun[0] != 1) {
176 2ccdcd8d Paolo Bonzini
        return NULL;
177 2ccdcd8d Paolo Bonzini
    }
178 2ccdcd8d Paolo Bonzini
    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
179 2ccdcd8d Paolo Bonzini
        return NULL;
180 2ccdcd8d Paolo Bonzini
    }
181 2ccdcd8d Paolo Bonzini
    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
182 2ccdcd8d Paolo Bonzini
}
183 2ccdcd8d Paolo Bonzini
184 326799c0 Stefan Hajnoczi
static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
185 326799c0 Stefan Hajnoczi
{
186 326799c0 Stefan Hajnoczi
    VirtIOSCSI *s = req->dev;
187 326799c0 Stefan Hajnoczi
    VirtQueue *vq = req->vq;
188 326799c0 Stefan Hajnoczi
    virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len);
189 326799c0 Stefan Hajnoczi
    qemu_sglist_destroy(&req->qsgl);
190 326799c0 Stefan Hajnoczi
    if (req->sreq) {
191 326799c0 Stefan Hajnoczi
        req->sreq->hba_private = NULL;
192 326799c0 Stefan Hajnoczi
        scsi_req_unref(req->sreq);
193 326799c0 Stefan Hajnoczi
    }
194 326799c0 Stefan Hajnoczi
    g_free(req);
195 326799c0 Stefan Hajnoczi
    virtio_notify(&s->vdev, vq);
196 326799c0 Stefan Hajnoczi
}
197 326799c0 Stefan Hajnoczi
198 326799c0 Stefan Hajnoczi
static void virtio_scsi_bad_req(void)
199 326799c0 Stefan Hajnoczi
{
200 326799c0 Stefan Hajnoczi
    error_report("wrong size for virtio-scsi headers");
201 326799c0 Stefan Hajnoczi
    exit(1);
202 326799c0 Stefan Hajnoczi
}
203 326799c0 Stefan Hajnoczi
204 326799c0 Stefan Hajnoczi
static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
205 326799c0 Stefan Hajnoczi
                                   target_phys_addr_t *addr, int num)
206 326799c0 Stefan Hajnoczi
{
207 326799c0 Stefan Hajnoczi
    memset(qsgl, 0, sizeof(*qsgl));
208 326799c0 Stefan Hajnoczi
    while (num--) {
209 326799c0 Stefan Hajnoczi
        qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
210 326799c0 Stefan Hajnoczi
    }
211 326799c0 Stefan Hajnoczi
}
212 326799c0 Stefan Hajnoczi
213 326799c0 Stefan Hajnoczi
static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq,
214 326799c0 Stefan Hajnoczi
                                  VirtIOSCSIReq *req)
215 326799c0 Stefan Hajnoczi
{
216 b6866fee Cong Meng
    assert(req->elem.in_num);
217 326799c0 Stefan Hajnoczi
    req->vq = vq;
218 326799c0 Stefan Hajnoczi
    req->dev = s;
219 326799c0 Stefan Hajnoczi
    req->sreq = NULL;
220 b6866fee Cong Meng
    if (req->elem.out_num) {
221 b6866fee Cong Meng
        req->req.buf = req->elem.out_sg[0].iov_base;
222 b6866fee Cong Meng
    }
223 326799c0 Stefan Hajnoczi
    req->resp.buf = req->elem.in_sg[0].iov_base;
224 326799c0 Stefan Hajnoczi
225 326799c0 Stefan Hajnoczi
    if (req->elem.out_num > 1) {
226 326799c0 Stefan Hajnoczi
        qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
227 326799c0 Stefan Hajnoczi
                               &req->elem.out_addr[1],
228 326799c0 Stefan Hajnoczi
                               req->elem.out_num - 1);
229 326799c0 Stefan Hajnoczi
    } else {
230 326799c0 Stefan Hajnoczi
        qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
231 326799c0 Stefan Hajnoczi
                               &req->elem.in_addr[1],
232 326799c0 Stefan Hajnoczi
                               req->elem.in_num - 1);
233 326799c0 Stefan Hajnoczi
    }
234 326799c0 Stefan Hajnoczi
}
235 326799c0 Stefan Hajnoczi
236 326799c0 Stefan Hajnoczi
static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
237 326799c0 Stefan Hajnoczi
{
238 326799c0 Stefan Hajnoczi
    VirtIOSCSIReq *req;
239 326799c0 Stefan Hajnoczi
    req = g_malloc(sizeof(*req));
240 326799c0 Stefan Hajnoczi
    if (!virtqueue_pop(vq, &req->elem)) {
241 326799c0 Stefan Hajnoczi
        g_free(req);
242 326799c0 Stefan Hajnoczi
        return NULL;
243 326799c0 Stefan Hajnoczi
    }
244 326799c0 Stefan Hajnoczi
245 326799c0 Stefan Hajnoczi
    virtio_scsi_parse_req(s, vq, req);
246 326799c0 Stefan Hajnoczi
    return req;
247 326799c0 Stefan Hajnoczi
}
248 326799c0 Stefan Hajnoczi
249 5db1764c Paolo Bonzini
static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
250 5db1764c Paolo Bonzini
{
251 5db1764c Paolo Bonzini
    VirtIOSCSIReq *req = sreq->hba_private;
252 d2ad7dd4 Paolo Bonzini
    uint32_t n = virtio_queue_get_id(req->vq) - 2;
253 5db1764c Paolo Bonzini
254 d2ad7dd4 Paolo Bonzini
    assert(n < req->dev->conf->num_queues);
255 fcf104a7 Paolo Bonzini
    qemu_put_be32s(f, &n);
256 5db1764c Paolo Bonzini
    qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
257 5db1764c Paolo Bonzini
}
258 5db1764c Paolo Bonzini
259 5db1764c Paolo Bonzini
static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
260 5db1764c Paolo Bonzini
{
261 5db1764c Paolo Bonzini
    SCSIBus *bus = sreq->bus;
262 5db1764c Paolo Bonzini
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
263 5db1764c Paolo Bonzini
    VirtIOSCSIReq *req;
264 fcf104a7 Paolo Bonzini
    uint32_t n;
265 5db1764c Paolo Bonzini
266 5db1764c Paolo Bonzini
    req = g_malloc(sizeof(*req));
267 fcf104a7 Paolo Bonzini
    qemu_get_be32s(f, &n);
268 d2ad7dd4 Paolo Bonzini
    assert(n < s->conf->num_queues);
269 5db1764c Paolo Bonzini
    qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
270 d2ad7dd4 Paolo Bonzini
    virtio_scsi_parse_req(s, s->cmd_vqs[n], req);
271 5db1764c Paolo Bonzini
272 5db1764c Paolo Bonzini
    scsi_req_ref(sreq);
273 5db1764c Paolo Bonzini
    req->sreq = sreq;
274 5db1764c Paolo Bonzini
    if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
275 5db1764c Paolo Bonzini
        int req_mode =
276 5db1764c Paolo Bonzini
            (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
277 5db1764c Paolo Bonzini
278 5db1764c Paolo Bonzini
        assert(req->sreq->cmd.mode == req_mode);
279 5db1764c Paolo Bonzini
    }
280 5db1764c Paolo Bonzini
    return req;
281 5db1764c Paolo Bonzini
}
282 5db1764c Paolo Bonzini
283 06114d72 Paolo Bonzini
static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
284 326799c0 Stefan Hajnoczi
{
285 06114d72 Paolo Bonzini
    SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
286 06114d72 Paolo Bonzini
    SCSIRequest *r, *next;
287 0866aca1 Anthony Liguori
    BusChild *kid;
288 06114d72 Paolo Bonzini
    int target;
289 06114d72 Paolo Bonzini
290 06114d72 Paolo Bonzini
    /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
291 06114d72 Paolo Bonzini
    req->resp.tmf->response = VIRTIO_SCSI_S_OK;
292 06114d72 Paolo Bonzini
293 06114d72 Paolo Bonzini
    switch (req->req.tmf->subtype) {
294 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
295 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
296 06114d72 Paolo Bonzini
        if (!d) {
297 06114d72 Paolo Bonzini
            goto fail;
298 06114d72 Paolo Bonzini
        }
299 06114d72 Paolo Bonzini
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
300 06114d72 Paolo Bonzini
            goto incorrect_lun;
301 06114d72 Paolo Bonzini
        }
302 06114d72 Paolo Bonzini
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
303 4dd7c82c Paolo Bonzini
            VirtIOSCSIReq *cmd_req = r->hba_private;
304 4dd7c82c Paolo Bonzini
            if (cmd_req && cmd_req->req.cmd->tag == req->req.tmf->tag) {
305 06114d72 Paolo Bonzini
                break;
306 06114d72 Paolo Bonzini
            }
307 06114d72 Paolo Bonzini
        }
308 4dd7c82c Paolo Bonzini
        if (r) {
309 4dd7c82c Paolo Bonzini
            /*
310 4dd7c82c Paolo Bonzini
             * Assert that the request has not been completed yet, we
311 4dd7c82c Paolo Bonzini
             * check for it in the loop above.
312 4dd7c82c Paolo Bonzini
             */
313 4dd7c82c Paolo Bonzini
            assert(r->hba_private);
314 06114d72 Paolo Bonzini
            if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
315 06114d72 Paolo Bonzini
                /* "If the specified command is present in the task set, then
316 06114d72 Paolo Bonzini
                 * return a service response set to FUNCTION SUCCEEDED".
317 06114d72 Paolo Bonzini
                 */
318 06114d72 Paolo Bonzini
                req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
319 06114d72 Paolo Bonzini
            } else {
320 06114d72 Paolo Bonzini
                scsi_req_cancel(r);
321 06114d72 Paolo Bonzini
            }
322 06114d72 Paolo Bonzini
        }
323 06114d72 Paolo Bonzini
        break;
324 06114d72 Paolo Bonzini
325 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
326 06114d72 Paolo Bonzini
        if (!d) {
327 06114d72 Paolo Bonzini
            goto fail;
328 06114d72 Paolo Bonzini
        }
329 06114d72 Paolo Bonzini
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
330 06114d72 Paolo Bonzini
            goto incorrect_lun;
331 06114d72 Paolo Bonzini
        }
332 06114d72 Paolo Bonzini
        s->resetting++;
333 06114d72 Paolo Bonzini
        qdev_reset_all(&d->qdev);
334 06114d72 Paolo Bonzini
        s->resetting--;
335 06114d72 Paolo Bonzini
        break;
336 06114d72 Paolo Bonzini
337 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
338 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
339 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
340 06114d72 Paolo Bonzini
        if (!d) {
341 06114d72 Paolo Bonzini
            goto fail;
342 06114d72 Paolo Bonzini
        }
343 06114d72 Paolo Bonzini
        if (d->lun != virtio_scsi_get_lun(req->req.tmf->lun)) {
344 06114d72 Paolo Bonzini
            goto incorrect_lun;
345 06114d72 Paolo Bonzini
        }
346 06114d72 Paolo Bonzini
        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
347 06114d72 Paolo Bonzini
            if (r->hba_private) {
348 06114d72 Paolo Bonzini
                if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
349 06114d72 Paolo Bonzini
                    /* "If there is any command present in the task set, then
350 06114d72 Paolo Bonzini
                     * return a service response set to FUNCTION SUCCEEDED".
351 06114d72 Paolo Bonzini
                     */
352 06114d72 Paolo Bonzini
                    req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
353 06114d72 Paolo Bonzini
                    break;
354 06114d72 Paolo Bonzini
                } else {
355 06114d72 Paolo Bonzini
                    scsi_req_cancel(r);
356 06114d72 Paolo Bonzini
                }
357 06114d72 Paolo Bonzini
            }
358 06114d72 Paolo Bonzini
        }
359 06114d72 Paolo Bonzini
        break;
360 06114d72 Paolo Bonzini
361 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
362 06114d72 Paolo Bonzini
        target = req->req.tmf->lun[1];
363 06114d72 Paolo Bonzini
        s->resetting++;
364 0866aca1 Anthony Liguori
        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
365 0866aca1 Anthony Liguori
             d = DO_UPCAST(SCSIDevice, qdev, kid->child);
366 06114d72 Paolo Bonzini
             if (d->channel == 0 && d->id == target) {
367 06114d72 Paolo Bonzini
                qdev_reset_all(&d->qdev);
368 06114d72 Paolo Bonzini
             }
369 06114d72 Paolo Bonzini
        }
370 06114d72 Paolo Bonzini
        s->resetting--;
371 06114d72 Paolo Bonzini
        break;
372 06114d72 Paolo Bonzini
373 06114d72 Paolo Bonzini
    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
374 06114d72 Paolo Bonzini
    default:
375 06114d72 Paolo Bonzini
        req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
376 06114d72 Paolo Bonzini
        break;
377 326799c0 Stefan Hajnoczi
    }
378 326799c0 Stefan Hajnoczi
379 06114d72 Paolo Bonzini
    return;
380 06114d72 Paolo Bonzini
381 06114d72 Paolo Bonzini
incorrect_lun:
382 06114d72 Paolo Bonzini
    req->resp.tmf->response = VIRTIO_SCSI_S_INCORRECT_LUN;
383 06114d72 Paolo Bonzini
    return;
384 06114d72 Paolo Bonzini
385 06114d72 Paolo Bonzini
fail:
386 06114d72 Paolo Bonzini
    req->resp.tmf->response = VIRTIO_SCSI_S_BAD_TARGET;
387 326799c0 Stefan Hajnoczi
}
388 326799c0 Stefan Hajnoczi
389 973abc7f Stefan Hajnoczi
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
390 973abc7f Stefan Hajnoczi
{
391 326799c0 Stefan Hajnoczi
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
392 326799c0 Stefan Hajnoczi
    VirtIOSCSIReq *req;
393 326799c0 Stefan Hajnoczi
394 326799c0 Stefan Hajnoczi
    while ((req = virtio_scsi_pop_req(s, vq))) {
395 06114d72 Paolo Bonzini
        int out_size, in_size;
396 06114d72 Paolo Bonzini
        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
397 06114d72 Paolo Bonzini
            virtio_scsi_bad_req();
398 06114d72 Paolo Bonzini
            continue;
399 06114d72 Paolo Bonzini
        }
400 06114d72 Paolo Bonzini
401 06114d72 Paolo Bonzini
        out_size = req->elem.out_sg[0].iov_len;
402 06114d72 Paolo Bonzini
        in_size = req->elem.in_sg[0].iov_len;
403 06114d72 Paolo Bonzini
        if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
404 06114d72 Paolo Bonzini
            if (out_size < sizeof(VirtIOSCSICtrlTMFReq) ||
405 06114d72 Paolo Bonzini
                in_size < sizeof(VirtIOSCSICtrlTMFResp)) {
406 06114d72 Paolo Bonzini
                virtio_scsi_bad_req();
407 06114d72 Paolo Bonzini
            }
408 06114d72 Paolo Bonzini
            virtio_scsi_do_tmf(s, req);
409 06114d72 Paolo Bonzini
410 06114d72 Paolo Bonzini
        } else if (req->req.tmf->type == VIRTIO_SCSI_T_AN_QUERY ||
411 06114d72 Paolo Bonzini
                   req->req.tmf->type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
412 06114d72 Paolo Bonzini
            if (out_size < sizeof(VirtIOSCSICtrlANReq) ||
413 06114d72 Paolo Bonzini
                in_size < sizeof(VirtIOSCSICtrlANResp)) {
414 06114d72 Paolo Bonzini
                virtio_scsi_bad_req();
415 06114d72 Paolo Bonzini
            }
416 06114d72 Paolo Bonzini
            req->resp.an->event_actual = 0;
417 06114d72 Paolo Bonzini
            req->resp.an->response = VIRTIO_SCSI_S_OK;
418 06114d72 Paolo Bonzini
        }
419 06114d72 Paolo Bonzini
        virtio_scsi_complete_req(req);
420 326799c0 Stefan Hajnoczi
    }
421 326799c0 Stefan Hajnoczi
}
422 326799c0 Stefan Hajnoczi
423 2ccdcd8d Paolo Bonzini
static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
424 2ccdcd8d Paolo Bonzini
                                         size_t resid)
425 2ccdcd8d Paolo Bonzini
{
426 2ccdcd8d Paolo Bonzini
    VirtIOSCSIReq *req = r->hba_private;
427 2ccdcd8d Paolo Bonzini
428 2ccdcd8d Paolo Bonzini
    req->resp.cmd->response = VIRTIO_SCSI_S_OK;
429 2ccdcd8d Paolo Bonzini
    req->resp.cmd->status = status;
430 2ccdcd8d Paolo Bonzini
    if (req->resp.cmd->status == GOOD) {
431 2ccdcd8d Paolo Bonzini
        req->resp.cmd->resid = resid;
432 2ccdcd8d Paolo Bonzini
    } else {
433 2ccdcd8d Paolo Bonzini
        req->resp.cmd->resid = 0;
434 2ccdcd8d Paolo Bonzini
        req->resp.cmd->sense_len =
435 2ccdcd8d Paolo Bonzini
            scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE);
436 2ccdcd8d Paolo Bonzini
    }
437 2ccdcd8d Paolo Bonzini
    virtio_scsi_complete_req(req);
438 2ccdcd8d Paolo Bonzini
}
439 2ccdcd8d Paolo Bonzini
440 2ccdcd8d Paolo Bonzini
static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
441 2ccdcd8d Paolo Bonzini
{
442 2ccdcd8d Paolo Bonzini
    VirtIOSCSIReq *req = r->hba_private;
443 2ccdcd8d Paolo Bonzini
444 2ccdcd8d Paolo Bonzini
    return &req->qsgl;
445 2ccdcd8d Paolo Bonzini
}
446 2ccdcd8d Paolo Bonzini
447 2ccdcd8d Paolo Bonzini
static void virtio_scsi_request_cancelled(SCSIRequest *r)
448 2ccdcd8d Paolo Bonzini
{
449 2ccdcd8d Paolo Bonzini
    VirtIOSCSIReq *req = r->hba_private;
450 2ccdcd8d Paolo Bonzini
451 2ccdcd8d Paolo Bonzini
    if (!req) {
452 2ccdcd8d Paolo Bonzini
        return;
453 2ccdcd8d Paolo Bonzini
    }
454 06114d72 Paolo Bonzini
    if (req->dev->resetting) {
455 06114d72 Paolo Bonzini
        req->resp.cmd->response = VIRTIO_SCSI_S_RESET;
456 06114d72 Paolo Bonzini
    } else {
457 06114d72 Paolo Bonzini
        req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
458 06114d72 Paolo Bonzini
    }
459 2ccdcd8d Paolo Bonzini
    virtio_scsi_complete_req(req);
460 2ccdcd8d Paolo Bonzini
}
461 2ccdcd8d Paolo Bonzini
462 2ccdcd8d Paolo Bonzini
static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
463 326799c0 Stefan Hajnoczi
{
464 326799c0 Stefan Hajnoczi
    req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
465 326799c0 Stefan Hajnoczi
    virtio_scsi_complete_req(req);
466 973abc7f Stefan Hajnoczi
}
467 973abc7f Stefan Hajnoczi
468 973abc7f Stefan Hajnoczi
static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
469 973abc7f Stefan Hajnoczi
{
470 326799c0 Stefan Hajnoczi
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
471 326799c0 Stefan Hajnoczi
    VirtIOSCSIReq *req;
472 2ccdcd8d Paolo Bonzini
    int n;
473 326799c0 Stefan Hajnoczi
474 326799c0 Stefan Hajnoczi
    while ((req = virtio_scsi_pop_req(s, vq))) {
475 2ccdcd8d Paolo Bonzini
        SCSIDevice *d;
476 326799c0 Stefan Hajnoczi
        int out_size, in_size;
477 326799c0 Stefan Hajnoczi
        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
478 326799c0 Stefan Hajnoczi
            virtio_scsi_bad_req();
479 326799c0 Stefan Hajnoczi
        }
480 326799c0 Stefan Hajnoczi
481 326799c0 Stefan Hajnoczi
        out_size = req->elem.out_sg[0].iov_len;
482 326799c0 Stefan Hajnoczi
        in_size = req->elem.in_sg[0].iov_len;
483 326799c0 Stefan Hajnoczi
        if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size ||
484 326799c0 Stefan Hajnoczi
            in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) {
485 326799c0 Stefan Hajnoczi
            virtio_scsi_bad_req();
486 326799c0 Stefan Hajnoczi
        }
487 326799c0 Stefan Hajnoczi
488 326799c0 Stefan Hajnoczi
        if (req->elem.out_num > 1 && req->elem.in_num > 1) {
489 2ccdcd8d Paolo Bonzini
            virtio_scsi_fail_cmd_req(req);
490 326799c0 Stefan Hajnoczi
            continue;
491 326799c0 Stefan Hajnoczi
        }
492 326799c0 Stefan Hajnoczi
493 2ccdcd8d Paolo Bonzini
        d = virtio_scsi_device_find(s, req->req.cmd->lun);
494 2ccdcd8d Paolo Bonzini
        if (!d) {
495 2ccdcd8d Paolo Bonzini
            req->resp.cmd->response = VIRTIO_SCSI_S_BAD_TARGET;
496 2ccdcd8d Paolo Bonzini
            virtio_scsi_complete_req(req);
497 2ccdcd8d Paolo Bonzini
            continue;
498 2ccdcd8d Paolo Bonzini
        }
499 2ccdcd8d Paolo Bonzini
        req->sreq = scsi_req_new(d, req->req.cmd->tag,
500 2ccdcd8d Paolo Bonzini
                                 virtio_scsi_get_lun(req->req.cmd->lun),
501 2ccdcd8d Paolo Bonzini
                                 req->req.cmd->cdb, req);
502 2ccdcd8d Paolo Bonzini
503 2ccdcd8d Paolo Bonzini
        if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
504 2ccdcd8d Paolo Bonzini
            int req_mode =
505 2ccdcd8d Paolo Bonzini
                (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
506 2ccdcd8d Paolo Bonzini
507 2ccdcd8d Paolo Bonzini
            if (req->sreq->cmd.mode != req_mode ||
508 2ccdcd8d Paolo Bonzini
                req->sreq->cmd.xfer > req->qsgl.size) {
509 2ccdcd8d Paolo Bonzini
                req->resp.cmd->response = VIRTIO_SCSI_S_OVERRUN;
510 2ccdcd8d Paolo Bonzini
                virtio_scsi_complete_req(req);
511 2ccdcd8d Paolo Bonzini
                continue;
512 2ccdcd8d Paolo Bonzini
            }
513 2ccdcd8d Paolo Bonzini
        }
514 2ccdcd8d Paolo Bonzini
515 2ccdcd8d Paolo Bonzini
        n = scsi_req_enqueue(req->sreq);
516 2ccdcd8d Paolo Bonzini
        if (n) {
517 2ccdcd8d Paolo Bonzini
            scsi_req_continue(req->sreq);
518 2ccdcd8d Paolo Bonzini
        }
519 326799c0 Stefan Hajnoczi
    }
520 973abc7f Stefan Hajnoczi
}
521 973abc7f Stefan Hajnoczi
522 973abc7f Stefan Hajnoczi
static void virtio_scsi_get_config(VirtIODevice *vdev,
523 973abc7f Stefan Hajnoczi
                                   uint8_t *config)
524 973abc7f Stefan Hajnoczi
{
525 973abc7f Stefan Hajnoczi
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
526 973abc7f Stefan Hajnoczi
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
527 973abc7f Stefan Hajnoczi
528 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
529 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->seg_max, 128 - 2);
530 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
531 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
532 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
533 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->sense_size, s->sense_size);
534 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->cdb_size, s->cdb_size);
535 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
536 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
537 973abc7f Stefan Hajnoczi
    stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
538 973abc7f Stefan Hajnoczi
}
539 973abc7f Stefan Hajnoczi
540 973abc7f Stefan Hajnoczi
static void virtio_scsi_set_config(VirtIODevice *vdev,
541 973abc7f Stefan Hajnoczi
                                   const uint8_t *config)
542 973abc7f Stefan Hajnoczi
{
543 973abc7f Stefan Hajnoczi
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
544 973abc7f Stefan Hajnoczi
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
545 973abc7f Stefan Hajnoczi
546 973abc7f Stefan Hajnoczi
    if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
547 973abc7f Stefan Hajnoczi
        (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
548 973abc7f Stefan Hajnoczi
        error_report("bad data written to virtio-scsi configuration space");
549 973abc7f Stefan Hajnoczi
        exit(1);
550 973abc7f Stefan Hajnoczi
    }
551 973abc7f Stefan Hajnoczi
552 973abc7f Stefan Hajnoczi
    s->sense_size = ldl_raw(&scsiconf->sense_size);
553 973abc7f Stefan Hajnoczi
    s->cdb_size = ldl_raw(&scsiconf->cdb_size);
554 973abc7f Stefan Hajnoczi
}
555 973abc7f Stefan Hajnoczi
556 973abc7f Stefan Hajnoczi
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
557 973abc7f Stefan Hajnoczi
                                         uint32_t requested_features)
558 973abc7f Stefan Hajnoczi
{
559 973abc7f Stefan Hajnoczi
    return requested_features;
560 973abc7f Stefan Hajnoczi
}
561 973abc7f Stefan Hajnoczi
562 973abc7f Stefan Hajnoczi
static void virtio_scsi_reset(VirtIODevice *vdev)
563 973abc7f Stefan Hajnoczi
{
564 973abc7f Stefan Hajnoczi
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
565 973abc7f Stefan Hajnoczi
566 973abc7f Stefan Hajnoczi
    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
567 973abc7f Stefan Hajnoczi
    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
568 2baa1beb Paolo Bonzini
    s->events_dropped = false;
569 973abc7f Stefan Hajnoczi
}
570 973abc7f Stefan Hajnoczi
571 5db1764c Paolo Bonzini
/* The device does not have anything to save beyond the virtio data.
572 5db1764c Paolo Bonzini
 * Request data is saved with callbacks from SCSI devices.
573 5db1764c Paolo Bonzini
 */
574 5db1764c Paolo Bonzini
static void virtio_scsi_save(QEMUFile *f, void *opaque)
575 5db1764c Paolo Bonzini
{
576 5db1764c Paolo Bonzini
    VirtIOSCSI *s = opaque;
577 5db1764c Paolo Bonzini
    virtio_save(&s->vdev, f);
578 5db1764c Paolo Bonzini
}
579 5db1764c Paolo Bonzini
580 5db1764c Paolo Bonzini
static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
581 5db1764c Paolo Bonzini
{
582 5db1764c Paolo Bonzini
    VirtIOSCSI *s = opaque;
583 2a633c46 Orit Wassermann
    int ret;
584 2a633c46 Orit Wassermann
585 2a633c46 Orit Wassermann
    ret = virtio_load(&s->vdev, f);
586 2a633c46 Orit Wassermann
    if (ret) {
587 2a633c46 Orit Wassermann
        return ret;
588 2a633c46 Orit Wassermann
    }
589 5db1764c Paolo Bonzini
    return 0;
590 5db1764c Paolo Bonzini
}
591 5db1764c Paolo Bonzini
592 b6866fee Cong Meng
static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
593 b6866fee Cong Meng
                                   uint32_t event, uint32_t reason)
594 b6866fee Cong Meng
{
595 b6866fee Cong Meng
    VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq);
596 b6866fee Cong Meng
    VirtIOSCSIEvent *evt;
597 64f64855 Paolo Bonzini
    int in_size;
598 b6866fee Cong Meng
599 64f64855 Paolo Bonzini
    if (!req) {
600 64f64855 Paolo Bonzini
        s->events_dropped = true;
601 64f64855 Paolo Bonzini
        return;
602 64f64855 Paolo Bonzini
    }
603 b6866fee Cong Meng
604 64f64855 Paolo Bonzini
    if (req->elem.out_num || req->elem.in_num != 1) {
605 64f64855 Paolo Bonzini
        virtio_scsi_bad_req();
606 64f64855 Paolo Bonzini
    }
607 b6866fee Cong Meng
608 64f64855 Paolo Bonzini
    if (s->events_dropped) {
609 64f64855 Paolo Bonzini
        event |= VIRTIO_SCSI_T_EVENTS_MISSED;
610 64f64855 Paolo Bonzini
        s->events_dropped = false;
611 64f64855 Paolo Bonzini
    }
612 64f64855 Paolo Bonzini
613 64f64855 Paolo Bonzini
    in_size = req->elem.in_sg[0].iov_len;
614 64f64855 Paolo Bonzini
    if (in_size < sizeof(VirtIOSCSIEvent)) {
615 64f64855 Paolo Bonzini
        virtio_scsi_bad_req();
616 64f64855 Paolo Bonzini
    }
617 64f64855 Paolo Bonzini
618 64f64855 Paolo Bonzini
    evt = req->resp.event;
619 64f64855 Paolo Bonzini
    memset(evt, 0, sizeof(VirtIOSCSIEvent));
620 64f64855 Paolo Bonzini
    evt->event = event;
621 64f64855 Paolo Bonzini
    evt->reason = reason;
622 64f64855 Paolo Bonzini
    if (!dev) {
623 64f64855 Paolo Bonzini
        assert(event == VIRTIO_SCSI_T_NO_EVENT);
624 64f64855 Paolo Bonzini
    } else {
625 b6866fee Cong Meng
        evt->lun[0] = 1;
626 b6866fee Cong Meng
        evt->lun[1] = dev->id;
627 b6866fee Cong Meng
628 b6866fee Cong Meng
        /* Linux wants us to keep the same encoding we use for REPORT LUNS.  */
629 b6866fee Cong Meng
        if (dev->lun >= 256) {
630 b6866fee Cong Meng
            evt->lun[2] = (dev->lun >> 8) | 0x40;
631 b6866fee Cong Meng
        }
632 b6866fee Cong Meng
        evt->lun[3] = dev->lun & 0xFF;
633 64f64855 Paolo Bonzini
    }
634 64f64855 Paolo Bonzini
    virtio_scsi_complete_req(req);
635 64f64855 Paolo Bonzini
}
636 64f64855 Paolo Bonzini
637 64f64855 Paolo Bonzini
static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
638 64f64855 Paolo Bonzini
{
639 64f64855 Paolo Bonzini
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
640 64f64855 Paolo Bonzini
641 64f64855 Paolo Bonzini
    if (s->events_dropped) {
642 64f64855 Paolo Bonzini
        virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
643 b6866fee Cong Meng
    }
644 b6866fee Cong Meng
}
645 b6866fee Cong Meng
646 feda01e4 Paolo Bonzini
static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
647 feda01e4 Paolo Bonzini
{
648 feda01e4 Paolo Bonzini
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
649 feda01e4 Paolo Bonzini
650 feda01e4 Paolo Bonzini
    if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
651 feda01e4 Paolo Bonzini
        (s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) &&
652 feda01e4 Paolo Bonzini
        dev->type != TYPE_ROM) {
653 feda01e4 Paolo Bonzini
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
654 feda01e4 Paolo Bonzini
                               sense.asc | (sense.ascq << 8));
655 feda01e4 Paolo Bonzini
    }
656 feda01e4 Paolo Bonzini
}
657 feda01e4 Paolo Bonzini
658 b6866fee Cong Meng
static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
659 b6866fee Cong Meng
{
660 b6866fee Cong Meng
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
661 b6866fee Cong Meng
662 b6866fee Cong Meng
    if (((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) &&
663 b6866fee Cong Meng
        (s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
664 b6866fee Cong Meng
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
665 b6866fee Cong Meng
                               VIRTIO_SCSI_EVT_RESET_RESCAN);
666 b6866fee Cong Meng
    }
667 b6866fee Cong Meng
}
668 b6866fee Cong Meng
669 b6866fee Cong Meng
static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev)
670 b6866fee Cong Meng
{
671 b6866fee Cong Meng
    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
672 b6866fee Cong Meng
673 b6866fee Cong Meng
    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
674 b6866fee Cong Meng
        virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
675 b6866fee Cong Meng
                               VIRTIO_SCSI_EVT_RESET_REMOVED);
676 b6866fee Cong Meng
    }
677 b6866fee Cong Meng
}
678 b6866fee Cong Meng
679 2ccdcd8d Paolo Bonzini
static struct SCSIBusInfo virtio_scsi_scsi_info = {
680 2ccdcd8d Paolo Bonzini
    .tcq = true,
681 2ccdcd8d Paolo Bonzini
    .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
682 2ccdcd8d Paolo Bonzini
    .max_target = VIRTIO_SCSI_MAX_TARGET,
683 2ccdcd8d Paolo Bonzini
    .max_lun = VIRTIO_SCSI_MAX_LUN,
684 2ccdcd8d Paolo Bonzini
685 2ccdcd8d Paolo Bonzini
    .complete = virtio_scsi_command_complete,
686 2ccdcd8d Paolo Bonzini
    .cancel = virtio_scsi_request_cancelled,
687 feda01e4 Paolo Bonzini
    .change = virtio_scsi_change,
688 b6866fee Cong Meng
    .hotplug = virtio_scsi_hotplug,
689 b6866fee Cong Meng
    .hot_unplug = virtio_scsi_hot_unplug,
690 2ccdcd8d Paolo Bonzini
    .get_sg_list = virtio_scsi_get_sg_list,
691 5db1764c Paolo Bonzini
    .save_request = virtio_scsi_save_request,
692 5db1764c Paolo Bonzini
    .load_request = virtio_scsi_load_request,
693 2ccdcd8d Paolo Bonzini
};
694 2ccdcd8d Paolo Bonzini
695 973abc7f Stefan Hajnoczi
VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
696 973abc7f Stefan Hajnoczi
{
697 973abc7f Stefan Hajnoczi
    VirtIOSCSI *s;
698 5db1764c Paolo Bonzini
    static int virtio_scsi_id;
699 d2ad7dd4 Paolo Bonzini
    size_t sz;
700 d2ad7dd4 Paolo Bonzini
    int i;
701 973abc7f Stefan Hajnoczi
702 d2ad7dd4 Paolo Bonzini
    sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *);
703 973abc7f Stefan Hajnoczi
    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
704 d2ad7dd4 Paolo Bonzini
                                         sizeof(VirtIOSCSIConfig), sz);
705 973abc7f Stefan Hajnoczi
706 973abc7f Stefan Hajnoczi
    s->qdev = dev;
707 973abc7f Stefan Hajnoczi
    s->conf = proxyconf;
708 973abc7f Stefan Hajnoczi
709 973abc7f Stefan Hajnoczi
    /* TODO set up vdev function pointers */
710 973abc7f Stefan Hajnoczi
    s->vdev.get_config = virtio_scsi_get_config;
711 973abc7f Stefan Hajnoczi
    s->vdev.set_config = virtio_scsi_set_config;
712 973abc7f Stefan Hajnoczi
    s->vdev.get_features = virtio_scsi_get_features;
713 973abc7f Stefan Hajnoczi
    s->vdev.reset = virtio_scsi_reset;
714 973abc7f Stefan Hajnoczi
715 973abc7f Stefan Hajnoczi
    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
716 973abc7f Stefan Hajnoczi
                                   virtio_scsi_handle_ctrl);
717 973abc7f Stefan Hajnoczi
    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
718 619d7ae9 Paolo Bonzini
                                   virtio_scsi_handle_event);
719 d2ad7dd4 Paolo Bonzini
    for (i = 0; i < s->conf->num_queues; i++) {
720 d2ad7dd4 Paolo Bonzini
        s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
721 d2ad7dd4 Paolo Bonzini
                                         virtio_scsi_handle_cmd);
722 d2ad7dd4 Paolo Bonzini
    }
723 973abc7f Stefan Hajnoczi
724 2ccdcd8d Paolo Bonzini
    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
725 2ccdcd8d Paolo Bonzini
    if (!dev->hotplugged) {
726 2ccdcd8d Paolo Bonzini
        scsi_bus_legacy_handle_cmdline(&s->bus);
727 2ccdcd8d Paolo Bonzini
    }
728 2ccdcd8d Paolo Bonzini
729 5db1764c Paolo Bonzini
    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
730 5db1764c Paolo Bonzini
                    virtio_scsi_save, virtio_scsi_load, s);
731 973abc7f Stefan Hajnoczi
732 973abc7f Stefan Hajnoczi
    return &s->vdev;
733 973abc7f Stefan Hajnoczi
}
734 973abc7f Stefan Hajnoczi
735 973abc7f Stefan Hajnoczi
void virtio_scsi_exit(VirtIODevice *vdev)
736 973abc7f Stefan Hajnoczi
{
737 eb2fa764 Paolo Bonzini
    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
738 eb2fa764 Paolo Bonzini
    unregister_savevm(s->qdev, "virtio-scsi", s);
739 973abc7f Stefan Hajnoczi
    virtio_cleanup(vdev);
740 973abc7f Stefan Hajnoczi
}