1/*
2 * Copyright (c) 2014 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#ifndef VIRTIO_VIRTIO_DEVICE_H
11#define VIRTIO_VIRTIO_DEVICE_H
12
13struct virtio_device;
14
15/*
16 * 2.1 Device Status Field
17 */
18
19/// The device is in the reset state (not discovered by the guest)
20#define VIRTIO_DEVICE_STATUS_RESET       0x00
21
22/// Guest OS has found the device and recognized it as a valid virtio device.
23#define VIRTIO_DEVICE_STATUS_ACKNOWLEDGE 0x01
24
25/// Guest OS knows how to drive the device i.e. recognized as valid virtio device.
26#define VIRTIO_DEVICE_STATUS_DRIVER      0x02
27
28/// Driver is set up and ready to drive the device.
29#define VIRTIO_DEVICE_STATUS_DRIVER_OK   0x04
30
31/// Driver has acknowledged all the features it understands
32#define VIRTIO_DEVICE_STATUS_FEATURES_OK 0x08
33
34/// Something went wrong in the guest, and it has given up on the device.
35#define VIRTIO_DEVICE_STATUS_FAILED      0x80
36
37/*
38 * 5.0 Device Types
39 * The following device IDs are used to identify different types of virtio
40 * devices. Some device IDs are reserved for devices which are not currently
41 * defined in this standard.
42 */
43
44/// Invalid device identifier
45#define VIRTIO_DEVICE_TYPE_INVALID   0x00
46
47/// Device type for network interface cards
48#define VIRTIO_DEVICE_TYPE_NET       0x01
49
50/// Device type for block devices
51#define VIRTIO_DEVICE_TYPE_BLOCK     0x02
52
53/// Device type for console devices
54#define VIRTIO_DEVICE_TYPE_CONSOLE   0x03
55
56/// Device type for entorpy devices
57#define VIRTIO_DEVICE_TYPE_ENTORPY   0x04
58
59//#define VIRTIO_DEVICE_TYPE_LEGACY_BALLOON 5
60
61/// Device type for IO memory devices
62#define VIRTIO_DEVICE_TYPE_IOMEM     0x06
63
64/// Device type for rpmgs devices
65#define VIRTIO_DEVICE_TYPE_RPMSG     0x07
66
67/// Device type for SCSI host devices
68#define VIRTIO_DEVICE_TYPE_SCSIHOST  0x08
69
70/// Device type for 9P transport devices
71#define VIRTIO_DEVICE_TYPE_9PTRANSP  0x09
72
73/// Device type for MAC 802.11 WLAn devices
74#define VIRTIO_DEVICE_TYPE_WLAN      0x0A
75
76/// Device type for RPROC serial devices
77#define VIRTIO_DEVICE_TYPE_SERIAL    0x0B
78
79/// Device type for virtio CAIF devices
80#define VIRTIO_DEVICE_TYPE_CAIF      0x0C
81
82/// Device type for memory ballooning devices
83#define VIRTIO_DEVICE_TYPE_BALLOON   0x0D
84
85/// Device type for GPU devices
86#define VIRTIO_DEVICE_TYPE_GPU       0x0E
87
88/// Device type for timer / clock devices
89#define VIRTIO_DEVICE_TYPE_TIMER     0x0F
90
91/**
92 * specifies the possible virtio backends to be used
93 */
94enum virtio_backend {
95    VIRTIO_DEVICE_BACKEND_INVALID,
96    VIRTIO_DEVICE_BACKEND_PCI,
97    VIRTIO_DEVICE_BACKEND_MMIO,
98    VIRTIO_DEVICE_BACKEND_IO,
99};
100
101/**
102 * driver specific device status
103 */
104enum virtio_state {
105    VIRTIO_DEVICE_S_INVALID,
106    VIRTIO_DEVICE_S_INITIALIZING,
107    VIRTIO_DEVICE_S_READY,
108    VIRTIO_DEVICE_S_TERMINATING,
109    VIRTIO_DEVICE_S_ERROR,
110};
111
112/*
113 * 4.1.2 PCI Device Discovery
114 *
115 * Any PCI device with Vendor ID 0x1AF4, and Device ID 0x1000 through 0x103F
116 * inclusive is a virtio device. The Subsystem Device ID indicates which virtio
117 * device is supported by the device.
118 */
119#define VIRTIO_PCI_VENDOR_ID 0x1AF4
120#define VIRTIO_PCI_DEVICE_ID 0x1000
121#define VIRTIO_PCI_DEVICE_ID2 0x103F
122
123#define VIRTIO_DEVICE_NAME_MAX 32
124
125#define VIRTIO_DEVICE_HC_IFACE_MAX 32
126
127
128/*
129 * Function pointers type definitions
130 */
131
132/// interrupt handler when the device configuration space changes
133typedef void (*config_intr_handler_t)(struct virtio_device *dev);
134
135/// device specific initialization function
136typedef errval_t (*virtio_device_setup_t)(struct virtio_device *dev,
137                                         void *state);
138
139struct virtio_backend_arg {
140    enum virtio_backend  type;
141    union {
142        struct {
143            struct capref dev_cap;      ///<
144            void   *dev_base;
145            size_t  dev_size;
146        } mmio;
147        struct {
148            struct capref dev_cap;
149            /* TODO: fill in needed fieds */
150        } pci;
151        struct {
152            struct capref dev_cap;
153            /* TODO: fill in needed fieds */
154        } io;
155    } args;
156};
157
158
159/**
160 * contains necessary values for the device initialization process
161 */
162struct virtio_device_setup
163{
164    uint8_t dev_type;           ///< expected VirtIO type of the device
165    char    dev_name[VIRTIO_DEVICE_NAME_MAX];
166    struct capref dev_cap;
167    void   *dev_t_st;           ///< pointer to device type specific state
168    uint64_t features;          ///< VirtIO feature bits supported
169
170    struct virtio_backend_arg  backend;    ///< arguments for the backend
171
172    virtio_device_setup_t setup_fn;
173    void                 *setup_arg;
174
175    config_intr_handler_t config_intr_fn;
176
177    uint16_t vq_num;
178    struct virtqueue_setup *vq_setup;
179#ifdef __VIRTIO_HOST__
180    enum virtio_host       hc_type;
181    char                  *hc_iface;
182    struct virtio_host_cb *hc_cb;
183    lpaddr_t               hc_offset;
184#endif
185};
186
187
188
189
190/**
191 * \brief initializes a new VirtIO device based on the values passed with the
192 *        device init struct. The device registers have already to be mapped. *
193 *
194 * \param dev       device structure to initialize
195 * \param init      additional information passed for the init process
196 * \param dev_regs  memory location of the device registers
197 */
198errval_t virtio_device_open(struct virtio_device **dev,
199                            struct virtio_device_setup *init);
200
201/**
202 * \brief initializes a new VirtIO device based on the values passed with the
203 *        device init struct. The supplied cap contains the memory range of the
204 *        device registers.
205 *
206 * \param dev       device structure to initialize
207 * \param init      additional information passed for the init process
208 * \param dev_cap   capability representing the device registers
209 */
210errval_t virtio_device_open_with_cap(struct virtio_device **dev,
211                                     struct virtio_device_setup *init,
212                                     struct capref dev_cap);
213
214/**
215 * \brief   closes a virtio device.
216 *
217 * \param dev the device to be closed
218 *
219 * \returns SYS_ERR_OK on success
220 */
221errval_t virtio_device_close(struct virtio_device *dev);
222
223/**
224 * \brief resets the virtio device
225 *
226 * \param dev   the device to reset
227 *
228 * \returns SYS_ERR_OK on success
229 */
230errval_t virtio_device_reset(struct virtio_device *dev);
231
232/**
233 * \brief returns the status of a virtio device
234 *
235 * \param the device to query for status
236 * \param returned status
237 *
238 * \returns SYS_ERR_OK on success
239 */
240errval_t virtio_device_get_status(struct virtio_device *dev,
241                                  uint32_t *ret_status);
242
243/**
244 * \brief sets the status bit of the device
245 *
246 * \param dev    the VirtIO device
247 * \param status the status bit to set
248 *
249 * \return SYS_ERR_OK on success
250 */
251errval_t virtio_device_set_status(struct virtio_device *dev,
252                                  uint8_t status);
253
254/**
255 * \brief tells the device which features the driver understands
256 *
257 * \param dev       the VirtIO device
258 * \param features  bitmap of understood features
259 *
260 * \return SYS_ERR_OK on success
261 */
262errval_t virtio_device_set_driver_features(struct virtio_device *dev,
263                                           uint64_t features);
264
265/**
266 * \brief queries the device which features it understands
267 *
268 * \param dev       the VirtIO device
269 * \param features  bitmap of understood features by the device
270 *
271 * \return SYS_ERR_OK on success
272 */
273errval_t virtio_device_get_device_features(struct virtio_device *dev,
274                                           uint64_t *ret_features);
275
276/**
277 * \brief wrapper for calling the device specific initialization function
278 *
279 * \param dev   the VirtIO device
280 * \param arg   argument pointer to the initialization function
281 *
282 * \returns SYS_ERR_OK on success
283 *          VIRTIO_ERR_* on failure
284 */
285errval_t virtio_device_specific_setup(struct virtio_device *dev,
286                                      void *arg);
287
288/**
289 * \brief checks if a certain feature is negotiated and understood by both
290 *        device and driver.
291 *
292 * \param dev       the VirtIO device
293 * \param feature   feature bit to check
294 *
295 * \returns true  - if feature bit was set
296 *          false - if the featurebit was not set
297 */
298bool virtio_device_has_feature(struct virtio_device *dev,
299                               uint8_t feature);
300
301/**
302 * \brief negotiates the supported features based on the offered device features
303 *        and the supplied driver features
304 *
305 * \param dev            the VirtIO device
306 * \param driver_featurs bitmask of understood features by the device
307 *
308 * \returns SYS_ERR_OK on success
309 */
310errval_t virtio_device_feature_negotiate(struct virtio_device *dev,
311                                         uint64_t driver_features);
312
313/**
314 * \brief reads the device configuration space and copies it into a local buffer
315 *
316 * \param vdev  virtio device
317 * \param buf   pointer to the buffer to store the data
318 * \param len   the length of the buffer
319 *
320 * \returns SYS_ERR_OK on success
321 */
322errval_t virtio_device_config_read(struct virtio_device *vdev,
323                                  void *buf,
324                                  size_t len);
325/**
326 * \brief writes to the configuration space of a device
327 *
328 * \param vdev  virtio device
329 * \param buf   pointer to the buffer with data to update
330 * \param len   the length of the buffer
331 *
332 * \returns SYS_ERR_OK on success
333 */
334errval_t virtio_device_config_write(struct virtio_device *dev,
335                                    void *config,
336                                    size_t offset,
337                                    size_t length);
338
339/**
340 * \brief Returns the pointer to the device specific structure
341 *
342 * \param vdev to get the device specific pointer
343 *
344 * \returns device specific struct pointer
345 */
346void *virtio_device_get_type_state(struct virtio_device *vdev);
347
348/**
349 * \brief allocates the virtqueues for this device based on the setup information
350 *
351 * \param vdev      virtio device to allocate the queues for
352 * \param vq_setup  setup information for the virtqueues
353 * \param vq_num    number of virtqueues to allocate
354 *
355 * \returns SYS_ERR_OK on success
356 */
357errval_t virtio_device_virtqueue_alloc(struct virtio_device *vdev,
358                                       struct virtqueue_setup *vq_setup,
359                                       uint16_t vq_num);
360
361/**
362 * \brief notifies the host about new descriptors available in the
363 *        available ring
364 *
365 * \param vdev      VirtIO device
366 * \param virtq_id  the virtq to signal on
367 *
368 * \return SYS_ERR_OK on success
369 */
370errval_t virtio_device_notify_host(struct virtio_device *vdev,
371                                   uint16_t virtq_id);
372
373#ifdef __VIRTIO_HOST__
374/**
375 * \brief returns a pointer to a virtqueue of the device
376 *
377 * \param vdev   VirtIO device
378 * \param vq_idx the queue index of the queue we want
379 *
380 * \returns pointer to the requested virtqueue
381 *          NULL if no such virtqueue exists
382 */
383struct virtqueue_host *virtio_device_get_host_virtq(struct virtio_device *vdev,
384                                                    uint16_t vq_idx);
385#else
386/**
387 * \brief returns a pointer to a virtqueue of the device
388 *
389 * \param vdev   VirtIO device
390 * \param vq_idx the queue index of the queue we want
391 *
392 * \returns pointer to the requested virtqueue
393 *          NULL if no such virtqueue exists
394 */
395struct virtqueue *virtio_device_get_virtq(struct virtio_device *vdev,
396                                          uint16_t vq_idx);
397
398
399/**
400 * \brief exposes the virtqueue to the device such that it can be used
401 *
402 * \param dev the VirtIO device
403 * \param vq  the virtqueue to be added to the device
404 *
405 * \return SYS_ERR_OK on success
406 */
407errval_t virtio_device_set_virtq(struct virtio_device *dev,
408                                 struct virtqueue *vq);
409#endif
410/**
411 * \brief sets the interrupt handler for the configuration space interrupts
412 *
413 * \param dev the VirtIO device
414 * \param fn  handler function
415 *
416 * \return SYS_ERR_OK on success
417 */
418errval_t virtio_device_set_config_intr_handler(struct virtio_device *dev,
419                                               config_intr_handler_t fn);
420
421#endif // VIRTIO_VIRTIO_DEVICE_H
422