diff options
Diffstat (limited to 'src/include/gpxe')
| -rw-r--r-- | src/include/gpxe/virtio-pci.h | 94 | ||||
| -rw-r--r-- | src/include/gpxe/virtio-ring.h | 93 |
2 files changed, 187 insertions, 0 deletions
diff --git a/src/include/gpxe/virtio-pci.h b/src/include/gpxe/virtio-pci.h new file mode 100644 index 000000000..ba0604d52 --- /dev/null +++ b/src/include/gpxe/virtio-pci.h @@ -0,0 +1,94 @@ +#ifndef _VIRTIO_PCI_H_ +# define _VIRTIO_PCI_H_ + +/* A 32-bit r/o bitmask of the features supported by the host */ +#define VIRTIO_PCI_HOST_FEATURES 0 + +/* A 32-bit r/w bitmask of features activated by the guest */ +#define VIRTIO_PCI_GUEST_FEATURES 4 + +/* A 32-bit r/w PFN for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_PFN 8 + +/* A 16-bit r/o queue size for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_NUM 12 + +/* A 16-bit r/w queue selector */ +#define VIRTIO_PCI_QUEUE_SEL 14 + +/* A 16-bit r/w queue notifier */ +#define VIRTIO_PCI_QUEUE_NOTIFY 16 + +/* An 8-bit device status register. */ +#define VIRTIO_PCI_STATUS 18 + +/* An 8-bit r/o interrupt status register. Reading the value will return the + * current contents of the ISR and will also clear it. This is effectively + * a read-and-acknowledge. */ +#define VIRTIO_PCI_ISR 19 + +/* The bit of the ISR which indicates a device configuration change. */ +#define VIRTIO_PCI_ISR_CONFIG 0x2 + +/* The remaining space is defined by each driver as the per-driver + * configuration space */ +#define VIRTIO_PCI_CONFIG 20 + +/* Virtio ABI version, this must match exactly */ +#define VIRTIO_PCI_ABI_VERSION 0 + +static inline u32 vp_get_features(struct nic *nic) +{ + return inl(nic->ioaddr + VIRTIO_PCI_HOST_FEATURES); +} + +static inline void vp_set_features(struct nic *nic, u32 features) +{ + outl(features, nic->ioaddr + VIRTIO_PCI_GUEST_FEATURES); +} + +static inline void vp_get(struct nic *nic, unsigned offset, + void *buf, unsigned len) +{ + u8 *ptr = buf; + unsigned i; + + for (i = 0; i < len; i++) + ptr[i] = inb(nic->ioaddr + VIRTIO_PCI_CONFIG + offset + i); +} + +static inline u8 vp_get_status(struct nic *nic) +{ + return inb(nic->ioaddr + VIRTIO_PCI_STATUS); +} + +static inline void vp_set_status(struct nic *nic, u8 status) +{ + if (status == 0) /* reset */ + return; + outb(status, nic->ioaddr + VIRTIO_PCI_STATUS); +} + + +static inline void vp_reset(struct nic *nic) +{ + outb(0, nic->ioaddr + VIRTIO_PCI_STATUS); + (void)inb(nic->ioaddr + VIRTIO_PCI_ISR); +} + +static inline void vp_notify(struct nic *nic, int queue_index) +{ + outw(queue_index, nic->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); +} + +static inline void vp_del_vq(struct nic *nic, int queue_index) +{ + /* select the queue */ + + outw(queue_index, nic->ioaddr + VIRTIO_PCI_QUEUE_SEL); + + /* deactivate the queue */ + + outl(0, nic->ioaddr + VIRTIO_PCI_QUEUE_PFN); +} +#endif /* _VIRTIO_PCI_H_ */ diff --git a/src/include/gpxe/virtio-ring.h b/src/include/gpxe/virtio-ring.h new file mode 100644 index 000000000..33060b112 --- /dev/null +++ b/src/include/gpxe/virtio-ring.h @@ -0,0 +1,93 @@ +#ifndef _VIRTIO_RING_H_ +# define _VIRTIO_RING_H_ +#define PAGE_SHIFT (12) +#define PAGE_SIZE (1<<PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE-1) + +/* Status byte for guest to report progress, and synchronize features. */ +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define VIRTIO_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* We've given up on this device. */ +#define VIRTIO_CONFIG_S_FAILED 0x80 + +#define MAX_QUEUE_NUM (512) + +#define VRING_DESC_F_NEXT 1 +#define VRING_DESC_F_WRITE 2 + +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +#define VRING_USED_F_NO_NOTIFY 1 + +struct vring_desc +{ + u64 addr; + u32 len; + u16 flags; + u16 next; +}; + +struct vring_avail +{ + u16 flags; + u16 idx; + u16 ring[0]; +}; + +struct vring_used_elem +{ + u32 id; + u32 len; +}; + +struct vring_used +{ + u16 flags; + u16 idx; + struct vring_used_elem ring[]; +}; + +struct vring { + unsigned int num; + struct vring_desc *desc; + struct vring_avail *avail; + struct vring_used *used; +}; + +static inline void vring_init(struct vring *vr, + unsigned int num, unsigned char *queue) +{ + unsigned int i; + unsigned long pa; + + vr->num = num; + + /* physical address of desc must be page aligned */ + + pa = virt_to_phys(queue); + pa = (pa + PAGE_MASK) & ~PAGE_MASK; + vr->desc = phys_to_virt(pa); + + vr->avail = (struct vring_avail *)&vr->desc[num]; + + /* physical address of used must be page aligned */ + + pa = virt_to_phys(&vr->avail->ring[num]); + pa = (pa + PAGE_MASK) & ~PAGE_MASK; + vr->used = phys_to_virt(pa); + + for (i = 0; i < num - 1; i++) + vr->desc[i].next = i + 1; + vr->desc[i].next = 0; +} + +#define vring_size(num) \ + (((((sizeof(struct vring_desc) * num) + \ + (sizeof(struct vring_avail) + sizeof(u16) * num)) \ + + PAGE_MASK) & ~PAGE_MASK) + \ + (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num)) +#endif /* _VIRTIO_RING_H_ */ |
