lguest: documentation I: Preparation
[deliverable/linux.git] / drivers / lguest / lguest_bus.c
1 /*P:050 Lguest guests use a very simple bus for devices. It's a simple array
2 * of device descriptors contained just above the top of normal memory. The
3 * lguest bus is 80% tedious boilerplate code. :*/
4 #include <linux/init.h>
5 #include <linux/bootmem.h>
6 #include <linux/lguest_bus.h>
7 #include <asm/io.h>
8
9 static ssize_t type_show(struct device *_dev,
10 struct device_attribute *attr, char *buf)
11 {
12 struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
13 return sprintf(buf, "%hu", lguest_devices[dev->index].type);
14 }
15 static ssize_t features_show(struct device *_dev,
16 struct device_attribute *attr, char *buf)
17 {
18 struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
19 return sprintf(buf, "%hx", lguest_devices[dev->index].features);
20 }
21 static ssize_t pfn_show(struct device *_dev,
22 struct device_attribute *attr, char *buf)
23 {
24 struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
25 return sprintf(buf, "%u", lguest_devices[dev->index].pfn);
26 }
27 static ssize_t status_show(struct device *_dev,
28 struct device_attribute *attr, char *buf)
29 {
30 struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
31 return sprintf(buf, "%hx", lguest_devices[dev->index].status);
32 }
33 static ssize_t status_store(struct device *_dev, struct device_attribute *attr,
34 const char *buf, size_t count)
35 {
36 struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
37 if (sscanf(buf, "%hi", &lguest_devices[dev->index].status) != 1)
38 return -EINVAL;
39 return count;
40 }
41 static struct device_attribute lguest_dev_attrs[] = {
42 __ATTR_RO(type),
43 __ATTR_RO(features),
44 __ATTR_RO(pfn),
45 __ATTR(status, 0644, status_show, status_store),
46 __ATTR_NULL
47 };
48
49 static int lguest_dev_match(struct device *_dev, struct device_driver *_drv)
50 {
51 struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
52 struct lguest_driver *drv = container_of(_drv,struct lguest_driver,drv);
53
54 return (drv->device_type == lguest_devices[dev->index].type);
55 }
56
57 struct lguest_bus {
58 struct bus_type bus;
59 struct device dev;
60 };
61
62 static struct lguest_bus lguest_bus = {
63 .bus = {
64 .name = "lguest",
65 .match = lguest_dev_match,
66 .dev_attrs = lguest_dev_attrs,
67 },
68 .dev = {
69 .parent = NULL,
70 .bus_id = "lguest",
71 }
72 };
73
74 static int lguest_dev_probe(struct device *_dev)
75 {
76 int ret;
77 struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
78 struct lguest_driver *drv = container_of(dev->dev.driver,
79 struct lguest_driver, drv);
80
81 lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER;
82 ret = drv->probe(dev);
83 if (ret == 0)
84 lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER_OK;
85 return ret;
86 }
87
88 int register_lguest_driver(struct lguest_driver *drv)
89 {
90 if (!lguest_devices)
91 return 0;
92
93 drv->drv.bus = &lguest_bus.bus;
94 drv->drv.name = drv->name;
95 drv->drv.owner = drv->owner;
96 drv->drv.probe = lguest_dev_probe;
97
98 return driver_register(&drv->drv);
99 }
100 EXPORT_SYMBOL_GPL(register_lguest_driver);
101
102 static void add_lguest_device(unsigned int index)
103 {
104 struct lguest_device *new;
105
106 lguest_devices[index].status |= LGUEST_DEVICE_S_ACKNOWLEDGE;
107 new = kmalloc(sizeof(struct lguest_device), GFP_KERNEL);
108 if (!new) {
109 printk(KERN_EMERG "Cannot allocate lguest device %u\n", index);
110 lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED;
111 return;
112 }
113
114 new->index = index;
115 new->private = NULL;
116 memset(&new->dev, 0, sizeof(new->dev));
117 new->dev.parent = &lguest_bus.dev;
118 new->dev.bus = &lguest_bus.bus;
119 sprintf(new->dev.bus_id, "%u", index);
120 if (device_register(&new->dev) != 0) {
121 printk(KERN_EMERG "Cannot register lguest device %u\n", index);
122 lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED;
123 kfree(new);
124 }
125 }
126
127 static void scan_devices(void)
128 {
129 unsigned int i;
130
131 for (i = 0; i < LGUEST_MAX_DEVICES; i++)
132 if (lguest_devices[i].type)
133 add_lguest_device(i);
134 }
135
136 static int __init lguest_bus_init(void)
137 {
138 if (strcmp(paravirt_ops.name, "lguest") != 0)
139 return 0;
140
141 /* Devices are in page above top of "normal" mem. */
142 lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1);
143
144 if (bus_register(&lguest_bus.bus) != 0
145 || device_register(&lguest_bus.dev) != 0)
146 panic("lguest bus registration failed");
147
148 scan_devices();
149 return 0;
150 }
151 postcore_initcall(lguest_bus_init);
This page took 0.034815 seconds and 5 git commands to generate.