]> git.proxmox.com Git - qemu.git/blob - hw/virtio-scsi.c
virtio-scsi: Add virtio-scsi stub device
[qemu.git] / hw / virtio-scsi.c
1 /*
2 * Virtio SCSI HBA
3 *
4 * Copyright IBM, Corp. 2010
5 * Copyright Red Hat, Inc. 2011
6 *
7 * Authors:
8 * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
9 * Paolo Bonzini <pbonzini@redhat.com>
10 *
11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
12 * See the COPYING file in the top-level directory.
13 *
14 */
15
16 #include "virtio-scsi.h"
17 #include <hw/scsi.h>
18 #include <hw/scsi-defs.h>
19
20 #define VIRTIO_SCSI_VQ_SIZE 128
21 #define VIRTIO_SCSI_CDB_SIZE 32
22 #define VIRTIO_SCSI_SENSE_SIZE 96
23 #define VIRTIO_SCSI_MAX_CHANNEL 0
24 #define VIRTIO_SCSI_MAX_TARGET 255
25 #define VIRTIO_SCSI_MAX_LUN 16383
26
27 /* Response codes */
28 #define VIRTIO_SCSI_S_OK 0
29 #define VIRTIO_SCSI_S_OVERRUN 1
30 #define VIRTIO_SCSI_S_ABORTED 2
31 #define VIRTIO_SCSI_S_BAD_TARGET 3
32 #define VIRTIO_SCSI_S_RESET 4
33 #define VIRTIO_SCSI_S_BUSY 5
34 #define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
35 #define VIRTIO_SCSI_S_TARGET_FAILURE 7
36 #define VIRTIO_SCSI_S_NEXUS_FAILURE 8
37 #define VIRTIO_SCSI_S_FAILURE 9
38 #define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10
39 #define VIRTIO_SCSI_S_FUNCTION_REJECTED 11
40 #define VIRTIO_SCSI_S_INCORRECT_LUN 12
41
42 /* Controlq type codes. */
43 #define VIRTIO_SCSI_T_TMF 0
44 #define VIRTIO_SCSI_T_AN_QUERY 1
45 #define VIRTIO_SCSI_T_AN_SUBSCRIBE 2
46
47 /* Valid TMF subtypes. */
48 #define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
49 #define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
50 #define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
51 #define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3
52 #define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
53 #define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
54 #define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
55 #define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
56
57 /* Events. */
58 #define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
59 #define VIRTIO_SCSI_T_NO_EVENT 0
60 #define VIRTIO_SCSI_T_TRANSPORT_RESET 1
61 #define VIRTIO_SCSI_T_ASYNC_NOTIFY 2
62
63 /* SCSI command request, followed by data-out */
64 typedef struct {
65 uint8_t lun[8]; /* Logical Unit Number */
66 uint64_t tag; /* Command identifier */
67 uint8_t task_attr; /* Task attribute */
68 uint8_t prio;
69 uint8_t crn;
70 uint8_t cdb[];
71 } QEMU_PACKED VirtIOSCSICmdReq;
72
73 /* Response, followed by sense data and data-in */
74 typedef struct {
75 uint32_t sense_len; /* Sense data length */
76 uint32_t resid; /* Residual bytes in data buffer */
77 uint16_t status_qualifier; /* Status qualifier */
78 uint8_t status; /* Command completion status */
79 uint8_t response; /* Response values */
80 uint8_t sense[];
81 } QEMU_PACKED VirtIOSCSICmdResp;
82
83 /* Task Management Request */
84 typedef struct {
85 uint32_t type;
86 uint32_t subtype;
87 uint8_t lun[8];
88 uint64_t tag;
89 } QEMU_PACKED VirtIOSCSICtrlTMFReq;
90
91 typedef struct {
92 uint8_t response;
93 } QEMU_PACKED VirtIOSCSICtrlTMFResp;
94
95 /* Asynchronous notification query/subscription */
96 typedef struct {
97 uint32_t type;
98 uint8_t lun[8];
99 uint32_t event_requested;
100 } QEMU_PACKED VirtIOSCSICtrlANReq;
101
102 typedef struct {
103 uint32_t event_actual;
104 uint8_t response;
105 } QEMU_PACKED VirtIOSCSICtrlANResp;
106
107 typedef struct {
108 uint32_t event;
109 uint8_t lun[8];
110 uint32_t reason;
111 } QEMU_PACKED VirtIOSCSIEvent;
112
113 typedef struct {
114 uint32_t num_queues;
115 uint32_t seg_max;
116 uint32_t max_sectors;
117 uint32_t cmd_per_lun;
118 uint32_t event_info_size;
119 uint32_t sense_size;
120 uint32_t cdb_size;
121 uint16_t max_channel;
122 uint16_t max_target;
123 uint32_t max_lun;
124 } QEMU_PACKED VirtIOSCSIConfig;
125
126 typedef struct {
127 VirtIODevice vdev;
128 DeviceState *qdev;
129 VirtIOSCSIConf *conf;
130
131 VirtQueue *ctrl_vq;
132 VirtQueue *event_vq;
133 VirtQueue *cmd_vq;
134 uint32_t sense_size;
135 uint32_t cdb_size;
136 } VirtIOSCSI;
137
138 static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
139 {
140 /* TODO */
141 }
142
143 static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
144 {
145 /* TODO */
146 }
147
148 static void virtio_scsi_get_config(VirtIODevice *vdev,
149 uint8_t *config)
150 {
151 VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
152 VirtIOSCSI *s = (VirtIOSCSI *)vdev;
153
154 stl_raw(&scsiconf->num_queues, s->conf->num_queues);
155 stl_raw(&scsiconf->seg_max, 128 - 2);
156 stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
157 stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
158 stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
159 stl_raw(&scsiconf->sense_size, s->sense_size);
160 stl_raw(&scsiconf->cdb_size, s->cdb_size);
161 stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
162 stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
163 stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
164 }
165
166 static void virtio_scsi_set_config(VirtIODevice *vdev,
167 const uint8_t *config)
168 {
169 VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
170 VirtIOSCSI *s = (VirtIOSCSI *)vdev;
171
172 if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
173 (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
174 error_report("bad data written to virtio-scsi configuration space");
175 exit(1);
176 }
177
178 s->sense_size = ldl_raw(&scsiconf->sense_size);
179 s->cdb_size = ldl_raw(&scsiconf->cdb_size);
180 }
181
182 static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
183 uint32_t requested_features)
184 {
185 return requested_features;
186 }
187
188 static void virtio_scsi_reset(VirtIODevice *vdev)
189 {
190 VirtIOSCSI *s = (VirtIOSCSI *)vdev;
191
192 s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
193 s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
194 }
195
196 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
197 {
198 VirtIOSCSI *s;
199
200 s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
201 sizeof(VirtIOSCSIConfig),
202 sizeof(VirtIOSCSI));
203
204 s->qdev = dev;
205 s->conf = proxyconf;
206
207 /* TODO set up vdev function pointers */
208 s->vdev.get_config = virtio_scsi_get_config;
209 s->vdev.set_config = virtio_scsi_set_config;
210 s->vdev.get_features = virtio_scsi_get_features;
211 s->vdev.reset = virtio_scsi_reset;
212
213 s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
214 virtio_scsi_handle_ctrl);
215 s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
216 NULL);
217 s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
218 virtio_scsi_handle_cmd);
219
220 /* TODO savevm */
221
222 return &s->vdev;
223 }
224
225 void virtio_scsi_exit(VirtIODevice *vdev)
226 {
227 virtio_cleanup(vdev);
228 }