ReactOS  0.4.15-dev-985-gd905dd5
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 {
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 {
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__);
100 }
101 
103 {
104  DPrintf(6, "%s>>> %x\n", __FUNCTION__, status);
106 }
107 
109 {
110  /* 0 status means a reset. */
112 }
113 
115 {
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);
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 */
138 }
139 
141 {
142  VirtIODevice *vdev = vq->vdev;
143 
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. */
164  return STATUS_NOT_FOUND;
165  }
166 
167  ring_size = ROUND_TO_PAGES(vring_size(num, VIRTIO_PCI_VRING_ALIGN, false));
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 
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 
225 err_assign:
226 err_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 
280  vdev->device = &virtio_pci_device_ops;
281 
282  return STATUS_SUCCESS;
283 }
void vp_notify(struct virtqueue *vq)
#define VIRTIO_PCI_STATUS
Definition: virtio_pci.h:66
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static void vio_legacy_del_vq(VirtIOQueueInfo *info)
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define iowrite32(vdev, val, addr)
#define ioread8(vdev, addr)
unsigned int vring_control_block_size(u16 qsize, bool packed)
Definition: VirtIORing.c:474
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
void * notification_addr
Definition: VirtIO.h:47
static void vio_legacy_set_status(VirtIODevice *vdev, u8 status)
#define pci_map_address_range(vdev, bar, offset, maxlen)
volatile u8 * isr
Definition: virtio_pci.h:260
#define iowrite8(vdev, val, addr)
static void vio_legacy_set_config(VirtIODevice *vdev, unsigned offset, const void *buf, unsigned len)
unsigned int index
Definition: VirtIO.h:45
void vring_transport_features(VirtIODevice *vdev, u64 *features)
Definition: VirtIORing.c:534
#define VIRTIO_PCI_CONFIG(msix_enabled)
Definition: virtio_pci.h:83
ULONG32 u32
Definition: btrfs.h:14
#define pci_get_resource_len(vdev, bar)
uint32_t ULONG_PTR
Definition: typedefs.h:65
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 VIRTIO_PCI_ISR
Definition: virtio_pci.h:71
#define VIRTIO_PCI_QUEUE_NOTIFY
Definition: virtio_pci.h:63
static NTSTATUS vio_legacy_setup_vq(struct virtqueue **queue, VirtIODevice *vdev, VirtIOQueueInfo *info, unsigned index, u16 msix_vec)
const struct virtio_device_ops * device
Definition: virtio_pci.h:251
static PVOID ptr
Definition: dispmode.c:27
#define DPrintf(Level, Fmt)
Definition: kdebugprint.h:61
Definition: _queue.h:59
smooth NULL
Definition: ftsmooth.c:416
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT
Definition: virtio_pci.h:87
static NTSTATUS vio_legacy_query_vq_alloc(VirtIODevice *vdev, unsigned index, unsigned short *pNumEntries, unsigned long *pRingSize, unsigned long *pHeapSize)
GLuint index
Definition: glext.h:6031
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define VIRTIO_PCI_HOST_FEATURES
Definition: virtio_pci.h:48
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static void vio_legacy_reset(VirtIODevice *vdev)
static NTSTATUS vio_legacy_set_features(VirtIODevice *vdev, u64 features)
#define VIRTIO_PCI_QUEUE_PFN
Definition: virtio_pci.h:54
GLuint GLuint num
Definition: glext.h:9618
UCHAR u8
Definition: btrfs.h:12
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static u64 vio_legacy_get_features(VirtIODevice *vdev)
ULONG64 u64
Definition: btrfs.h:15
GLenum GLsizei len
Definition: glext.h:6722
#define VIRTIO_PCI_QUEUE_NUM
Definition: virtio_pci.h:57
static void vio_legacy_get_config(VirtIODevice *vdev, unsigned offset, void *buf, unsigned len)
NTSTATUS vio_legacy_initialize(VirtIODevice *vdev)
#define VIRTIO_MSI_CONFIG_VECTOR
Definition: virtio_pci.h:75
#define VIRTIO_PCI_QUEUE_SEL
Definition: virtio_pci.h:60
#define ROUND_TO_PAGES(Size)
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define VIRTIO_MSI_NO_VECTOR
Definition: virtio_pci.h:98
void vio_legacy_dump_registers(VirtIODevice *vdev)
static const struct virtio_device_ops virtio_pci_device_ops
static u16 vio_legacy_set_queue_vector(struct virtqueue *vq, u16 vector)
static u16 vio_legacy_set_config_vector(VirtIODevice *vdev, u16 vector)
static u8 vio_legacy_get_status(VirtIODevice *vdev)
unsigned long vring_size(unsigned int num, unsigned long align, bool packed)
Definition: VirtIORing.c:555
#define mem_alloc_contiguous_pages(vdev, size)
VirtIODevice * vdev
Definition: VirtIO.h:44
#define mem_free_contiguous_pages(vdev, virt)
#define ioread32(vdev, addr)
#define iowrite16(vdev, val, addr)
#define ULONG_PTR
Definition: config.h:101
#define ioread16(vdev, addr)
#define VIRTIO_PCI_GUEST_FEATURES
Definition: virtio_pci.h:51
return STATUS_SUCCESS
Definition: btrfs.c:3014
ULONG_PTR addr
Definition: virtio_pci.h:239
USHORT u16
Definition: btrfs.h:13
#define __FUNCTION__
Definition: types.h:112
static SERVICE_STATUS status
Definition: service.c:31
#define mem_get_physical_address(vdev, virt)
#define VIRTIO_PCI_VRING_ALIGN
Definition: virtio_pci.h:91
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
#define VIRTIO_MSI_QUEUE_VECTOR
Definition: virtio_pci.h:77
Definition: ps.c:97