13 #include <linux/virtio.h>
14 #include <linux/virtio_config.h>
16 #include <linux/virtio_ring.h>
18 #include <linux/export.h>
19 #include <linux/slab.h>
21 #include <asm/paravirt.h>
25 static void *lguest_devices;
31 static inline void *lguest_map(
unsigned long phys_addr,
unsigned long pages)
36 static inline void lguest_unmap(
void *
addr)
57 #define to_lgdev(vd) container_of(vd, struct lguest_device, vdev)
72 return (
void *)(desc + 1);
78 return (
void *)(lg_vq(desc) + desc->
num_vq);
92 + desc->feature_len * 2
102 u8 *in_features = lg_features(desc);
106 if (in_features[i / 8] & (1 << (i % 8)))
107 features |= (1 << i);
118 unsigned long offset = (
void *)
to_lgdev(vdev)->desc - lguest_devices;
131 unsigned int i,
bits;
146 for (i = 0; i <
bits; i++) {
148 out_features[i / 8] |= (1 << (i % 8));
156 static void lg_get(
struct virtio_device *vdev,
unsigned int offset,
157 void *
buf,
unsigned len)
163 memcpy(buf, lg_config(desc) + offset, len);
167 static void lg_set(
struct virtio_device *vdev,
unsigned int offset,
168 const void *buf,
unsigned len)
174 memcpy(lg_config(desc) + offset, buf, len);
183 return to_lgdev(vdev)->desc->status;
232 static void lg_notify(
struct virtqueue *vq)
270 if (index >= ldev->
desc->num_vq)
284 printk(
"Mapping virtqueue %i addr %lx\n", index,
323 dev_name(&vdev->
dev), vq);
335 irq_free_desc(lvq->
config.irq);
339 lguest_unmap(lvq->
pages);
347 static void lg_del_vq(
struct virtqueue *vq)
356 lguest_unmap(lvq->
pages);
378 if (nvqs > ldev->
desc->num_vq)
381 for (i = 0; i < nvqs; ++
i) {
382 vqs[
i] = lg_find_vq(vdev, i, callbacks[i], names[i]);
390 return PTR_ERR(vqs[i]);
400 .get_features = lg_get_features,
401 .finalize_features = lg_finalize_features,
404 .get_status = lg_get_status,
405 .set_status = lg_set_status,
407 .find_vqs = lg_find_vqs,
408 .del_vqs = lg_del_vqs,
409 .bus_name = lg_bus_name,
416 static struct device *lguest_root;
444 ldev->
vdev.dev.parent = lguest_root;
455 ldev->
vdev.config = &lguest_config_ops;
475 static void scan_devices(
void)
481 for (i = 0; i <
PAGE_SIZE; i += desc_size(d)) {
482 d = lguest_devices +
i;
488 printk(
"Device at %i has size %u\n", i, desc_size(d));
489 add_lguest_device(d, i);
507 static int __init lguest_devices_init(
void)
513 if (IS_ERR(lguest_root))
514 panic(
"Could not register lguest root");