1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 * VirtIO Sandbox transport driver, for testing purpose only
10 #include <virtio_types.h>
12 #include <virtio_ring.h>
13 #include <linux/bug.h>
14 #include <linux/compat.h>
15 #include <linux/err.h>
18 struct virtio_sandbox_priv {
24 ulong queue_available;
28 static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
29 void *buf, unsigned int len)
34 static int virtio_sandbox_set_config(struct udevice *udev, unsigned int offset,
35 const void *buf, unsigned int len)
40 static int virtio_sandbox_get_status(struct udevice *udev, u8 *status)
42 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
44 *status = priv->status;
49 static int virtio_sandbox_set_status(struct udevice *udev, u8 status)
51 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
53 /* We should never be setting status to 0 */
56 priv->status = status;
61 static int virtio_sandbox_reset(struct udevice *udev)
63 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
65 /* 0 status means a reset */
71 static int virtio_sandbox_get_features(struct udevice *udev, u64 *features)
73 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
75 *features = priv->device_features;
80 static int virtio_sandbox_set_features(struct udevice *udev)
82 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
83 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
85 priv->driver_features = uc_priv->features;
90 static struct virtqueue *virtio_sandbox_setup_vq(struct udevice *udev,
93 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
98 /* Create the vring */
99 vq = vring_create_virtqueue(index, 4, 4096, udev);
102 goto error_new_virtqueue;
105 addr = virtqueue_get_desc_addr(vq);
106 priv->queue_desc = addr;
108 addr = virtqueue_get_avail_addr(vq);
109 priv->queue_available = addr;
111 addr = virtqueue_get_used_addr(vq);
112 priv->queue_used = addr;
120 static void virtio_sandbox_del_vq(struct virtqueue *vq)
122 vring_del_virtqueue(vq);
125 static int virtio_sandbox_del_vqs(struct udevice *udev)
127 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
128 struct virtqueue *vq, *n;
130 list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
131 virtio_sandbox_del_vq(vq);
136 static int virtio_sandbox_find_vqs(struct udevice *udev, unsigned int nvqs,
137 struct virtqueue *vqs[])
141 for (i = 0; i < nvqs; ++i) {
142 vqs[i] = virtio_sandbox_setup_vq(udev, i);
143 if (IS_ERR(vqs[i])) {
144 virtio_sandbox_del_vqs(udev);
145 return PTR_ERR(vqs[i]);
152 static int virtio_sandbox_notify(struct udevice *udev, struct virtqueue *vq)
157 static int virtio_sandbox_probe(struct udevice *udev)
159 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
160 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
162 /* fake some information for testing */
163 priv->device_features = VIRTIO_F_VERSION_1;
164 uc_priv->device = VIRTIO_ID_BLOCK;
165 uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';
170 /* check virtio device driver's remove routine was called to reset the device */
171 static int virtio_sandbox_child_post_remove(struct udevice *vdev)
175 virtio_get_status(vdev, &status);
177 panic("virtio device was not reset\n");
182 static const struct dm_virtio_ops virtio_sandbox1_ops = {
183 .get_config = virtio_sandbox_get_config,
184 .set_config = virtio_sandbox_set_config,
185 .get_status = virtio_sandbox_get_status,
186 .set_status = virtio_sandbox_set_status,
187 .reset = virtio_sandbox_reset,
188 .get_features = virtio_sandbox_get_features,
189 .set_features = virtio_sandbox_set_features,
190 .find_vqs = virtio_sandbox_find_vqs,
191 .del_vqs = virtio_sandbox_del_vqs,
192 .notify = virtio_sandbox_notify,
195 static const struct udevice_id virtio_sandbox1_ids[] = {
196 { .compatible = "sandbox,virtio1" },
200 U_BOOT_DRIVER(virtio_sandbox1) = {
201 .name = "virtio-sandbox1",
203 .of_match = virtio_sandbox1_ids,
204 .ops = &virtio_sandbox1_ops,
205 .probe = virtio_sandbox_probe,
206 .child_post_remove = virtio_sandbox_child_post_remove,
207 .priv_auto = sizeof(struct virtio_sandbox_priv),
210 /* this one without notify op */
211 static const struct dm_virtio_ops virtio_sandbox2_ops = {
212 .get_config = virtio_sandbox_get_config,
213 .set_config = virtio_sandbox_set_config,
214 .get_status = virtio_sandbox_get_status,
215 .set_status = virtio_sandbox_set_status,
216 .reset = virtio_sandbox_reset,
217 .get_features = virtio_sandbox_get_features,
218 .set_features = virtio_sandbox_set_features,
219 .find_vqs = virtio_sandbox_find_vqs,
220 .del_vqs = virtio_sandbox_del_vqs,
223 static const struct udevice_id virtio_sandbox2_ids[] = {
224 { .compatible = "sandbox,virtio2" },
228 U_BOOT_DRIVER(virtio_sandbox2) = {
229 .name = "virtio-sandbox2",
231 .of_match = virtio_sandbox2_ids,
232 .ops = &virtio_sandbox2_ops,
233 .probe = virtio_sandbox_probe,
234 .priv_auto = sizeof(struct virtio_sandbox_priv),