virtio_sandbox.c 5.3 KB

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