ReactOS 0.4.15-dev-7677-g8209aa5
VirtIOPCILegacy.c
Go to the documentation of this file.
1/*
2 * Virtio PCI driver - legacy (virtio 0.9) device support
3 *
4 * Copyright IBM Corp. 2007
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 * Windows porting - Yan Vugenfirer <yvugenfi@redhat.com>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met :
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and / or other materials provided with the distribution.
18 * 3. Neither the names of the copyright holders nor the names of their contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33#include "osdep.h"
34#include "virtio_pci.h"
35#include "VirtIO.h"
36#include "kdebugprint.h"
37#include "virtio_ring.h"
38#include "virtio_pci_common.h"
40
41#ifdef WPP_EVENT_TRACING
42#include "VirtIOPCILegacy.tmh"
43#endif
44
46//
47// vio_legacy_dump_registers - Dump HW registers of the device
48//
51{
52 DPrintf(5, "%s\n", __FUNCTION__);
53
54 DPrintf(0, "[VIRTIO_PCI_HOST_FEATURES] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_HOST_FEATURES));
55 DPrintf(0, "[VIRTIO_PCI_GUEST_FEATURES] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_GUEST_FEATURES));
56 DPrintf(0, "[VIRTIO_PCI_QUEUE_PFN] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_QUEUE_PFN));
57 DPrintf(0, "[VIRTIO_PCI_QUEUE_NUM] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_QUEUE_NUM));
58 DPrintf(0, "[VIRTIO_PCI_QUEUE_SEL] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_QUEUE_SEL));
59 DPrintf(0, "[VIRTIO_PCI_QUEUE_NOTIFY] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_QUEUE_NOTIFY));
60 DPrintf(0, "[VIRTIO_PCI_STATUS] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_STATUS));
61 DPrintf(0, "[VIRTIO_PCI_ISR] = %x\n", ioread32(vdev, vdev->addr + VIRTIO_PCI_ISR));
62}
63
65 unsigned offset,
66 void *buf,
67 unsigned len)
68{
69 ULONG_PTR ioaddr = vdev->addr + VIRTIO_PCI_CONFIG(vdev->msix_used) + offset;
70 u8 *ptr = buf;
71 unsigned i;
72
73 DPrintf(5, "%s\n", __FUNCTION__);
74
75 for (i = 0; i < len; i++) {
76 ptr[i] = ioread8(vdev, ioaddr + i);
77 }
78}
79
81 unsigned offset,
82 const void *buf,
83 unsigned len)
84{
85 ULONG_PTR ioaddr = vdev->addr + VIRTIO_PCI_CONFIG(vdev->msix_used) + offset;
86 const u8 *ptr = buf;
87 unsigned i;
88
89 DPrintf(5, "%s\n", __FUNCTION__);
90
91 for (i = 0; i < len; i++) {
92 iowrite8(vdev, ptr[i], ioaddr + i);
93 }
94}
95
97{
98 DPrintf(6, "%s\n", __FUNCTION__);
99 return ioread8(vdev, vdev->addr + VIRTIO_PCI_STATUS);
100}
101
103{
104 DPrintf(6, "%s>>> %x\n", __FUNCTION__, status);
105 iowrite8(vdev, status, vdev->addr + VIRTIO_PCI_STATUS);
106}
107
109{
110 /* 0 status means a reset. */
111 iowrite8(vdev, 0, vdev->addr + VIRTIO_PCI_STATUS);
112}
113
115{
116 return ioread32(vdev, vdev->addr + VIRTIO_PCI_HOST_FEATURES);
117}
118
120{
121 /* Give virtio_ring a chance to accept features. */
122 vring_transport_features(vdev, &features);
123
124 /* Make sure we don't have any features > 32 bits! */
125 ASSERT((u32)features == features);
126 iowrite32(vdev, (u32)features, vdev->addr + VIRTIO_PCI_GUEST_FEATURES);
127
128 return STATUS_SUCCESS;
129}
130
132{
133 /* Setup the vector used for configuration events */
135 /* Verify we had enough resources to assign the vector */
136 /* Will also flush the write out to device */
137 return ioread16(vdev, vdev->addr + VIRTIO_MSI_CONFIG_VECTOR);
138}
139
141{
142 VirtIODevice *vdev = vq->vdev;
143
144 iowrite16(vdev, (u16)vq->index, vdev->addr + VIRTIO_PCI_QUEUE_SEL);
146 return ioread16(vdev, vdev->addr + VIRTIO_MSI_QUEUE_VECTOR);
147}
148
150 unsigned index,
151 unsigned short *pNumEntries,
152 unsigned long *pRingSize,
153 unsigned long *pHeapSize)
154{
155 unsigned long ring_size, data_size;
156 u16 num;
157
158 /* Select the queue we're interested in */
160
161 /* Check if queue is either not available or already active. */
162 num = ioread16(vdev, vdev->addr + VIRTIO_PCI_QUEUE_NUM);
163 if (!num || ioread32(vdev, vdev->addr + VIRTIO_PCI_QUEUE_PFN)) {
164 return STATUS_NOT_FOUND;
165 }
166
168 data_size = ROUND_TO_PAGES(vring_control_block_size(num, false));
169
170 *pNumEntries = num;
171 *pRingSize = ring_size + data_size;
172 *pHeapSize = 0;
173
174 return STATUS_SUCCESS;
175}
176
178 VirtIODevice *vdev,
180 unsigned index,
181 u16 msix_vec)
182{
183 struct virtqueue *vq;
184 unsigned long ring_size, heap_size;
186
187 /* Select the queue and query allocation parameters */
188 status = vio_legacy_query_vq_alloc(vdev, index, &info->num, &ring_size, &heap_size);
189 if (!NT_SUCCESS(status)) {
190 return status;
191 }
192
193 info->queue = mem_alloc_contiguous_pages(vdev, ring_size);
194 if (info->queue == NULL) {
196 }
197
198 /* activate the queue */
201
202 /* create the vring */
205 info->queue, vp_notify,
206 (u8 *)info->queue + ROUND_TO_PAGES(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN, false)));
207 if (!vq) {
209 goto err_activate_queue;
210 }
211
213
214 if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
215 msix_vec = vdev->device->set_queue_vector(vq, msix_vec);
216 if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
218 goto err_assign;
219 }
220 }
221
222 *queue = vq;
223 return STATUS_SUCCESS;
224
225err_assign:
226err_activate_queue:
229 return status;
230}
231
233{
234 struct virtqueue *vq = info->vq;
235 VirtIODevice *vdev = vq->vdev;
236
238
239 if (vdev->msix_used) {
242 /* Flush the write out to device */
244 }
245
246 /* Select and deactivate the queue */
248
250}
251
253 /* .get_config = */ vio_legacy_get_config,
254 /* .set_config = */ vio_legacy_set_config,
255 /* .get_config_generation = */ NULL,
256 /* .get_status = */ vio_legacy_get_status,
257 /* .set_status = */ vio_legacy_set_status,
258 /* .reset = */ vio_legacy_reset,
259 /* .get_features = */ vio_legacy_get_features,
260 /* .set_features = */ vio_legacy_set_features,
261 /* .set_config_vector = */ vio_legacy_set_config_vector,
262 /* .set_queue_vector = */ vio_legacy_set_queue_vector,
263 /* .query_queue_alloc = */ vio_legacy_query_vq_alloc,
264 /* .setup_queue = */ vio_legacy_setup_vq,
265 /* .delete_queue = */ vio_legacy_del_vq,
266};
267
268/* Legacy device initialization */
270{
271 size_t length = pci_get_resource_len(vdev, 0);
272 vdev->addr = (ULONG_PTR)pci_map_address_range(vdev, 0, 0, length);
273
274 if (!vdev->addr) {
276 }
277
278 vdev->isr = (u8 *)vdev->addr + VIRTIO_PCI_ISR;
279
281
282 return STATUS_SUCCESS;
283}
void vio_legacy_dump_registers(VirtIODevice *vdev)
static void vio_legacy_del_vq(VirtIOQueueInfo *info)
static void vio_legacy_set_status(VirtIODevice *vdev, u8 status)
static void vio_legacy_reset(VirtIODevice *vdev)
static NTSTATUS vio_legacy_query_vq_alloc(VirtIODevice *vdev, unsigned index, unsigned short *pNumEntries, unsigned long *pRingSize, unsigned long *pHeapSize)
static const struct virtio_device_ops virtio_pci_device_ops
static void vio_legacy_get_config(VirtIODevice *vdev, unsigned offset, void *buf, unsigned len)
static u16 vio_legacy_set_queue_vector(struct virtqueue *vq, u16 vector)
static NTSTATUS vio_legacy_set_features(VirtIODevice *vdev, u64 features)
static u16 vio_legacy_set_config_vector(VirtIODevice *vdev, u16 vector)
static NTSTATUS vio_legacy_setup_vq(struct virtqueue **queue, VirtIODevice *vdev, VirtIOQueueInfo *info, unsigned index, u16 msix_vec)
static u8 vio_legacy_get_status(VirtIODevice *vdev)
NTSTATUS vio_legacy_initialize(VirtIODevice *vdev)
static u64 vio_legacy_get_features(VirtIODevice *vdev)
static void vio_legacy_set_config(VirtIODevice *vdev, unsigned offset, const void *buf, unsigned len)
struct virtqueue * vring_new_virtqueue_split(unsigned int index, unsigned int num, unsigned int vring_align, VirtIODevice *vdev, void *pages, void(*notify)(struct virtqueue *), void *control)
Definition: VirtIORing.c:486
unsigned int vring_control_block_size(u16 qsize, bool packed)
Definition: VirtIORing.c:474
LONG NTSTATUS
Definition: precomp.h:26
ULONG32 u32
Definition: btrfs.h:14
ULONG64 u64
Definition: btrfs.h:15
UCHAR u8
Definition: btrfs.h:12
USHORT u16
Definition: btrfs.h:13
Definition: _queue.h:67
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define __FUNCTION__
Definition: types.h:116
#define DPrintf(Level, Fmt)
Definition: kdebugprint.h:61
#define ULONG_PTR
Definition: config.h:101
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
static PVOID ptr
Definition: dispmode.c:27
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
Definition: ps.c:97
volatile u8 * isr
Definition: virtio_pci.h:260
ULONG_PTR addr
Definition: virtio_pci.h:239
const struct virtio_device_ops * device
Definition: virtio_pci.h:251
void * notification_addr
Definition: VirtIO.h:47
unsigned int index
Definition: VirtIO.h:45
VirtIODevice * vdev
Definition: VirtIO.h:44
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define VIRTIO_PCI_QUEUE_NUM
Definition: virtio_pci.h:57
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT
Definition: virtio_pci.h:87
#define VIRTIO_PCI_VRING_ALIGN
Definition: virtio_pci.h:91
#define VIRTIO_PCI_ISR
Definition: virtio_pci.h:71
#define VIRTIO_MSI_QUEUE_VECTOR
Definition: virtio_pci.h:77
#define VIRTIO_PCI_CONFIG(msix_enabled)
Definition: virtio_pci.h:83
#define VIRTIO_MSI_NO_VECTOR
Definition: virtio_pci.h:98
#define VIRTIO_PCI_HOST_FEATURES
Definition: virtio_pci.h:48
#define VIRTIO_PCI_QUEUE_SEL
Definition: virtio_pci.h:60
#define VIRTIO_PCI_STATUS
Definition: virtio_pci.h:66
#define VIRTIO_PCI_QUEUE_NOTIFY
Definition: virtio_pci.h:63
#define VIRTIO_PCI_GUEST_FEATURES
Definition: virtio_pci.h:51
#define VIRTIO_MSI_CONFIG_VECTOR
Definition: virtio_pci.h:75
#define VIRTIO_PCI_QUEUE_PFN
Definition: virtio_pci.h:54
#define mem_get_physical_address(vdev, virt)
#define ioread16(vdev, addr)
#define pci_map_address_range(vdev, bar, offset, maxlen)
#define mem_alloc_contiguous_pages(vdev, size)
#define mem_free_contiguous_pages(vdev, virt)
#define iowrite32(vdev, val, addr)
void vp_notify(struct virtqueue *vq)
#define pci_get_resource_len(vdev, bar)
#define iowrite16(vdev, val, addr)
#define ioread8(vdev, addr)
#define iowrite8(vdev, val, addr)
#define ioread32(vdev, addr)
unsigned long vring_size(unsigned int num, unsigned long align, bool packed)
Definition: VirtIORing.c:555
void vring_transport_features(VirtIODevice *vdev, u64 *features)
Definition: VirtIORing.c:534
#define ROUND_TO_PAGES(Size)