ReactOS 0.4.16-dev-295-g4aee028
VirtIOPCIModern.c File Reference
#include "osdep.h"
#include "virtio_pci.h"
#include "VirtIO.h"
#include "kdebugprint.h"
#include "virtio_ring.h"
#include "virtio_pci_common.h"
#include "windows/virtio_ring_allocation.h"
#include <stddef.h>
Include dependency graph for VirtIOPCIModern.c:

Go to the source code of this file.

Macros

#define VIRTIO_PCI_NO_LEGACY
 

Functions

static voidvio_modern_map_capability (VirtIODevice *vdev, int cap_offset, size_t minlen, u32 alignment, u32 start, u32 size, size_t *len)
 
static voidvio_modern_map_simple_capability (VirtIODevice *vdev, int cap_offset, size_t length, u32 alignment)
 
static void vio_modern_get_config (VirtIODevice *vdev, unsigned offset, void *buf, unsigned len)
 
static void vio_modern_set_config (VirtIODevice *vdev, unsigned offset, const void *buf, unsigned len)
 
static u32 vio_modern_get_generation (VirtIODevice *vdev)
 
static u8 vio_modern_get_status (VirtIODevice *vdev)
 
static void vio_modern_set_status (VirtIODevice *vdev, u8 status)
 
static void vio_modern_reset (VirtIODevice *vdev)
 
static u64 vio_modern_get_features (VirtIODevice *vdev)
 
static NTSTATUS vio_modern_set_features (VirtIODevice *vdev, u64 features)
 
static u16 vio_modern_set_config_vector (VirtIODevice *vdev, u16 vector)
 
static u16 vio_modern_set_queue_vector (struct virtqueue *vq, u16 vector)
 
static size_t vring_pci_size (u16 num, bool packed)
 
static NTSTATUS vio_modern_query_vq_alloc (VirtIODevice *vdev, unsigned index, unsigned short *pNumEntries, unsigned long *pRingSize, unsigned long *pHeapSize)
 
static NTSTATUS vio_modern_setup_vq (struct virtqueue **queue, VirtIODevice *vdev, VirtIOQueueInfo *info, unsigned index, u16 msix_vec)
 
static void vio_modern_del_vq (VirtIOQueueInfo *info)
 
static u8 find_next_pci_vendor_capability (VirtIODevice *vdev, u8 offset)
 
static u8 find_first_pci_vendor_capability (VirtIODevice *vdev)
 
static void find_pci_vendor_capabilities (VirtIODevice *vdev, int *Offsets, size_t nOffsets)
 
NTSTATUS vio_modern_initialize (VirtIODevice *vdev)
 

Variables

static const struct virtio_device_ops virtio_pci_device_ops
 

Macro Definition Documentation

◆ VIRTIO_PCI_NO_LEGACY

#define VIRTIO_PCI_NO_LEGACY

Definition at line 36 of file VirtIOPCIModern.c.

Function Documentation

◆ find_first_pci_vendor_capability()

static u8 find_first_pci_vendor_capability ( VirtIODevice vdev)
static

Definition at line 463 of file VirtIOPCIModern.c.

464{
465 u8 hdr_type, offset;
466 u16 status;
467
468 if (pci_read_config_byte(vdev, offsetof(PCI_COMMON_HEADER, HeaderType), &hdr_type) != 0) {
469 return 0;
470 }
472 return 0;
473 }
475 return 0;
476 }
477
478 switch (hdr_type & ~PCI_MULTIFUNCTION) {
479 case PCI_BRIDGE_TYPE:
480 offset = offsetof(PCI_COMMON_HEADER, u.type1.CapabilitiesPtr);
481 break;
483 offset = offsetof(PCI_COMMON_HEADER, u.type2.CapabilitiesPtr);
484 break;
485 default:
486 offset = offsetof(PCI_COMMON_HEADER, u.type0.CapabilitiesPtr);
487 break;
488 }
489
490 if (offset != 0) {
492 }
493 return offset;
494}
static u8 find_next_pci_vendor_capability(VirtIODevice *vdev, u8 offset)
UCHAR u8
Definition: btrfs.h:12
USHORT u16
Definition: btrfs.h:13
Status
Definition: gdiplustypes.h:25
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 * u
Definition: glfuncs.h:240
#define offsetof(TYPE, MEMBER)
Definition: ps.c:97
#define pci_read_config_byte(vdev, where, bVal)
#define pci_read_config_word(vdev, where, wVal)
#define PCI_MULTIFUNCTION
Definition: iotypes.h:3604
#define PCI_BRIDGE_TYPE
Definition: iotypes.h:3606
#define PCI_STATUS_CAPABILITIES_LIST
Definition: iotypes.h:3630
#define PCI_CARDBUS_BRIDGE_TYPE
Definition: iotypes.h:3607

Referenced by find_pci_vendor_capabilities().

◆ find_next_pci_vendor_capability()

static u8 find_next_pci_vendor_capability ( VirtIODevice vdev,
u8  offset 
)
static

Definition at line 434 of file VirtIOPCIModern.c.

435{
436 u8 id = 0;
437 int iterations = 48;
438
439 if (pci_read_config_byte(vdev, offset, &offset) != 0) {
440 return 0;
441 }
442
443 while (iterations-- && offset >= 0x40) {
444 offset &= ~3;
446 CapabilityID), &id) != 0) {
447 break;
448 }
449 if (id == 0xFF) {
450 break;
451 }
453 return offset;
454 }
456 Next), &offset) != 0) {
457 break;
458 }
459 }
460 return 0;
461}
#define PCI_CAPABILITY_ID_VENDOR_SPECIFIC
Definition: iotypes.h:3655

Referenced by find_first_pci_vendor_capability(), and find_pci_vendor_capabilities().

◆ find_pci_vendor_capabilities()

static void find_pci_vendor_capabilities ( VirtIODevice vdev,
int Offsets,
size_t  nOffsets 
)
static

Definition at line 497 of file VirtIOPCIModern.c.

498{
500 while (offset > 0) {
501 u8 cfg_type, bar;
502 pci_read_config_byte(vdev, offset + offsetof(struct virtio_pci_cap, cfg_type), &cfg_type);
504
505 if (bar < PCI_TYPE0_ADDRESSES &&
506 cfg_type < nOffsets &&
507 pci_get_resource_len(vdev, bar) > 0) {
508 Offsets[cfg_type] = offset;
509 }
510
512 }
513}
static u8 find_first_pci_vendor_capability(VirtIODevice *vdev)
void bar()
Definition: ehthrow.cxx:142
#define pci_get_resource_len(vdev, bar)
#define PCI_TYPE0_ADDRESSES
Definition: iotypes.h:3500

Referenced by vio_modern_initialize().

◆ vio_modern_del_vq()

static void vio_modern_del_vq ( VirtIOQueueInfo info)
static

Definition at line 399 of file VirtIOPCIModern.c.

400{
401 struct virtqueue *vq = info->vq;
402 VirtIODevice *vdev = vq->vdev;
403
404 iowrite16(vdev, (u16)vq->index, &vdev->common->queue_select);
405
406 if (vdev->msix_used) {
407 iowrite16(vdev, VIRTIO_MSI_NO_VECTOR, &vdev->common->queue_msix_vector);
408 /* Flush the write out to device */
409 ioread16(vdev, &vdev->common->queue_msix_vector);
410 }
411
413
416}
static void virtqueue_shutdown(struct virtqueue *vq)
Definition: VirtIO.h:120
volatile struct virtio_pci_common_cfg * common
Definition: virtio_pci.h:263
unsigned int index
Definition: VirtIO.h:45
VirtIODevice * vdev
Definition: VirtIO.h:44
#define VIRTIO_MSI_NO_VECTOR
Definition: virtio_pci.h:98
#define mem_free_nonpaged_block(vdev, addr)
#define ioread16(vdev, addr)
#define mem_free_contiguous_pages(vdev, virt)
#define iowrite16(vdev, val, addr)

◆ vio_modern_get_config()

static void vio_modern_get_config ( VirtIODevice vdev,
unsigned  offset,
void buf,
unsigned  len 
)
static

Definition at line 106 of file VirtIOPCIModern.c.

108{
109 if (!vdev->config) {
110 ASSERT(!"Device has no config to read");
111 return;
112 }
113 if (offset + len > vdev->config_len) {
114 ASSERT(!"Can't read beyond the config length");
115 return;
116 }
117
118 switch (len) {
119 case 1:
120 *(u8 *)buf = ioread8(vdev, vdev->config + offset);
121 break;
122 case 2:
123 *(u16 *)buf = ioread16(vdev, vdev->config + offset);
124 break;
125 case 4:
126 *(u32 *)buf = ioread32(vdev, vdev->config + offset);
127 break;
128 default:
129 ASSERT(!"Only 1, 2, 4 byte config reads are supported");
130 }
131}
ULONG32 u32
Definition: btrfs.h:14
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLsizei len
Definition: glext.h:6722
#define ASSERT(a)
Definition: mode.c:44
volatile unsigned char * config
Definition: virtio_pci.h:264
size_t config_len
Definition: virtio_pci.h:269
#define ioread8(vdev, addr)
#define ioread32(vdev, addr)

◆ vio_modern_get_features()

static u64 vio_modern_get_features ( VirtIODevice vdev)
static

Definition at line 196 of file VirtIOPCIModern.c.

197{
198 u64 features;
199
200 iowrite32(vdev, 0, &vdev->common->device_feature_select);
201 features = ioread32(vdev, &vdev->common->device_feature);
202 iowrite32(vdev, 1, &vdev->common->device_feature_select);
203 features |= ((u64)ioread32(vdev, &vdev->common->device_feature) << 32);
204
205 return features;
206}
ULONG64 u64
Definition: btrfs.h:15
#define u64
Definition: types.h:10
#define iowrite32(vdev, val, addr)

◆ vio_modern_get_generation()

static u32 vio_modern_get_generation ( VirtIODevice vdev)
static

Definition at line 160 of file VirtIOPCIModern.c.

161{
162 return ioread8(vdev, &vdev->common->config_generation);
163}

◆ vio_modern_get_status()

static u8 vio_modern_get_status ( VirtIODevice vdev)
static

Definition at line 165 of file VirtIOPCIModern.c.

166{
167 return ioread8(vdev, &vdev->common->device_status);
168}

◆ vio_modern_initialize()

NTSTATUS vio_modern_initialize ( VirtIODevice vdev)

Definition at line 516 of file VirtIOPCIModern.c.

517{
518 int capabilities[VIRTIO_PCI_CAP_PCI_CFG];
519
520 u32 notify_length;
521 u32 notify_offset;
522
523 RtlZeroMemory(capabilities, sizeof(capabilities));
525
526 /* Check for a common config, if not found use legacy mode */
527 if (!capabilities[VIRTIO_PCI_CAP_COMMON_CFG]) {
528 DPrintf(0, "%s(%p): device not found\n", __FUNCTION__, vdev);
530 }
531
532 /* Check isr and notify caps, if not found fail */
533 if (!capabilities[VIRTIO_PCI_CAP_ISR_CFG] || !capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG]) {
534 DPrintf(0, "%s(%p): missing capabilities %i/%i/%i\n",
535 __FUNCTION__, vdev,
536 capabilities[VIRTIO_PCI_CAP_COMMON_CFG],
537 capabilities[VIRTIO_PCI_CAP_ISR_CFG],
538 capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG]);
540 }
541
542 /* Map bars according to the capabilities */
544 capabilities[VIRTIO_PCI_CAP_COMMON_CFG],
545 sizeof(struct virtio_pci_common_cfg), 4);
546 if (!vdev->common) {
548 }
549
551 capabilities[VIRTIO_PCI_CAP_ISR_CFG],
552 sizeof(u8), 1);
553 if (!vdev->isr) {
555 }
556
557 /* Read notify_off_multiplier from config space. */
560 notify_off_multiplier),
562
563 /* Read notify length and offset from config space. */
566 cap.length),
567 &notify_length);
570 cap.offset),
571 &notify_offset);
572
573 /* Map the notify capability if it's small enough.
574 * Otherwise, map each VQ individually later.
575 */
576 if (notify_length + (notify_offset % PAGE_SIZE) <= PAGE_SIZE) {
578 capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG], 2, 2,
579 0, notify_length,
580 &vdev->notify_len);
581 if (!vdev->notify_base) {
583 }
584 } else {
585 vdev->notify_map_cap = capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG];
586 }
587
588 /* Map the device config capability, the PAGE_SIZE size is a guess */
589 if (capabilities[VIRTIO_PCI_CAP_DEVICE_CFG]) {
591 capabilities[VIRTIO_PCI_CAP_DEVICE_CFG], 0, 4,
592 0, PAGE_SIZE,
593 &vdev->config_len);
594 if (!vdev->config) {
596 }
597 }
598
600
601 return STATUS_SUCCESS;
602}
static void * vio_modern_map_simple_capability(VirtIODevice *vdev, int cap_offset, size_t length, u32 alignment)
static void find_pci_vendor_capabilities(VirtIODevice *vdev, int *Offsets, size_t nOffsets)
static const struct virtio_device_ops virtio_pci_device_ops
static void * vio_modern_map_capability(VirtIODevice *vdev, int cap_offset, size_t minlen, u32 alignment, u32 start, u32 size, size_t *len)
#define __FUNCTION__
Definition: types.h:116
#define DPrintf(Level, Fmt)
Definition: kdebugprint.h:61
#define PAGE_SIZE
Definition: env_spec_w32.h:49
GLenum cap
Definition: glext.h:9639
#define STATUS_SUCCESS
Definition: shellext.h:65
volatile u8 * isr
Definition: virtio_pci.h:260
size_t notify_len
Definition: virtio_pci.h:270
int notify_map_cap
Definition: virtio_pci.h:266
const struct virtio_device_ops * device
Definition: virtio_pci.h:251
volatile unsigned char * notify_base
Definition: virtio_pci.h:265
u32 notify_offset_multiplier
Definition: virtio_pci.h:267
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define VIRTIO_PCI_CAP_PCI_CFG
Definition: virtio_pci.h:111
#define VIRTIO_PCI_CAP_DEVICE_CFG
Definition: virtio_pci.h:109
#define VIRTIO_PCI_CAP_ISR_CFG
Definition: virtio_pci.h:107
#define VIRTIO_PCI_CAP_NOTIFY_CFG
Definition: virtio_pci.h:105
#define VIRTIO_PCI_CAP_COMMON_CFG
Definition: virtio_pci.h:103
#define pci_read_config_dword(vdev, where, dwVal)

Referenced by virtio_device_initialize().

◆ vio_modern_map_capability()

static void * vio_modern_map_capability ( VirtIODevice vdev,
int  cap_offset,
size_t  minlen,
u32  alignment,
u32  start,
u32  size,
size_t len 
)
static

Definition at line 49 of file VirtIOPCIModern.c.

52{
53 u8 bar;
54 u32 bar_offset, bar_length;
55 void *addr;
56
57 pci_read_config_byte(vdev, cap_offset + offsetof(struct virtio_pci_cap, bar), &bar);
58 pci_read_config_dword(vdev, cap_offset + offsetof(struct virtio_pci_cap, offset), &bar_offset);
59 pci_read_config_dword(vdev, cap_offset + offsetof(struct virtio_pci_cap, length), &bar_length);
60
61 if (start + minlen > bar_length) {
62 DPrintf(0, "bar %i cap is not large enough to map %zu bytes at offset %u\n", bar, minlen, start);
63 return NULL;
64 }
65
66 bar_length -= start;
67 bar_offset += start;
68
69 if (bar_offset & (alignment - 1)) {
70 DPrintf(0, "bar %i offset %u not aligned to %u\n", bar, bar_offset, alignment);
71 return NULL;
72 }
73
74 if (bar_length > size) {
75 bar_length = size;
76 }
77
78 if (len) {
79 *len = bar_length;
80 }
81
82 if (bar_offset + minlen > pci_get_resource_len(vdev, bar)) {
83 DPrintf(0, "bar %i is not large enough to map %zu bytes at offset %u\n", bar, minlen, bar_offset);
84 return NULL;
85 }
86
87 addr = pci_map_address_range(vdev, bar, bar_offset, bar_length);
88 if (!addr) {
89 DPrintf(0, "unable to map %u bytes at bar %i offset %u\n", bar_length, bar, bar_offset);
90 }
91 return addr;
92}
#define NULL
Definition: types.h:112
GLuint start
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum const GLvoid * addr
Definition: glext.h:9621
#define pci_map_address_range(vdev, bar, offset, maxlen)

Referenced by vio_modern_initialize(), vio_modern_map_simple_capability(), and vio_modern_setup_vq().

◆ vio_modern_map_simple_capability()

static void * vio_modern_map_simple_capability ( VirtIODevice vdev,
int  cap_offset,
size_t  length,
u32  alignment 
)
static

Definition at line 94 of file VirtIOPCIModern.c.

95{
97 vdev,
98 cap_offset,
99 length, // minlen
100 alignment,
101 0, // offset
102 (u32)length, // size is equal to minlen
103 NULL); // not interested in the full length
104}

Referenced by vio_modern_initialize().

◆ vio_modern_query_vq_alloc()

static NTSTATUS vio_modern_query_vq_alloc ( VirtIODevice vdev,
unsigned  index,
unsigned short pNumEntries,
unsigned long pRingSize,
unsigned long pHeapSize 
)
static

Definition at line 251 of file VirtIOPCIModern.c.

256{
257 volatile struct virtio_pci_common_cfg *cfg = vdev->common;
258 u16 num;
259
260 if (index >= ioread16(vdev, &cfg->num_queues)) {
261 return STATUS_NOT_FOUND;
262 }
263
264 /* Select the queue we're interested in */
265 iowrite16(vdev, (u16)index, &cfg->queue_select);
266
267 /* Check if queue is either not available or already active. */
268 num = ioread16(vdev, &cfg->queue_size);
269 /* QEMU has a bug where queues don't revert to inactive on device
270 * reset. Skip checking the queue_enable field until it is fixed.
271 */
272 if (!num /*|| ioread16(vdev, &cfg->queue_enable)*/) {
273 return STATUS_NOT_FOUND;
274 }
275
276 if (num & (num - 1)) {
277 DPrintf(0, "%p: bad queue size %u", vdev, num);
279 }
280
281 *pNumEntries = num;
282 *pRingSize = (unsigned long)vring_pci_size(num, vdev->packed_ring);
283 *pHeapSize = vring_control_block_size(num, vdev->packed_ring);
284
285 return STATUS_SUCCESS;
286}
static size_t vring_pci_size(u16 num, bool packed)
unsigned int vring_control_block_size(u16 qsize, bool packed)
Definition: VirtIORing.c:474
GLuint index
Definition: glext.h:6031
GLuint GLuint num
Definition: glext.h:9618
#define long
Definition: qsort.c:33
#define STATUS_NOT_FOUND
Definition: shellext.h:72
bool packed_ring
Definition: virtio_pci.h:248

Referenced by vio_modern_setup_vq().

◆ vio_modern_reset()

static void vio_modern_reset ( VirtIODevice vdev)
static

Definition at line 177 of file VirtIOPCIModern.c.

178{
179 /* 0 status means a reset. */
180 iowrite8(vdev, 0, &vdev->common->device_status);
181 /* After writing 0 to device_status, the driver MUST wait for a read of
182 * device_status to return 0 before reinitializing the device.
183 * This will flush out the status write, and flush in device writes,
184 * including MSI-X interrupts, if any.
185 */
186 while (ioread8(vdev, &vdev->common->device_status)) {
187 u16 val;
188 if (pci_read_config_word(vdev, 0, &val) || val == 0xffff) {
189 DPrintf(0, "PCI config space is not readable, probably the device is removed\n", 0);
190 break;
191 }
192 vdev_sleep(vdev, 1);
193 }
194}
GLuint GLfloat * val
Definition: glext.h:7180
#define vdev_sleep(vdev, msecs)
#define iowrite8(vdev, val, addr)

◆ vio_modern_set_config()

static void vio_modern_set_config ( VirtIODevice vdev,
unsigned  offset,
const void buf,
unsigned  len 
)
static

Definition at line 133 of file VirtIOPCIModern.c.

135{
136 if (!vdev->config) {
137 ASSERT(!"Device has no config to write");
138 return;
139 }
140 if (offset + len > vdev->config_len) {
141 ASSERT(!"Can't write beyond the config length");
142 return;
143 }
144
145 switch (len) {
146 case 1:
147 iowrite8(vdev, *(u8 *)buf, vdev->config + offset);
148 break;
149 case 2:
150 iowrite16(vdev, *(u16 *)buf, vdev->config + offset);
151 break;
152 case 4:
153 iowrite32(vdev, *(u32 *)buf, vdev->config + offset);
154 break;
155 default:
156 ASSERT(!"Only 1, 2, 4 byte config writes are supported");
157 }
158}

◆ vio_modern_set_config_vector()

static u16 vio_modern_set_config_vector ( VirtIODevice vdev,
u16  vector 
)
static

Definition at line 226 of file VirtIOPCIModern.c.

227{
228 /* Setup the vector used for configuration events */
229 iowrite16(vdev, vector, &vdev->common->msix_config);
230 /* Verify we had enough resources to assign the vector */
231 /* Will also flush the write out to device */
232 return ioread16(vdev, &vdev->common->msix_config);
233}

◆ vio_modern_set_features()

static NTSTATUS vio_modern_set_features ( VirtIODevice vdev,
u64  features 
)
static

Definition at line 208 of file VirtIOPCIModern.c.

209{
210 /* Give virtio_ring a chance to accept features. */
211 vring_transport_features(vdev, &features);
212
214 DPrintf(0, "virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1\n", 0);
216 }
217
218 iowrite32(vdev, 0, &vdev->common->guest_feature_select);
219 iowrite32(vdev, (u32)features, &vdev->common->guest_feature);
220 iowrite32(vdev, 1, &vdev->common->guest_feature_select);
221 iowrite32(vdev, features >> 32, &vdev->common->guest_feature);
222
223 return STATUS_SUCCESS;
224}
#define VIRTIO_F_VERSION_1
Definition: virtio_config.h:63
#define virtio_is_feature_enabled(FeaturesList, Feature)
Definition: virtio_pci.h:311
void vring_transport_features(VirtIODevice *vdev, u64 *features)
Definition: VirtIORing.c:534

◆ vio_modern_set_queue_vector()

static u16 vio_modern_set_queue_vector ( struct virtqueue vq,
u16  vector 
)
static

Definition at line 235 of file VirtIOPCIModern.c.

236{
237 VirtIODevice *vdev = vq->vdev;
238 volatile struct virtio_pci_common_cfg *cfg = vdev->common;
239
240 iowrite16(vdev, (u16)vq->index, &cfg->queue_select);
241 iowrite16(vdev, vector, &cfg->queue_msix_vector);
242 return ioread16(vdev, &cfg->queue_msix_vector);
243}

◆ vio_modern_set_status()

static void vio_modern_set_status ( VirtIODevice vdev,
u8  status 
)
static

Definition at line 170 of file VirtIOPCIModern.c.

171{
172 /* We should never be setting status to 0. */
173 ASSERT(status != 0);
174 iowrite8(vdev, status, &vdev->common->device_status);
175}

◆ vio_modern_setup_vq()

static NTSTATUS vio_modern_setup_vq ( struct virtqueue **  queue,
VirtIODevice vdev,
VirtIOQueueInfo info,
unsigned  index,
u16  msix_vec 
)
static

Definition at line 288 of file VirtIOPCIModern.c.

293{
294 volatile struct virtio_pci_common_cfg *cfg = vdev->common;
295 struct virtqueue *vq;
296 void *vq_addr;
297 u16 off;
298 unsigned long ring_size, heap_size;
300
301 /* select the queue and query allocation parameters */
302 status = vio_modern_query_vq_alloc(vdev, index, &info->num, &ring_size, &heap_size);
303 if (!NT_SUCCESS(status)) {
304 return status;
305 }
306
307 /* get offset of notification word for this vq */
308 off = ioread16(vdev, &cfg->queue_notify_off);
309
310 /* try to allocate contiguous pages, scale down on failure */
312 if (info->num > 0) {
313 info->num /= 2;
314 } else {
316 }
317 }
318
319 vq_addr = mem_alloc_nonpaged_block(vdev, heap_size);
320 if (vq_addr == NULL) {
322 }
323
324 /* create the vring */
325 if (vdev->packed_ring) {
328 info->queue, vp_notify, vq_addr);
329 } else {
332 info->queue, vp_notify, vq_addr);
333 }
334
335 if (!vq) {
337 goto err_new_queue;
338 }
339
340 /* activate the queue */
341 iowrite16(vdev, info->num, &cfg->queue_size);
343 &cfg->queue_desc_lo, &cfg->queue_desc_hi);
345 &cfg->queue_avail_lo, &cfg->queue_avail_hi);
347 &cfg->queue_used_lo, &cfg->queue_used_hi);
348
349 if (vdev->notify_base) {
350 /* offset should not wrap */
351 if ((u64)off * vdev->notify_offset_multiplier + 2
352 > vdev->notify_len) {
353 DPrintf(0,
354 "%p: bad notification offset %u (x %u) "
355 "for queue %u > %zd",
356 vdev,
360 goto err_map_notify;
361 }
362 vq->notification_addr = (void *)(vdev->notify_base +
364 } else {
366 vdev->notify_map_cap, 2, 2,
368 NULL);
369 }
370
371 if (!vq->notification_addr) {
373 goto err_map_notify;
374 }
375
376 if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
377 msix_vec = vdev->device->set_queue_vector(vq, msix_vec);
378 if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
380 goto err_assign_vector;
381 }
382 }
383
384 /* enable the queue */
385 iowrite16(vdev, 1, &vdev->common->queue_enable);
386
387 *queue = vq;
388 return STATUS_SUCCESS;
389
390err_assign_vector:
391err_map_notify:
393err_new_queue:
396 return status;
397}
static NTSTATUS vio_modern_query_vq_alloc(VirtIODevice *vdev, unsigned index, unsigned short *pNumEntries, unsigned long *pRingSize, unsigned long *pHeapSize)
struct virtqueue * vring_new_virtqueue_packed(unsigned int index, unsigned int num, unsigned int vring_align, VirtIODevice *vdev, void *pages, void(*notify)(struct virtqueue *), void *control)
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
LONG NTSTATUS
Definition: precomp.h:26
Definition: _queue.h:67
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define SMP_CACHE_BYTES
Definition: osdep.h:41
void * notification_addr
Definition: VirtIO.h:47
void * avail_va
Definition: VirtIO.h:48
void * used_va
Definition: VirtIO.h:49
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define mem_get_physical_address(vdev, virt)
#define mem_alloc_nonpaged_block(vdev, size)
#define iowrite64_twopart(vdev, val, lo_addr, hi_addr)
#define mem_alloc_contiguous_pages(vdev, size)
void vp_notify(struct virtqueue *vq)

◆ vring_pci_size()

static size_t vring_pci_size ( u16  num,
bool  packed 
)
static

Definition at line 245 of file VirtIOPCIModern.c.

246{
247 /* We only need a cacheline separation. */
249}
GLuint GLenum GLsizei GLsizei GLint GLint GLboolean packed
Definition: glext.h:9271
unsigned long vring_size(unsigned int num, unsigned long align, bool packed)
Definition: VirtIORing.c:555
#define ROUND_TO_PAGES(Size)

Referenced by vio_modern_query_vq_alloc(), and vio_modern_setup_vq().

Variable Documentation

◆ virtio_pci_device_ops

const struct virtio_device_ops virtio_pci_device_ops
static
Initial value:
= {
}
static u8 vio_modern_get_status(VirtIODevice *vdev)
static u32 vio_modern_get_generation(VirtIODevice *vdev)
static u64 vio_modern_get_features(VirtIODevice *vdev)
static u16 vio_modern_set_queue_vector(struct virtqueue *vq, u16 vector)
static u16 vio_modern_set_config_vector(VirtIODevice *vdev, u16 vector)
static void vio_modern_get_config(VirtIODevice *vdev, unsigned offset, void *buf, unsigned len)
static void vio_modern_reset(VirtIODevice *vdev)
static void vio_modern_del_vq(VirtIOQueueInfo *info)
static NTSTATUS vio_modern_setup_vq(struct virtqueue **queue, VirtIODevice *vdev, VirtIOQueueInfo *info, unsigned index, u16 msix_vec)
static void vio_modern_set_status(VirtIODevice *vdev, u8 status)
static void vio_modern_set_config(VirtIODevice *vdev, unsigned offset, const void *buf, unsigned len)
static NTSTATUS vio_modern_set_features(VirtIODevice *vdev, u64 features)

Definition at line 418 of file VirtIOPCIModern.c.

Referenced by vio_modern_initialize().