virtio_sandbox.c 5.3 KB

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