virtio.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #ifndef _VIRTIO_H_
  2. #define _VIRTIO_H_
  3. /*
  4. * A minimal implementation of virtio.
  5. * Structures adapted from the Linux Kernel.
  6. *
  7. * Copyright (C) 2017, Red Hat Inc, Andrew Jones <drjones@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2.
  10. */
  11. #include "libcflat.h"
  12. #define VIRTIO_ID_CONSOLE 3
  13. struct virtio_device_id {
  14. u32 device;
  15. u32 vendor;
  16. };
  17. struct virtio_device {
  18. struct virtio_device_id id;
  19. const struct virtio_config_ops *config;
  20. };
  21. struct virtqueue {
  22. void (*callback)(struct virtqueue *vq);
  23. const char *name;
  24. struct virtio_device *vdev;
  25. unsigned int index;
  26. unsigned int num_free;
  27. void *priv;
  28. };
  29. typedef void vq_callback_t(struct virtqueue *);
  30. struct virtio_config_ops {
  31. void (*get)(struct virtio_device *vdev, unsigned offset,
  32. void *buf, unsigned len);
  33. void (*set)(struct virtio_device *vdev, unsigned offset,
  34. const void *buf, unsigned len);
  35. int (*find_vqs)(struct virtio_device *vdev, unsigned nvqs,
  36. struct virtqueue *vqs[],
  37. vq_callback_t *callbacks[],
  38. const char *names[]);
  39. };
  40. static inline u8
  41. virtio_config_readb(struct virtio_device *vdev, unsigned offset)
  42. {
  43. u8 val;
  44. vdev->config->get(vdev, offset, &val, 1);
  45. return val;
  46. }
  47. static inline u16
  48. virtio_config_readw(struct virtio_device *vdev, unsigned offset)
  49. {
  50. u16 val;
  51. vdev->config->get(vdev, offset, &val, 2);
  52. return val;
  53. }
  54. static inline u32
  55. virtio_config_readl(struct virtio_device *vdev, unsigned offset)
  56. {
  57. u32 val;
  58. vdev->config->get(vdev, offset, &val, 4);
  59. return val;
  60. }
  61. static inline void
  62. virtio_config_writeb(struct virtio_device *vdev, unsigned offset, u8 val)
  63. {
  64. vdev->config->set(vdev, offset, &val, 1);
  65. }
  66. static inline void
  67. virtio_config_writew(struct virtio_device *vdev, unsigned offset, u16 val)
  68. {
  69. vdev->config->set(vdev, offset, &val, 2);
  70. }
  71. static inline void
  72. virtio_config_writel(struct virtio_device *vdev, unsigned offset, u32 val)
  73. {
  74. vdev->config->set(vdev, offset, &val, 4);
  75. }
  76. #define VRING_DESC_F_NEXT 1
  77. #define VRING_DESC_F_WRITE 2
  78. struct vring_desc {
  79. u64 addr;
  80. u32 len;
  81. u16 flags;
  82. u16 next;
  83. };
  84. struct vring_avail {
  85. u16 flags;
  86. u16 idx;
  87. u16 ring[];
  88. };
  89. struct vring_used_elem {
  90. u32 id;
  91. u32 len;
  92. };
  93. struct vring_used {
  94. u16 flags;
  95. u16 idx;
  96. struct vring_used_elem ring[];
  97. };
  98. struct vring {
  99. unsigned int num;
  100. struct vring_desc *desc;
  101. struct vring_avail *avail;
  102. struct vring_used *used;
  103. };
  104. struct vring_virtqueue {
  105. struct virtqueue vq;
  106. struct vring vring;
  107. unsigned int free_head;
  108. unsigned int num_added;
  109. u16 last_used_idx;
  110. bool (*notify)(struct virtqueue *vq);
  111. void *data[];
  112. };
  113. #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
  114. extern void vring_init(struct vring *vr, unsigned int num, void *p,
  115. unsigned long align);
  116. extern void vring_init_virtqueue(struct vring_virtqueue *vq, unsigned index,
  117. unsigned num, unsigned vring_align,
  118. struct virtio_device *vdev, void *pages,
  119. bool (*notify)(struct virtqueue *),
  120. void (*callback)(struct virtqueue *),
  121. const char *name);
  122. extern int virtqueue_add_outbuf(struct virtqueue *vq, char *buf,
  123. unsigned int len);
  124. extern bool virtqueue_kick(struct virtqueue *vq);
  125. extern void detach_buf(struct vring_virtqueue *vq, unsigned head);
  126. extern void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len);
  127. extern struct virtio_device *virtio_bind(u32 devid);
  128. #endif /* _VIRTIO_H_ */