Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / lib / libvirtio / virtio.c
1 /******************************************************************************
2  * Copyright (c) 2011 IBM Corporation
3  * All rights reserved.
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
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 #include <cpu.h>
14 #include <cache.h>
15 #include <byteorder.h>
16 #include "virtio.h"
17
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
28
29
30 /**
31  * Calculate ring size according to queue size number
32  */
33 unsigned long virtio_vring_size(unsigned int qsize)
34 {
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);
39 }
40
41
42 /**
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
47  */
48 int virtio_get_qsize(struct virtio_device *dev, int queue)
49 {
50         int size = 0;
51
52         if (dev->type == VIRTIO_TYPE_PCI) {
53                 ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
54                             cpu_to_le16(queue));
55                 eieio();
56                 size = le16_to_cpu(ci_read_16(dev->base+VIRTIOHDR_QUEUE_SIZE));
57         }
58
59         return size;
60 }
61
62
63 /**
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
68  */
69 struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue)
70 {
71         struct vring_desc *desc = 0;
72
73         if (dev->type == VIRTIO_TYPE_PCI) {
74                 ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
75                             cpu_to_le16(queue));
76                 eieio();
77                 desc = (void*)(4096L *
78                    le32_to_cpu(ci_read_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS)));
79         }
80
81         return desc;
82 }
83
84
85 /**
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
90  */
91 struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue)
92 {
93         return (void*)((uint64_t)virtio_get_vring_desc(dev, queue)
94                         + virtio_get_qsize(dev, queue) * sizeof(struct vring_desc));
95 }
96
97
98 /**
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
103  */
104 struct vring_used *virtio_get_vring_used(struct virtio_device *dev, int queue)
105 {
106         return (void*)VQ_ALIGN((uint64_t)virtio_get_vring_avail(dev, queue)
107                                   + virtio_get_qsize(dev, queue)
108                                     * sizeof(struct vring_avail));
109 }
110
111
112 /**
113  * Reset virtio device
114  */
115 void virtio_reset_device(struct virtio_device *dev)
116 {
117         if (dev->type == VIRTIO_TYPE_PCI) {
118                 ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, 0);
119         }
120 }
121
122
123 /**
124  * Notify hypervisor about queue update
125  */
126 void virtio_queue_notify(struct virtio_device *dev, int queue)
127 {
128         if (dev->type == VIRTIO_TYPE_PCI) {
129                 ci_write_16(dev->base+VIRTIOHDR_QUEUE_NOTIFY, cpu_to_le16(queue));
130         }
131 }
132
133 /**
134  * Set queue address
135  */
136 void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned int qaddr)
137 {
138         if (dev->type == VIRTIO_TYPE_PCI) {
139                 uint32_t val = qaddr;
140                 val = val >> 12;
141                 ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
142                             cpu_to_le16(queue));
143                 eieio();
144                 ci_write_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS,
145                             cpu_to_le32(val));
146         }
147 }
148
149 /**
150  * Set device status bits
151  */
152 void virtio_set_status(struct virtio_device *dev, int status)
153 {
154         if (dev->type == VIRTIO_TYPE_PCI) {
155                 ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, status);
156         }
157 }
158
159
160 /**
161  * Set guest feature bits
162  */
163 void virtio_set_guest_features(struct virtio_device *dev, int features)
164
165 {
166         if (dev->type == VIRTIO_TYPE_PCI) {
167                 ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, bswap_32(features));
168         }
169 }
170
171 /**
172  * Get host feature bits
173  */
174 void virtio_get_host_features(struct virtio_device *dev, int *features)
175
176 {
177         if (dev->type == VIRTIO_TYPE_PCI && features) {
178                 *features = bswap_32(ci_read_32(dev->base+VIRTIOHDR_DEVICE_FEATURES));
179         }
180 }
181
182
183 /**
184  * Get additional config values
185  */
186 uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size)
187 {
188         uint64_t val = ~0ULL;
189         void *confbase;
190
191         switch (dev->type) {
192          case VIRTIO_TYPE_PCI:
193                 confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
194                 break;
195          default:
196                 return ~0ULL;
197         }
198         switch (size) {
199          case 1:
200                 val = ci_read_8(confbase+offset);
201                 break;
202          case 2:
203                 val = ci_read_16(confbase+offset);
204                 break;
205          case 4:
206                 val = ci_read_32(confbase+offset);
207                 break;
208          case 8:
209                 /* We don't support 8 bytes PIO accesses
210                  * in qemu and this is all PIO
211                  */
212                 val = ci_read_32(confbase+offset);
213                 val <<= 32;
214                 val |= ci_read_32(confbase+offset+4);
215                 break;
216         }
217
218         return val;
219 }
220
221 /**
222  * Get config blob
223  */
224 int __virtio_read_config(struct virtio_device *dev, void *dst,
225                           int offset, int len)
226 {
227         void *confbase;
228         unsigned char *buf = dst;
229         int i;
230
231         switch (dev->type) {
232          case VIRTIO_TYPE_PCI:
233                 confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
234                 break;
235          default:
236                 return 0;
237         }
238         for (i = 0; i < len; i++)
239                 buf[i] = ci_read_8(confbase + offset + i);
240         return len;
241 }