iPXE
virtio.c File Reference

Virtual I/O device. More...

#include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <ipxe/pci.h>
#include <ipxe/virtio.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static int virtio_legacy_reset (struct virtio_device *virtio)
 Reset device.
static unsigned int virtio_legacy_status (struct virtio_device *virtio)
 Report driver status.
static void virtio_legacy_supported (struct virtio_device *virtio)
 Get supported features.
static void virtio_legacy_negotiate (struct virtio_device *virtio)
 Negotiate device features.
static void virtio_legacy_size (struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
 Set queue size.
static void virtio_legacy_enable (struct virtio_device *virtio, struct virtio_queue *queue)
 Enable queue.
static int virtio_pci_reset (struct virtio_device *virtio)
 Reset device.
static unsigned int virtio_pci_status (struct virtio_device *virtio)
 Report driver status.
static void virtio_pci_supported (struct virtio_device *virtio)
 Get supported features.
static void virtio_pci_negotiate (struct virtio_device *virtio)
 Negotiate device features.
static void virtio_pci_size (struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
 Set queue size.
static void virtio_pci_address (struct virtio_device *virtio, struct virtio_queue *queue, void *addr, unsigned int offset)
 Program queue address.
static void virtio_pci_enable (struct virtio_device *virtio, struct virtio_queue *queue)
 Enable queue.
static int virtio_pci_cap (struct virtio_device *virtio, struct pci_device *pci, unsigned int type, struct virtio_pci_capability *cap)
 Find PCI capability.
static void * virtio_pci_map_cap (struct virtio_device *virtio, struct pci_device *pci, struct virtio_pci_capability *cap)
 Map PCI capability.
int virtio_pci_map (struct virtio_device *virtio, struct pci_device *pci)
 Map PCI device.
int virtio_reset (struct virtio_device *virtio)
 Reset device.
unsigned int virtio_status (struct virtio_device *virtio, unsigned int stat)
 Report driver status.
static void virtio_negotiate (struct virtio_device *virtio, const struct virtio_features *driver)
 Negotiate features.
int virtio_init (struct virtio_device *virtio, const struct virtio_features *driver)
 Initialise device.
int virtio_enable (struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
 Enable queue.
void virtio_free (struct virtio_device *virtio, struct virtio_queue *queue)
 Free queue.
void virtio_unmap (struct virtio_device *virtio)
 Unmap device.

Variables

static struct virtio_operations virtio_legacy_operations
 Original ("legacy") device operations.
static struct virtio_operations virtio_pci_operations
 PCI ("modern") device operations.

Detailed Description

Virtual I/O device.

Definition in file virtio.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ virtio_legacy_reset()

int virtio_legacy_reset ( struct virtio_device * virtio)
static

Reset device.

Parameters
virtioVirtio device
Return values
rcReturn status code

Definition at line 53 of file virtio.c.

53 {
55 unsigned int i;
56
57 /* Reset device */
58 iowrite8 ( 0, virtio->common + VIRTIO_LEG_STAT );
59
60 /* Wait for reset to complete */
61 for ( i = 0 ; i < VIRTIO_RESET_MAX_WAIT_MS ; i++ ) {
62 stat = ioread8 ( virtio->common + VIRTIO_LEG_STAT );
63 if ( ! stat )
64 return 0;
65 mdelay ( 1 );
66 }
67
68 DBGC ( virtio, "VIRTIO %s could not reset device\n", virtio->name );
69 return -ETIMEDOUT;
70}
unsigned char uint8_t
Definition stdint.h:10
uint32_t stat
Completion status.
Definition dwmac.h:1
#define DBGC(...)
Definition compiler.h:530
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define VIRTIO_LEG_STAT
Legacy driver status register.
Definition virtio.h:48
#define iowrite8(data, io_addr)
Definition io.h:370
#define ioread8(io_addr)
Definition io.h:340
const char * name
Device name.
Definition virtio.h:313
void * common
Common registers.
Definition virtio.h:319
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
#define VIRTIO_RESET_MAX_WAIT_MS
Maximum time to wait for reset (in ms).
Definition virtio.h:22

References virtio_device::common, DBGC, ETIMEDOUT, ioread8, iowrite8, mdelay(), virtio_device::name, stat, VIRTIO_LEG_STAT, and VIRTIO_RESET_MAX_WAIT_MS.

◆ virtio_legacy_status()

unsigned int virtio_legacy_status ( struct virtio_device * virtio)
static

Report driver status.

Parameters
virtioVirtio device
Return values
statActual device status

Definition at line 78 of file virtio.c.

78 {
79
80 /* Report device status */
81 iowrite8 ( virtio->stat, virtio->common + VIRTIO_LEG_STAT );
82
83 /* Read back device status */
84 return ioread8 ( virtio->common + VIRTIO_LEG_STAT );
85}
unsigned int stat
Driver status.
Definition virtio.h:325

References virtio_device::common, ioread8, iowrite8, virtio_device::stat, and VIRTIO_LEG_STAT.

◆ virtio_legacy_supported()

void virtio_legacy_supported ( struct virtio_device * virtio)
static

Get supported features.

Parameters
virtioVirtio device

Definition at line 92 of file virtio.c.

92 {
93 struct virtio_features *supported = &virtio->supported;
94 unsigned int i;
95
96 /* Get device supported features */
97 supported->word[0] = ioread32 ( virtio->common + VIRTIO_LEG_FEAT );
98
99 /* Legacy devices have only a single 32-bit feature register */
100 for ( i = 1 ; i < VIRTIO_FEATURE_WORDS ; i++ )
101 supported->word[i] = 0;
102}
uint16_t supported
Bitmask of supported option values.
Definition ena.h:1
#define VIRTIO_LEG_FEAT
Legacy device supported features register.
Definition virtio.h:30
#define ioread32(io_addr)
Definition io.h:360
struct virtio_features supported
Device supported features.
Definition virtio.h:327
A virtio feature set.
Definition virtio.h:299
#define VIRTIO_FEATURE_WORDS
Number of 32-bit feature words.
Definition virtio.h:296

References virtio_device::common, ioread32, supported, virtio_device::supported, VIRTIO_FEATURE_WORDS, and VIRTIO_LEG_FEAT.

◆ virtio_legacy_negotiate()

void virtio_legacy_negotiate ( struct virtio_device * virtio)
static

Negotiate device features.

Parameters
virtioVirtio device

Definition at line 109 of file virtio.c.

109 {
110 struct virtio_features *features = &virtio->features;
111 unsigned int i;
112
113 /* Set in-use features */
114 iowrite32 ( features->word[0], virtio->common + VIRTIO_LEG_USED );
115
116 /* Legacy devices have only a single 32-bit feature register */
117 for ( i = 1 ; i < VIRTIO_FEATURE_WORDS ; i++ )
118 assert ( features->word[i] == 0 );
119}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint32_t features
Supported features.
Definition ena.h:5
#define VIRTIO_LEG_USED
Legacy negotiated in-use features register.
Definition virtio.h:33
#define iowrite32(data, io_addr)
Definition io.h:390
struct virtio_features features
Negotiated features.
Definition virtio.h:329

References assert, virtio_device::common, features, virtio_device::features, iowrite32, VIRTIO_FEATURE_WORDS, and VIRTIO_LEG_USED.

◆ virtio_legacy_size()

void virtio_legacy_size ( struct virtio_device * virtio,
struct virtio_queue * queue,
unsigned int count )
static

Set queue size.

Parameters
virtioVirtio device
queueVirtio queue
countRequested size

Definition at line 128 of file virtio.c.

130 {
131 size_t len;
132
133 /* Select queue */
134 iowrite16 ( queue->index, virtio->common + VIRTIO_LEG_SEL );
135
136 /* Get (fixed) queue size */
137 count = ioread16 ( virtio->common + VIRTIO_LEG_SIZE );
138
139 /* Calculate queue length */
143
144 /* Record queue size */
145 queue->count = count;
146 queue->len = len;
147}
ring len
Length.
Definition dwmac.h:226
uint16_t queue
Queue ID.
Definition ena.h:11
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define VIRTIO_LEG_SEL
Legacy queue select register.
Definition virtio.h:42
#define VIRTIO_LEG_SIZE
Legacy queue size register.
Definition virtio.h:39
#define ioread16(io_addr)
Definition io.h:350
#define iowrite16(data, io_addr)
Definition io.h:380
static size_t virtio_align(size_t size)
Calculate aligned size.
Definition virtio.h:251
static size_t virtio_cq_size(unsigned int count)
Calculate (unaligned) completion queue size.
Definition virtio.h:289
static size_t virtio_sq_size(unsigned int count)
Calculate (unaligned) submission queue size.
Definition virtio.h:276
static size_t virtio_desc_size(unsigned int count)
Calculate (unaligned) descriptor array size.
Definition virtio.h:263

References virtio_device::common, count, ioread16, iowrite16, len, queue, virtio_align(), virtio_cq_size(), virtio_desc_size(), VIRTIO_LEG_SEL, VIRTIO_LEG_SIZE, and virtio_sq_size().

◆ virtio_legacy_enable()

void virtio_legacy_enable ( struct virtio_device * virtio,
struct virtio_queue * queue )
static

Enable queue.

Parameters
virtioVirtio device
queueVirtio queue

Definition at line 155 of file virtio.c.

156 {
157 unsigned int count = queue->count;
158 void *base = queue->desc;
159 size_t len;
160
161 /* Select queue */
162 iowrite16 ( queue->index, virtio->common + VIRTIO_LEG_SEL );
163
164 /* Lay out queue regions */
166 queue->sq = ( base + len );
168 queue->cq = ( base + len );
170 assert ( len == queue->len );
171
172 /* Program queue base page address */
173 iowrite32 ( ( dma ( &queue->map, queue->desc ) / VIRTIO_PAGE ),
174 virtio->common + VIRTIO_LEG_BASE );
175}
#define VIRTIO_LEG_BASE
Legacy queue base address register.
Definition virtio.h:36
physaddr_t dma(struct dma_mapping *map, void *addr)
Get DMA address from virtual address.
uint32_t base
Base.
Definition librm.h:3
#define VIRTIO_PAGE
Virtio page alignment.
Definition virtio.h:19

References assert, base, virtio_device::common, count, dma(), iowrite16, iowrite32, len, queue, virtio_align(), virtio_cq_size(), virtio_desc_size(), VIRTIO_LEG_BASE, VIRTIO_LEG_SEL, VIRTIO_PAGE, and virtio_sq_size().

◆ virtio_pci_reset()

int virtio_pci_reset ( struct virtio_device * virtio)
static

Reset device.

Parameters
virtioVirtio device
Return values
rcReturn status code

Definition at line 200 of file virtio.c.

200 {
202 unsigned int i;
203
204 /* Reset device */
205 iowrite8 ( 0, virtio->common + VIRTIO_PCI_STAT );
206
207 /* Wait for reset to complete */
208 for ( i = 0 ; i < VIRTIO_RESET_MAX_WAIT_MS ; i++ ) {
209 stat = ioread8 ( virtio->common + VIRTIO_PCI_STAT );
210 if ( ! stat )
211 return 0;
212 mdelay ( 1 );
213 }
214
215 DBGC ( virtio, "VIRTIO %s could not reset device\n", virtio->name );
216 return -ETIMEDOUT;
217}
#define VIRTIO_PCI_STAT
PCI device status register.
Definition virtio.h:123

References virtio_device::common, DBGC, ETIMEDOUT, ioread8, iowrite8, mdelay(), virtio_device::name, stat, VIRTIO_PCI_STAT, and VIRTIO_RESET_MAX_WAIT_MS.

◆ virtio_pci_status()

unsigned int virtio_pci_status ( struct virtio_device * virtio)
static

Report driver status.

Parameters
virtioVirtio device
Return values
statActual device status

Definition at line 225 of file virtio.c.

225 {
226
227 /* Report device status */
228 iowrite8 ( virtio->stat, virtio->common + VIRTIO_PCI_STAT );
229
230 /* Read back device status */
231 return ioread8 ( virtio->common + VIRTIO_PCI_STAT );
232}

References virtio_device::common, ioread8, iowrite8, virtio_device::stat, and VIRTIO_PCI_STAT.

◆ virtio_pci_supported()

void virtio_pci_supported ( struct virtio_device * virtio)
static

Get supported features.

Parameters
virtioVirtio device

Definition at line 239 of file virtio.c.

239 {
240 struct virtio_features *supported = &virtio->supported;
241 unsigned int i;
242
243 /* Get device supported features */
244 for ( i = 0 ; i < VIRTIO_FEATURE_WORDS ; i++ ) {
245 iowrite32 ( i, virtio->common + VIRTIO_PCI_FEAT_SEL );
246 supported->word[i] =
247 ioread32 ( virtio->common + VIRTIO_PCI_FEAT );
248 }
249}
#define VIRTIO_PCI_FEAT
PCI device supported features register.
Definition virtio.h:114
#define VIRTIO_PCI_FEAT_SEL
PCI device supported features select register.
Definition virtio.h:111

References virtio_device::common, ioread32, iowrite32, supported, virtio_device::supported, VIRTIO_FEATURE_WORDS, VIRTIO_PCI_FEAT, and VIRTIO_PCI_FEAT_SEL.

◆ virtio_pci_negotiate()

void virtio_pci_negotiate ( struct virtio_device * virtio)
static

Negotiate device features.

Parameters
virtioVirtio device

Definition at line 256 of file virtio.c.

256 {
257 struct virtio_features *features = &virtio->features;
258 unsigned int i;
259
260 /* Set in-use features */
261 for ( i = 0 ; i < VIRTIO_FEATURE_WORDS ; i++ ) {
262 iowrite32 ( i, virtio->common + VIRTIO_PCI_USED_SEL );
263 iowrite32 ( features->word[i],
264 virtio->common + VIRTIO_PCI_USED );
265 }
266}
#define VIRTIO_PCI_USED_SEL
PCI negotiated in-use features select register.
Definition virtio.h:117
#define VIRTIO_PCI_USED
PCI negotiated in-use features register.
Definition virtio.h:120

References virtio_device::common, features, virtio_device::features, iowrite32, VIRTIO_FEATURE_WORDS, VIRTIO_PCI_USED, and VIRTIO_PCI_USED_SEL.

◆ virtio_pci_size()

void virtio_pci_size ( struct virtio_device * virtio,
struct virtio_queue * queue,
unsigned int count )
static

Set queue size.

Parameters
virtioVirtio device
queueVirtio queue
countRequested size

Definition at line 275 of file virtio.c.

277 {
278 unsigned int max;
279 size_t len;
280
281 /* Select queue */
282 iowrite16 ( queue->index, virtio->common + VIRTIO_PCI_SEL );
283
284 /* Set queue size */
285 max = ioread16 ( virtio->common + VIRTIO_PCI_SIZE );
286 if ( count > max )
287 count = max;
288 iowrite16 ( count, virtio->common + VIRTIO_PCI_SIZE );
289
290 /* Calculate queue length */
294
295 /* Record queue size */
296 queue->count = count;
297 queue->len = len;
298}
#define max(x, y)
Definition ath.h:41
#define VIRTIO_PCI_SEL
PCI queue select register.
Definition virtio.h:129
#define VIRTIO_PCI_SIZE
PCI queue size register.
Definition virtio.h:132

References virtio_device::common, count, ioread16, iowrite16, len, max, queue, virtio_align(), virtio_cq_size(), virtio_desc_size(), VIRTIO_PCI_SEL, VIRTIO_PCI_SIZE, and virtio_sq_size().

◆ virtio_pci_address()

void virtio_pci_address ( struct virtio_device * virtio,
struct virtio_queue * queue,
void * addr,
unsigned int offset )
static

Program queue address.

Parameters
virtioVirtio device
queueVirtio queue
addrAddress
offsetRegister offset

Definition at line 308 of file virtio.c.

310 {
312
313 /* Program address */
314 phys = dma ( &queue->map, addr );
315 iowrite32 ( ( phys & 0xffffffffUL ), ( virtio->common + offset + 0 ) );
316 if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
317 iowrite32 ( ( ( ( uint64_t ) phys ) >> 32 ),
318 ( virtio->common + offset + 4 ) );
319 } else {
320 iowrite32 ( 0, ( virtio->common + offset + 4 ) );
321 }
322}
unsigned int uint32_t
Definition stdint.h:12
unsigned long physaddr_t
Definition stdint.h:20
unsigned long long uint64_t
Definition stdint.h:13
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint32_t addr
Buffer address.
Definition dwmac.h:9
static signed char phys[4]
Definition epic100.c:88

References addr, virtio_device::common, dma(), iowrite32, offset, phys, and queue.

Referenced by virtio_pci_enable().

◆ virtio_pci_enable()

void virtio_pci_enable ( struct virtio_device * virtio,
struct virtio_queue * queue )
static

Enable queue.

Parameters
virtioVirtio device
queueVirtio queue

Definition at line 330 of file virtio.c.

331 {
332 unsigned int count = queue->count;
333 void *base = queue->desc;
334 size_t len;
335
336 /* Select queue */
337 iowrite16 ( queue->index, virtio->common + VIRTIO_PCI_SEL );
338
339 /* Lay out queue regions */
341 queue->sq = ( base + len );
343 queue->cq = ( base + len );
345 assert ( len == queue->len );
346
347 /* Program queue addresses */
348 virtio_pci_address ( virtio, queue, queue->desc, VIRTIO_PCI_DESC );
351
352 /* Enable queue */
353 iowrite16 ( 1, virtio->common + VIRTIO_PCI_ENABLE );
354}
#define VIRTIO_PCI_DESC
PCI queue descriptor array base address register.
Definition virtio.h:141
#define VIRTIO_PCI_CQ
PCI queue completion queue base address register.
Definition virtio.h:147
#define VIRTIO_PCI_SQ
PCI queue submission queue base address register.
Definition virtio.h:144
#define VIRTIO_PCI_ENABLE
PCI queue enable register.
Definition virtio.h:135
static void virtio_pci_address(struct virtio_device *virtio, struct virtio_queue *queue, void *addr, unsigned int offset)
Program queue address.
Definition virtio.c:308

References assert, base, virtio_device::common, count, iowrite16, len, queue, virtio_align(), virtio_cq_size(), virtio_desc_size(), virtio_pci_address(), VIRTIO_PCI_CQ, VIRTIO_PCI_DESC, VIRTIO_PCI_ENABLE, VIRTIO_PCI_SEL, VIRTIO_PCI_SQ, and virtio_sq_size().

◆ virtio_pci_cap()

int virtio_pci_cap ( struct virtio_device * virtio,
struct pci_device * pci,
unsigned int type,
struct virtio_pci_capability * cap )
static

Find PCI capability.

Parameters
virtioVirtio device
pciPCI device
typeCapability type
capVirtio PCI capability to fill in
Return values
rcReturn status code

Definition at line 375 of file virtio.c.

377 {
378 unsigned int reg;
379 int pos;
380
381 /* Scan through vendor capabilities */
382 for ( pos = pci_find_capability ( pci, PCI_CAP_ID_VNDR ) ; pos > 0 ;
383 pos = pci_find_next_capability ( pci, pos, PCI_CAP_ID_VNDR ) ) {
384
385 /* Check length */
386 pci_read_config_byte ( pci, ( pos + PCI_CAP_LEN ), &cap->len );
387 if ( cap->len < VIRTIO_PCI_CAP_END ) {
388 DBGC ( virtio, "VIRTIO %s capability +%#02x too short "
389 "(%d bytes)\n", virtio->name, pos, cap->len );
390 continue;
391 }
392
393 /* Read values */
395 &cap->type );
397 &cap->bar );
399 &cap->offset );
400
401 /* Check type */
402 if ( cap->type != type )
403 continue;
404 DBGC2 ( virtio, "VIRTIO %s capability type %d BAR%d+%#04x\n",
405 virtio->name, type, cap->bar, cap->offset );
406
407 /* Check BAR */
408 reg = PCI_BASE_ADDRESS ( cap->bar );
409 if ( reg > PCI_BASE_ADDRESS_5 )
410 continue;
411
412 /* Check BAR accessibility */
413 if ( ! pci_bar_start ( pci, reg ) ) {
414 DBGC ( virtio, "VIRTIO %s capability type %d BAR%d is "
415 "not usable\n", virtio->name, type, cap->bar );
416 continue;
417 }
418
419 /* Success */
420 cap->pos = pos;
421 return 0;
422 }
423
424 DBGC ( virtio, "VIRTIO %s has no usable capability type %d\n",
425 virtio->name, type );
426 cap->pos = 0;
427 return -ENOENT;
428}
uint32_t type
Operating system type.
Definition ena.h:1
#define DBGC2(...)
Definition compiler.h:547
#define ENOENT
No such file or directory.
Definition errno.h:515
#define VIRTIO_PCI_CAP_BAR
Capability BAR index.
Definition virtio.h:75
#define VIRTIO_PCI_CAP_OFFSET
Capability BAR offset.
Definition virtio.h:78
#define VIRTIO_PCI_CAP_END
Capability minimum length.
Definition virtio.h:81
#define VIRTIO_PCI_CAP_TYPE
Capability type.
Definition virtio.h:69
int pci_read_config_dword(struct pci_device *pci, unsigned int where, uint32_t *value)
Read 32-bit dword from PCI configuration space.
int pci_read_config_byte(struct pci_device *pci, unsigned int where, uint8_t *value)
Read byte from PCI configuration space.
static unsigned int unsigned int reg
Definition myson.h:162
unsigned long pci_bar_start(struct pci_device *pci, unsigned int reg)
Find the start of a PCI BAR.
Definition pci.c:111
#define PCI_CAP_ID_VNDR
Vendor-specific.
Definition pci.h:97
#define PCI_CAP_LEN
Capability length.
Definition pci.h:106
#define PCI_BASE_ADDRESS(n)
PCI base address registers.
Definition pci.h:62
#define PCI_BASE_ADDRESS_5
Definition pci.h:68
int pci_find_next_capability(struct pci_device *pci, int pos, int cap)
Look for another PCI capability.
Definition pciextra.c:76
int pci_find_capability(struct pci_device *pci, int cap)
Look for a PCI capability.
Definition pciextra.c:39
uint32_t offset
Offset within BAR.
Definition virtio.h:102
uint8_t type
Capability type.
Definition virtio.h:94
uint8_t len
Capability length.
Definition virtio.h:98
uint8_t pos
Capability offset.
Definition virtio.h:96
uint8_t bar
BAR number.
Definition virtio.h:100

References virtio_pci_capability::bar, DBGC, DBGC2, ENOENT, virtio_pci_capability::len, virtio_device::name, virtio_pci_capability::offset, pci_bar_start(), PCI_BASE_ADDRESS, PCI_BASE_ADDRESS_5, PCI_CAP_ID_VNDR, PCI_CAP_LEN, pci_find_capability(), pci_find_next_capability(), pci_read_config_byte(), pci_read_config_dword(), virtio_pci_capability::pos, reg, type, virtio_pci_capability::type, VIRTIO_PCI_CAP_BAR, VIRTIO_PCI_CAP_END, VIRTIO_PCI_CAP_OFFSET, and VIRTIO_PCI_CAP_TYPE.

Referenced by virtio_pci_map().

◆ virtio_pci_map_cap()

void * virtio_pci_map_cap ( struct virtio_device * virtio,
struct pci_device * pci,
struct virtio_pci_capability * cap )
static

Map PCI capability.

Parameters
virtioVirtio device
pciPCI device
capVirtio PCI capability
Return values
io_addrI/O address, or NULL on error

Definition at line 438 of file virtio.c.

440 {
441 unsigned long addr;
442 unsigned int reg;
443 int is_io_bar;
444 void *io_addr;
445
446 /* Get BAR start address and type */
447 reg = PCI_BASE_ADDRESS ( cap->bar );
448 addr = pci_bar_start ( pci, reg );
449 if ( ! addr ) {
450 DBGC ( virtio, "VIRTIO %s BAR%d is not usable\n",
451 virtio->name, cap->bar );
452 return NULL;
453 }
454
455 /* Map memory or I/O BAR */
456 addr += cap->offset;
457 is_io_bar = pci_bar_is_io ( pci, reg );
458 io_addr = ( is_io_bar ? ( ( void * ) addr ) :
459 pci_ioremap ( pci, addr, VIRTIO_PAGE ) );
460 if ( ! io_addr ) {
461 DBGC ( virtio, "VIRTIO %s could not map BAR%d+%#04x\n",
462 virtio->name, cap->bar, cap->offset );
463 return NULL;
464 }
465
466 DBGC2 ( virtio, "VIRTIO %s mapped BAR%d+%#04x (%s %#08lx)\n",
467 virtio->name, cap->bar, cap->offset,
468 ( is_io_bar ? "IO" : "MEM" ), addr );
469 return io_addr;
470}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
void * pci_ioremap(struct pci_device *pci, unsigned long bus_addr, size_t len)
Map PCI bus address as an I/O address.
int pci_bar_is_io(struct pci_device *pci, unsigned int reg)
Get PCI BAR type.
Definition pci.c:90

References addr, virtio_pci_capability::bar, DBGC, DBGC2, virtio_device::name, NULL, virtio_pci_capability::offset, pci_bar_is_io(), pci_bar_start(), PCI_BASE_ADDRESS, pci_ioremap(), reg, and VIRTIO_PAGE.

Referenced by virtio_pci_map().

◆ virtio_pci_map()

int virtio_pci_map ( struct virtio_device * virtio,
struct pci_device * pci )

Map PCI device.

Parameters
virtioVirtio device
pciPCI device
Return values
rcReturn status code

Definition at line 479 of file virtio.c.

479 {
481 struct virtio_pci_capability notify;
483 unsigned int msix;
484 uint32_t mult;
486 int rc;
487
488 /* Initialise device */
489 virtio->name = pci->dev.name;
490 virtio->dma = &pci->dma;
491
492 /* Fix up PCI device */
493 adjust_pci_device ( pci );
494
495 /* Check if MSI-X is enabled */
496 msix = pci_find_capability ( pci, PCI_CAP_ID_MSIX );
497 if ( msix ) {
498 pci_read_config_word ( pci, msix, &ctrl );
499 if ( ! ( ctrl & PCI_MSIX_CTRL_ENABLE ) )
500 msix = 0;
501 }
502
503 /* Locate virtio capabilities */
505 virtio_pci_cap ( virtio, pci, VIRTIO_PCI_CAP_TYPE_NOTIFY, &notify );
507
508 /* Use modern interface if available */
509 if ( common.pos && notify.pos && device.pos &&
510 ( notify.len >= VIRTIO_PCI_CAP_NOTIFY_END ) ) {
511
512 /* Use modern interface */
513 virtio->op = &virtio_pci_operations;
514 dma_set_mask_64bit ( virtio->dma );
515
516 /* Read notification doorbell multiplier */
517 pci_read_config_dword ( pci, ( notify.pos +
519 &mult );
520 virtio->multiplier = mult;
521 DBGC ( virtio, "VIRTIO %s using modern interface (mult x%d)\n",
522 virtio->name, virtio->multiplier );
523
524 } else {
525
526 /* Use legacy interface */
527 virtio->op = &virtio_legacy_operations;
528 common.bar = 0;
529 common.offset = 0;
530 notify.bar = 0;
531 notify.offset = VIRTIO_LEG_DB;
532 device.bar = 0;
533 device.offset = ( msix ? VIRTIO_LEG_DEV_MSIX :
535 DBGC ( virtio, "VIRTIO %s using legacy interface (MSI-X "
536 "%sabled)\n", virtio->name, ( msix ? "en" : "dis" ) );
537 }
538
539 /* Map registers */
540 virtio->common = virtio_pci_map_cap ( virtio, pci, &common );
541 if ( ! virtio->common ) {
542 rc = -ENODEV;
543 goto err_common;
544 }
545 virtio->notify = virtio_pci_map_cap ( virtio, pci, &notify );
546 if ( ! virtio->notify ) {
547 rc = -ENODEV;
548 goto err_notify;
549 }
550 virtio->device = virtio_pci_map_cap ( virtio, pci, &device );
551 if ( ! virtio->device ) {
552 rc = -ENODEV;
553 goto err_device;
554 }
555
556 return 0;
557
558 iounmap ( virtio->device );
559 err_device:
560 iounmap ( virtio->notify );
561 err_notify:
562 iounmap ( virtio->common );
563 err_common:
564 return rc;
565}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
uint8_t ctrl
Ring control.
Definition dwmac.h:7
#define ENODEV
No such device.
Definition errno.h:510
#define VIRTIO_LEG_DEV_MSIX
Legacy device-specific register (if MSI-X is enabled).
Definition virtio.h:59
#define VIRTIO_LEG_DB
Legacy queue doorbell notification register.
Definition virtio.h:45
#define VIRTIO_LEG_DEV
Legacy device-specific registers.
Definition virtio.h:56
#define VIRTIO_PCI_CAP_NOTIFY_END
Notification doorbell capability minimum length.
Definition virtio.h:87
#define VIRTIO_PCI_CAP_TYPE_NOTIFY
Notification doorbells.
Definition virtio.h:71
#define VIRTIO_PCI_CAP_NOTIFY_MULT
Notification doorbell capability multiplier offset.
Definition virtio.h:84
#define VIRTIO_PCI_CAP_TYPE_DEVICE
Device-specific registers.
Definition virtio.h:72
#define VIRTIO_PCI_CAP_TYPE_COMMON
Common registers.
Definition virtio.h:70
struct ib_cm_common common
Definition ib_mad.h:0
void iounmap(volatile const void *io_addr)
Unmap I/O address.
int pci_read_config_word(struct pci_device *pci, unsigned int where, uint16_t *value)
Read 16-bit word from PCI configuration space.
static __always_inline void dma_set_mask_64bit(struct dma_device *dma)
Set 64-bit addressable space mask.
Definition dma.h:467
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
Definition pci.c:255
#define PCI_MSIX_CTRL_ENABLE
Enable MSI-X.
Definition pci.h:120
#define PCI_CAP_ID_MSIX
MSI-X.
Definition pci.h:99
A hardware device.
Definition device.h:77
char name[40]
Name.
Definition device.h:79
struct device dev
Generic device.
Definition pci.h:216
struct dma_device dma
DMA device.
Definition pci.h:218
unsigned int multiplier
Notification doorbell multiplier.
Definition virtio.h:331
void * notify
Doorbell notification registers.
Definition virtio.h:321
void * device
Device-specific registers.
Definition virtio.h:323
struct virtio_operations * op
Device operations.
Definition virtio.h:315
struct dma_device * dma
DMA device.
Definition virtio.h:317
A virtio PCI capability.
Definition virtio.h:92
static struct virtio_operations virtio_pci_operations
PCI ("modern") device operations.
Definition virtio.c:357
static int virtio_pci_cap(struct virtio_device *virtio, struct pci_device *pci, unsigned int type, struct virtio_pci_capability *cap)
Find PCI capability.
Definition virtio.c:375
static void * virtio_pci_map_cap(struct virtio_device *virtio, struct pci_device *pci, struct virtio_pci_capability *cap)
Map PCI capability.
Definition virtio.c:438
static struct virtio_operations virtio_legacy_operations
Original ("legacy") device operations.
Definition virtio.c:178

References adjust_pci_device(), virtio_pci_capability::bar, common, virtio_device::common, ctrl, DBGC, pci_device::dev, virtio_device::device, pci_device::dma, virtio_device::dma, dma_set_mask_64bit(), ENODEV, iounmap(), virtio_pci_capability::len, virtio_device::multiplier, device::name, virtio_device::name, virtio_device::notify, virtio_pci_capability::offset, virtio_device::op, PCI_CAP_ID_MSIX, pci_find_capability(), PCI_MSIX_CTRL_ENABLE, pci_read_config_dword(), pci_read_config_word(), virtio_pci_capability::pos, rc, VIRTIO_LEG_DB, VIRTIO_LEG_DEV, VIRTIO_LEG_DEV_MSIX, virtio_legacy_operations, virtio_pci_cap(), VIRTIO_PCI_CAP_NOTIFY_END, VIRTIO_PCI_CAP_NOTIFY_MULT, VIRTIO_PCI_CAP_TYPE_COMMON, VIRTIO_PCI_CAP_TYPE_DEVICE, VIRTIO_PCI_CAP_TYPE_NOTIFY, virtio_pci_map_cap(), and virtio_pci_operations.

Referenced by virtio_net_probe().

◆ virtio_reset()

int virtio_reset ( struct virtio_device * virtio)

Reset device.

Parameters
virtioVirtio device
Return values
rcReturn status code

Definition at line 580 of file virtio.c.

580 {
581 int rc;
582
583 /* Clear driver status */
584 virtio->stat = 0;
585
586 /* Reset device */
587 if ( ( rc = virtio->op->reset ( virtio ) ) != 0 ) {
588 DBGC ( virtio, "VIRTIO %s could not reset: %s\n",
589 virtio->name, strerror ( rc ) );
590 return rc;
591 }
592
593 return 0;
594}
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int(* reset)(struct virtio_device *virtio)
Reset device.
Definition virtio.h:342

References DBGC, virtio_device::name, virtio_device::op, rc, virtio_operations::reset, virtio_device::stat, and strerror().

Referenced by virtio_init(), virtio_net_close(), virtio_net_open(), virtio_net_probe(), and virtio_net_remove().

◆ virtio_status()

unsigned int virtio_status ( struct virtio_device * virtio,
unsigned int stat )

Report driver status.

Parameters
virtioVirtio device
statAdditional driver status bits
Return values
statActual device status

Definition at line 603 of file virtio.c.

604 {
605
606 /* Set new driver status bits */
607 virtio->stat |= stat;
608
609 /* Report driver status */
610 return virtio->op->status ( virtio );
611}
unsigned int(* status)(struct virtio_device *virtio)
Report driver status.
Definition virtio.h:349

References virtio_device::op, stat, virtio_device::stat, and virtio_operations::status.

Referenced by virtio_init(), and virtio_net_open().

◆ virtio_negotiate()

void virtio_negotiate ( struct virtio_device * virtio,
const struct virtio_features * driver )
static

Negotiate features.

Parameters
virtioVirtio device
driverDriver supported features

Definition at line 619 of file virtio.c.

620 {
621 struct virtio_features *device = &virtio->supported;
622 struct virtio_features *features = &virtio->features;
623 unsigned int i;
624
625 /* Get device supported features */
626 virtio->op->supported ( virtio );
627
628 /* Negotiate mutually supported features */
629 for ( i = 0 ; i < VIRTIO_FEATURE_WORDS ; i++ )
630 features->word[i] = ( device->word[i] & driver->word[i] );
631 virtio->op->negotiate ( virtio );
632
633 /* Show features */
634 DBGC ( virtio, "VIRTIO %s features", virtio->name );
635 for ( i = 0 ; i < VIRTIO_FEATURE_WORDS ; i++ )
636 DBGC ( virtio, "%s%08x", ( i ? ":" : " " ), device->word[i] );
637 DBGC ( virtio, " /" );
638 for ( i = 0 ; i < VIRTIO_FEATURE_WORDS ; i++ )
639 DBGC ( virtio, "%s%08x", ( i ? ":" : " " ), features->word[i] );
640 DBGC ( virtio, "\n" );
641}
uint32_t word[VIRTIO_FEATURE_WORDS]
Feature words.
Definition virtio.h:301
void(* negotiate)(struct virtio_device *virtio)
Set negotiated features.
Definition virtio.h:361
void(* supported)(struct virtio_device *virtio)
Get supported features.
Definition virtio.h:355

References DBGC, features, virtio_device::features, virtio_device::name, virtio_operations::negotiate, virtio_device::op, virtio_device::supported, virtio_operations::supported, VIRTIO_FEATURE_WORDS, and virtio_features::word.

Referenced by virtio_init().

◆ virtio_init()

int virtio_init ( struct virtio_device * virtio,
const struct virtio_features * driver )

Initialise device.

Parameters
virtioVirtio device
driverDriver supported features
Return values
rcReturn status code

Definition at line 650 of file virtio.c.

651 {
652 unsigned int stat;
653 int rc;
654
655 /* Reset device */
656 if ( ( rc = virtio_reset ( virtio ) ) != 0 )
657 goto err_reset;
658
659 /* Acknowledge device existence */
661
662 /* Report driver existence */
664
665 /* Negotiate features */
666 virtio_negotiate ( virtio, driver );
667
668 /* Report feature negotiation completion, if applicable */
669 if ( virtio->features.word[1] & VIRTIO_FEAT1_MODERN ) {
671 if ( ! ( stat & VIRTIO_STAT_FEATURES_OK ) ) {
672 DBGC ( virtio, "VIRTIO %s did not accept features\n",
673 virtio->name );
674 rc = -ENOTSUP;
675 goto err_features;
676 }
677 }
678
679 return 0;
680
681 err_features:
682 virtio_reset ( virtio );
683 err_reset:
685 return rc;
686}
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define VIRTIO_STAT_FEATURES_OK
Guest driver has set features.
Definition virtio.h:52
#define VIRTIO_STAT_ACKNOWLEDGE
Guest has found device.
Definition virtio.h:49
#define VIRTIO_STAT_FAIL
Guest driver has failed.
Definition virtio.h:53
#define VIRTIO_STAT_DRIVER
Guest driver exists.
Definition virtio.h:50
unsigned int virtio_status(struct virtio_device *virtio, unsigned int stat)
Report driver status.
Definition virtio.c:603
int virtio_reset(struct virtio_device *virtio)
Reset device.
Definition virtio.c:580
static void virtio_negotiate(struct virtio_device *virtio, const struct virtio_features *driver)
Negotiate features.
Definition virtio.c:619
#define VIRTIO_FEAT1_MODERN
Virtio version 1.0 or above.
Definition virtio.h:308

References DBGC, ENOTSUP, virtio_device::features, virtio_device::name, rc, stat, VIRTIO_FEAT1_MODERN, virtio_negotiate(), virtio_reset(), VIRTIO_STAT_ACKNOWLEDGE, VIRTIO_STAT_DRIVER, VIRTIO_STAT_FAIL, VIRTIO_STAT_FEATURES_OK, virtio_status(), and virtio_features::word.

Referenced by virtio_net_open(), and virtio_net_probe().

◆ virtio_enable()

int virtio_enable ( struct virtio_device * virtio,
struct virtio_queue * queue,
unsigned int count )

Enable queue.

Parameters
virtioVirtio device
queueVirtio queue
countRequested queue size
Return values
rcReturn status code

Definition at line 696 of file virtio.c.

697 {
698 unsigned int offset;
699 int rc;
700
701 /* Reset counters */
702 queue->prod = 0;
703 queue->cons = 0;
704
705 /* Determine queue size */
706 virtio->op->size ( virtio, queue, count );
707 if ( ( queue->count == 0 ) ||
708 ( queue->count & ( queue->count - 1 ) ) ) {
709 DBGC ( virtio, "VIRTIO %s Q%d invalid size %d\n",
710 virtio->name, queue->index, queue->count );
711 rc = -ENODEV;
712 goto err_count;
713 }
714 queue->mask = ( queue->count - 1 );
715
716 /* Allocate and initialise queue */
717 queue->desc = dma_alloc ( virtio->dma, &queue->map, queue->len,
718 VIRTIO_PAGE );
719 if ( ! queue->desc ) {
720 rc = -ENOMEM;
721 goto err_alloc;
722 }
723 memset ( queue->desc, 0, queue->len );
724
725 /* Enable queue */
726 virtio->op->enable ( virtio, queue );
727 DBGC ( virtio, "VIRTIO %s Q%d %dx descriptors at [%#08lx,%#08lx)\n",
728 virtio->name, queue->index, queue->count,
729 virt_to_phys ( queue->desc ),
730 ( virt_to_phys ( queue->desc ) +
731 virtio_desc_size ( queue->count ) ) );
732 DBGC ( virtio, "VIRTIO %s Q%d %dx submissions at [%#08lx,%#08lx)\n",
733 virtio->name, queue->index, queue->count,
734 virt_to_phys ( queue->sq ),
735 ( virt_to_phys ( queue->sq ) +
736 virtio_sq_size ( queue->count ) ) );
737 DBGC ( virtio, "VIRTIO %s Q%d %dx completions at [%#08lx,%#08lx)\n",
738 virtio->name, queue->index, queue->count,
739 virt_to_phys ( queue->cq ),
740 ( virt_to_phys ( queue->cq ) +
741 virtio_cq_size ( queue->count ) ) );
742
743 /* Calculate doorbell register address */
744 offset = ( queue->index * virtio->multiplier );
745 queue->db = ( virtio->notify + offset );
746 DBGC ( virtio, "VIRTIO %s Q%d doorbell at +%#04x\n",
747 virtio->name, queue->index, offset );
748
749 return 0;
750
751 dma_free ( &queue->map, queue->desc, queue->len );
752 queue->desc = NULL;
753 err_alloc:
754 err_count:
755 return rc;
756}
#define ENOMEM
Not enough space.
Definition errno.h:535
void * memset(void *dest, int character, size_t len) __nonnull
void dma_free(struct dma_mapping *map, void *addr, size_t len)
Unmap and free DMA-coherent buffer.
void * dma_alloc(struct dma_device *dma, struct dma_mapping *map, size_t len, size_t align)
Allocate and map DMA-coherent buffer.
void(* enable)(struct virtio_device *virtio, struct virtio_queue *queue)
Enable queue.
Definition virtio.h:377
void(* size)(struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
Set queue size.
Definition virtio.h:369

References count, DBGC, virtio_device::dma, dma_alloc(), dma_free(), virtio_operations::enable, ENODEV, ENOMEM, memset(), virtio_device::multiplier, virtio_device::name, virtio_device::notify, NULL, offset, virtio_device::op, queue, rc, virtio_operations::size, virtio_cq_size(), virtio_desc_size(), VIRTIO_PAGE, and virtio_sq_size().

Referenced by virtio_net_enable().

◆ virtio_free()

void virtio_free ( struct virtio_device * virtio,
struct virtio_queue * queue )

Free queue.

Parameters
virtioVirtio device
queueVirtio queue

Definition at line 764 of file virtio.c.

764 {
765
766 /* Free queue */
767 if ( queue->desc ) {
768 dma_free ( &queue->map, queue->desc, queue->len );
769 queue->desc = NULL;
770 DBGC ( virtio, "VIRTIO %s Q%d freed\n",
771 virtio->name, queue->index );
772 }
773}

References DBGC, dma_free(), virtio_device::name, NULL, and queue.

Referenced by virtio_net_close(), and virtio_net_open().

◆ virtio_unmap()

void virtio_unmap ( struct virtio_device * virtio)

Unmap device.

Parameters
virtioVirtio device

Definition at line 780 of file virtio.c.

780 {
781
782 /* Unmap device-specific registers */
783 iounmap ( virtio->device );
784
785 /* Unmap notification doorbells */
786 iounmap ( virtio->notify );
787
788 /* Unmap common registers */
789 iounmap ( virtio->common );
790}

References virtio_device::common, virtio_device::device, iounmap(), and virtio_device::notify.

Referenced by virtio_net_probe(), and virtio_net_remove().

Variable Documentation

◆ virtio_legacy_operations

struct virtio_operations virtio_legacy_operations
static
Initial value:
= {
}
static int virtio_legacy_reset(struct virtio_device *virtio)
Reset device.
Definition virtio.c:53
static void virtio_legacy_supported(struct virtio_device *virtio)
Get supported features.
Definition virtio.c:92
static void virtio_legacy_negotiate(struct virtio_device *virtio)
Negotiate device features.
Definition virtio.c:109
static unsigned int virtio_legacy_status(struct virtio_device *virtio)
Report driver status.
Definition virtio.c:78
static void virtio_legacy_size(struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
Set queue size.
Definition virtio.c:128
static void virtio_legacy_enable(struct virtio_device *virtio, struct virtio_queue *queue)
Enable queue.
Definition virtio.c:155

Original ("legacy") device operations.

Definition at line 178 of file virtio.c.

178 {
179 .reset = virtio_legacy_reset,
180 .status = virtio_legacy_status,
181 .supported = virtio_legacy_supported,
182 .negotiate = virtio_legacy_negotiate,
183 .size = virtio_legacy_size,
184 .enable = virtio_legacy_enable,
185};

Referenced by virtio_pci_map().

◆ virtio_pci_operations

struct virtio_operations virtio_pci_operations
static
Initial value:
= {
.reset = virtio_pci_reset,
.status = virtio_pci_status,
.supported = virtio_pci_supported,
.negotiate = virtio_pci_negotiate,
.size = virtio_pci_size,
.enable = virtio_pci_enable,
}
static unsigned int virtio_pci_status(struct virtio_device *virtio)
Report driver status.
Definition virtio.c:225
static void virtio_pci_size(struct virtio_device *virtio, struct virtio_queue *queue, unsigned int count)
Set queue size.
Definition virtio.c:275
static int virtio_pci_reset(struct virtio_device *virtio)
Reset device.
Definition virtio.c:200
static void virtio_pci_enable(struct virtio_device *virtio, struct virtio_queue *queue)
Enable queue.
Definition virtio.c:330
static void virtio_pci_supported(struct virtio_device *virtio)
Get supported features.
Definition virtio.c:239
static void virtio_pci_negotiate(struct virtio_device *virtio)
Negotiate device features.
Definition virtio.c:256

PCI ("modern") device operations.

Definition at line 357 of file virtio.c.

357 {
358 .reset = virtio_pci_reset,
359 .status = virtio_pci_status,
360 .supported = virtio_pci_supported,
361 .negotiate = virtio_pci_negotiate,
362 .size = virtio_pci_size,
363 .enable = virtio_pci_enable,
364};

Referenced by virtio_pci_map().