virtio_sandbox.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
  4. *
  5. * VirtIO Sandbox transport driver, for testing purpose only
  6. */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <virtio_types.h>
  10. #include <virtio.h>
  11. #include <virtio_ring.h>
  12. #include <linux/bug.h>
  13. #include <linux/compat.h>
  14. #include <linux/err.h>
  15. #include <linux/io.h>
  16. struct virtio_sandbox_priv {
  17. u8 id;
  18. u8 status;
  19. u64 device_features;
  20. u64 driver_features;
  21. ulong queue_desc;
  22. ulong queue_available;
  23. ulong queue_used;
  24. };
  25. static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
  26. void *buf, unsigned int len)
  27. {
  28. return 0;
  29. }
  30. static int virtio_sandbox_set_config(struct udevice *udev, unsigned int offset,
  31. const void *buf, unsigned int len)
  32. {
  33. return 0;
  34. }
  35. static int virtio_sandbox_get_status(struct udevice *udev, u8 *status)
  36. {
  37. struct virtio_sandbox_priv *priv = dev_get_priv(udev);
  38. *status = priv->status;
  39. return 0;
  40. }
  41. static int virtio_sandbox_set_status(struct udevice *udev, u8 status)
  42. {
  43. struct virtio_sandbox_priv *priv = dev_get_priv(udev);
  44. /* We should never be setting status to 0 */
  45. WARN_ON(status == 0);
  46. priv->status = status;
  47. return 0;
  48. }
  49. static int virtio_sandbox_reset(struct udevice *udev)
  50. {
  51. struct virtio_sandbox_priv *priv = dev_get_priv(udev);
  52. /* 0 status means a reset */
  53. priv->status = 0;
  54. return 0;
  55. }
  56. static int virtio_sandbox_get_features(struct udevice *udev, u64 *features)
  57. {
  58. struct virtio_sandbox_priv *priv = dev_get_priv(udev);
  59. *features = priv->device_features;
  60. return 0;
  61. }
  62. static int virtio_sandbox_set_features(struct udevice *udev)
  63. {
  64. struct virtio_sandbox_priv *priv = dev_get_priv(udev);
  65. struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
  66. priv->driver_features = uc_priv->features;
  67. return 0;
  68. }
  69. static struct virtqueue *virtio_sandbox_setup_vq(struct udevice *udev,
  70. unsigned int index)
  71. {
  72. struct virtio_sandbox_priv *priv = dev_get_priv(udev);
  73. struct virtqueue *vq;
  74. ulong addr;
  75. int err;
  76. /* Create the vring */
  77. vq = vring_create_virtqueue(index, 4, 4096, udev);
  78. if (!vq) {
  79. err = -ENOMEM;
  80. goto error_new_virtqueue;
  81. }
  82. addr = virtqueue_get_desc_addr(vq);
  83. priv->queue_desc = addr;
  84. addr = virtqueue_get_avail_addr(vq);
  85. priv->queue_available = addr;
  86. addr = virtqueue_get_used_addr(vq);
  87. priv->queue_used = addr;
  88. return vq;
  89. error_new_virtqueue:
  90. return ERR_PTR(err);
  91. }
  92. static void virtio_sandbox_del_vq(struct virtqueue *vq)
  93. {
  94. vring_del_virtqueue(vq);
  95. }
  96. static int virtio_sandbox_del_vqs(struct udevice *udev)
  97. {
  98. struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
  99. struct virtqueue *vq, *n;
  100. list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
  101. virtio_sandbox_del_vq(vq);
  102. return 0;
  103. }
  104. static int virtio_sandbox_find_vqs(struct udevice *udev, unsigned int nvqs,
  105. struct virtqueue *vqs[])
  106. {
  107. int i;
  108. for (i = 0; i < nvqs; ++i) {
  109. vqs[i] = virtio_sandbox_setup_vq(udev, i);
  110. if (IS_ERR(vqs[i])) {
  111. virtio_sandbox_del_vqs(udev);
  112. return PTR_ERR(vqs[i]);
  113. }
  114. }
  115. return 0;
  116. }
  117. static int virtio_sandbox_notify(struct udevice *udev, struct virtqueue *vq)
  118. {
  119. return 0;
  120. }
  121. static int virtio_sandbox_probe(struct udevice *udev)
  122. {
  123. struct virtio_sandbox_priv *priv = dev_get_priv(udev);
  124. struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
  125. /* fake some information for testing */
  126. priv->device_features = VIRTIO_F_VERSION_1;
  127. uc_priv->device = VIRTIO_ID_BLOCK;
  128. uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';
  129. return 0;
  130. }
  131. /* check virtio device driver's remove routine was called to reset the device */
  132. static int virtio_sandbox_child_post_remove(struct udevice *vdev)
  133. {
  134. u8 status;
  135. virtio_get_status(vdev, &status);
  136. if (status)
  137. panic("virtio device was not reset\n");
  138. return 0;
  139. }
  140. static const struct dm_virtio_ops virtio_sandbox1_ops = {
  141. .get_config = virtio_sandbox_get_config,
  142. .set_config = virtio_sandbox_set_config,
  143. .get_status = virtio_sandbox_get_status,
  144. .set_status = virtio_sandbox_set_status,
  145. .reset = virtio_sandbox_reset,
  146. .get_features = virtio_sandbox_get_features,
  147. .set_features = virtio_sandbox_set_features,
  148. .find_vqs = virtio_sandbox_find_vqs,
  149. .del_vqs = virtio_sandbox_del_vqs,
  150. .notify = virtio_sandbox_notify,
  151. };
  152. static const struct udevice_id virtio_sandbox1_ids[] = {
  153. { .compatible = "sandbox,virtio1" },
  154. { }
  155. };
  156. U_BOOT_DRIVER(virtio_sandbox1) = {
  157. .name = "virtio-sandbox1",
  158. .id = UCLASS_VIRTIO,
  159. .of_match = virtio_sandbox1_ids,
  160. .ops = &virtio_sandbox1_ops,
  161. .probe = virtio_sandbox_probe,
  162. .child_post_remove = virtio_sandbox_child_post_remove,
  163. .priv_auto_alloc_size = sizeof(struct virtio_sandbox_priv),
  164. };
  165. /* this one without notify op */
  166. static const struct dm_virtio_ops virtio_sandbox2_ops = {
  167. .get_config = virtio_sandbox_get_config,
  168. .set_config = virtio_sandbox_set_config,
  169. .get_status = virtio_sandbox_get_status,
  170. .set_status = virtio_sandbox_set_status,
  171. .reset = virtio_sandbox_reset,
  172. .get_features = virtio_sandbox_get_features,
  173. .set_features = virtio_sandbox_set_features,
  174. .find_vqs = virtio_sandbox_find_vqs,
  175. .del_vqs = virtio_sandbox_del_vqs,
  176. };
  177. static const struct udevice_id virtio_sandbox2_ids[] = {
  178. { .compatible = "sandbox,virtio2" },
  179. { }
  180. };
  181. U_BOOT_DRIVER(virtio_sandbox2) = {
  182. .name = "virtio-sandbox2",
  183. .id = UCLASS_VIRTIO,
  184. .of_match = virtio_sandbox2_ids,
  185. .ops = &virtio_sandbox2_ops,
  186. .probe = virtio_sandbox_probe,
  187. .priv_auto_alloc_size = sizeof(struct virtio_sandbox_priv),
  188. };