Statistics
| Branch: | Revision:

root / hw / virtio-scsi.c @ aebcf56f

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