1 /******************************************************************************
2 * Copyright (c) 2011 IBM Corporation
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
15 #include <byteorder.h>
18 /* PCI virtio header offsets */
19 #define VIRTIOHDR_DEVICE_FEATURES 0
20 #define VIRTIOHDR_GUEST_FEATURES 4
21 #define VIRTIOHDR_QUEUE_ADDRESS 8
22 #define VIRTIOHDR_QUEUE_SIZE 12
23 #define VIRTIOHDR_QUEUE_SELECT 14
24 #define VIRTIOHDR_QUEUE_NOTIFY 16
25 #define VIRTIOHDR_DEVICE_STATUS 18
26 #define VIRTIOHDR_ISR_STATUS 19
27 #define VIRTIOHDR_DEVICE_CONFIG 20
31 * Calculate ring size according to queue size number
33 unsigned long virtio_vring_size(unsigned int qsize)
35 return VQ_ALIGN(sizeof(struct vring_desc) * qsize +
36 sizeof(struct vring_avail) + sizeof(uint16_t) * qsize) +
37 VQ_ALIGN(sizeof(struct vring_used) +
38 sizeof(struct vring_used_elem) * qsize);
43 * Get number of elements in a vring
44 * @param dev pointer to virtio device information
45 * @param queue virtio queue number
46 * @return number of elements
48 int virtio_get_qsize(struct virtio_device *dev, int queue)
52 if (dev->type == VIRTIO_TYPE_PCI) {
53 ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
56 size = le16_to_cpu(ci_read_16(dev->base+VIRTIOHDR_QUEUE_SIZE));
64 * Get address of descriptor vring
65 * @param dev pointer to virtio device information
66 * @param queue virtio queue number
67 * @return pointer to the descriptor ring
69 struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue)
71 struct vring_desc *desc = 0;
73 if (dev->type == VIRTIO_TYPE_PCI) {
74 ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
77 desc = (void*)(4096L *
78 le32_to_cpu(ci_read_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS)));
86 * Get address of "available" vring
87 * @param dev pointer to virtio device information
88 * @param queue virtio queue number
89 * @return pointer to the "available" ring
91 struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue)
93 return (void*)((uint64_t)virtio_get_vring_desc(dev, queue)
94 + virtio_get_qsize(dev, queue) * sizeof(struct vring_desc));
99 * Get address of "used" vring
100 * @param dev pointer to virtio device information
101 * @param queue virtio queue number
102 * @return pointer to the "used" ring
104 struct vring_used *virtio_get_vring_used(struct virtio_device *dev, int queue)
106 return (void*)VQ_ALIGN((uint64_t)virtio_get_vring_avail(dev, queue)
107 + virtio_get_qsize(dev, queue)
108 * sizeof(struct vring_avail));
113 * Reset virtio device
115 void virtio_reset_device(struct virtio_device *dev)
117 if (dev->type == VIRTIO_TYPE_PCI) {
118 ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, 0);
124 * Notify hypervisor about queue update
126 void virtio_queue_notify(struct virtio_device *dev, int queue)
128 if (dev->type == VIRTIO_TYPE_PCI) {
129 ci_write_16(dev->base+VIRTIOHDR_QUEUE_NOTIFY, cpu_to_le16(queue));
136 void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned int qaddr)
138 if (dev->type == VIRTIO_TYPE_PCI) {
139 uint32_t val = qaddr;
141 ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
144 ci_write_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS,
150 * Set device status bits
152 void virtio_set_status(struct virtio_device *dev, int status)
154 if (dev->type == VIRTIO_TYPE_PCI) {
155 ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, status);
161 * Set guest feature bits
163 void virtio_set_guest_features(struct virtio_device *dev, int features)
166 if (dev->type == VIRTIO_TYPE_PCI) {
167 ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, bswap_32(features));
172 * Get host feature bits
174 void virtio_get_host_features(struct virtio_device *dev, int *features)
177 if (dev->type == VIRTIO_TYPE_PCI && features) {
178 *features = bswap_32(ci_read_32(dev->base+VIRTIOHDR_DEVICE_FEATURES));
184 * Get additional config values
186 uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size)
188 uint64_t val = ~0ULL;
192 case VIRTIO_TYPE_PCI:
193 confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
200 val = ci_read_8(confbase+offset);
203 val = ci_read_16(confbase+offset);
206 val = ci_read_32(confbase+offset);
209 /* We don't support 8 bytes PIO accesses
210 * in qemu and this is all PIO
212 val = ci_read_32(confbase+offset);
214 val |= ci_read_32(confbase+offset+4);
224 int __virtio_read_config(struct virtio_device *dev, void *dst,
228 unsigned char *buf = dst;
232 case VIRTIO_TYPE_PCI:
233 confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
238 for (i = 0; i < len; i++)
239 buf[i] = ci_read_8(confbase + offset + i);