lguest: documentation I: Preparation
[deliverable/linux.git] / drivers / lguest / lguest_bus.c
CommitLineData
f938d2c8
RR
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. :*/
07ad157f
RR
4#include <linux/init.h>
5#include <linux/bootmem.h>
6#include <linux/lguest_bus.h>
7#include <asm/io.h>
8
9static 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}
15static 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}
21static 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}
27static 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}
33static 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}
41static 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
49static 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
57struct lguest_bus {
58 struct bus_type bus;
59 struct device dev;
60};
61
62static 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
74static 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
88int 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}
100EXPORT_SYMBOL_GPL(register_lguest_driver);
101
102static 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
127static 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
136static 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}
151postcore_initcall(lguest_bus_init);
This page took 0.056107 seconds and 5 git commands to generate.