Deleted Added
full compact
xenbusb.c (181912) xenbusb.c (185605)
1/******************************************************************************
2 * Talks to Xen Store to figure out what devices we have.
3 *
1/******************************************************************************
2 * Talks to Xen Store to figure out what devices we have.
3 *
4 * Copyright (C) 2008 Doug Rabson
4 * Copyright (C) 2005 Rusty Russell, IBM Corporation
5 * Copyright (C) 2005 Mike Wray, Hewlett-Packard
6 * Copyright (C) 2005 XenSource Ltd
7 *
8 * This file may be distributed separately from the Linux kernel, or
9 * incorporated into other software packages, subject to the following license:
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy

--- 18 unchanged lines hidden (view full) ---

30#if 0
31#define DPRINTK(fmt, args...) \
32 printf("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
33#else
34#define DPRINTK(fmt, args...) ((void)0)
35#endif
36
37#include <sys/cdefs.h>
5 * Copyright (C) 2005 Rusty Russell, IBM Corporation
6 * Copyright (C) 2005 Mike Wray, Hewlett-Packard
7 * Copyright (C) 2005 XenSource Ltd
8 *
9 * This file may be distributed separately from the Linux kernel, or
10 * incorporated into other software packages, subject to the following license:
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy

--- 18 unchanged lines hidden (view full) ---

31#if 0
32#define DPRINTK(fmt, args...) \
33 printf("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
34#else
35#define DPRINTK(fmt, args...) ((void)0)
36#endif
37
38#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/xen/xenbus/xenbus_probe.c 181912 2008-08-20 09:20:12Z kmacy $");
39__FBSDID("$FreeBSD: head/sys/xen/xenbus/xenbus_probe.c 185605 2008-12-04 07:59:05Z kmacy $");
39
40#include <sys/param.h>
40
41#include <sys/param.h>
41#include <sys/types.h>
42#include <sys/cdefs.h>
43#include <sys/time.h>
44#include <sys/sema.h>
45#include <sys/eventhandler.h>
46#include <sys/errno.h>
42#include <sys/bus.h>
47#include <sys/kernel.h>
43#include <sys/kernel.h>
44#include <sys/lock.h>
48#include <sys/malloc.h>
49#include <sys/module.h>
45#include <sys/malloc.h>
46#include <sys/module.h>
50#include <sys/conf.h>
51#include <sys/systm.h>
47#include <sys/sysctl.h>
52#include <sys/syslog.h>
48#include <sys/syslog.h>
53#include <sys/proc.h>
54#include <sys/bus.h>
49#include <sys/systm.h>
55#include <sys/sx.h>
50#include <sys/sx.h>
51#include <sys/taskqueue.h>
56
57#include <machine/xen/xen-os.h>
52
53#include <machine/xen/xen-os.h>
58#include <machine/xen/hypervisor.h>
59#include <machine/xen/xenbus.h>
60#include <machine/xen/evtchn.h>
61#include <machine/stdarg.h>
62
54#include <machine/stdarg.h>
55
56#include <xen/gnttab.h>
57#include <xen/xenbus/xenbusvar.h>
63#include <xen/xenbus/xenbus_comms.h>
64
58#include <xen/xenbus/xenbus_comms.h>
59
65struct xendev_list_head xenbus_device_frontend_list;
66struct xendev_list_head xenbus_device_backend_list;
67static LIST_HEAD(, xenbus_driver) xendrv_list;
68
69extern struct sx xenwatch_mutex;
70
71EVENTHANDLER_DECLARE(xenstore_event, xenstore_event_handler_t);
72static struct eventhandler_list *xenstore_chain;
73device_t xenbus_dev;
74device_t xenbus_backend_dev;
75static MALLOC_DEFINE(M_XENDEV, "xenintrdrv", "xen system device");
76
77#define streq(a, b) (strcmp((a), (b)) == 0)
78
79static int watch_otherend(struct xenbus_device *dev);
80
81
82/* If something in array of ids matches this device, return it. */
83static const struct xenbus_device_id *
84match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
85{
86 for (; !streq(arr->devicetype, ""); arr++) {
87 if (streq(arr->devicetype, dev->devicetype))
88 return arr;
89 }
90 return NULL;
91}
92
93#if 0
94static int xenbus_match(device_t _dev)
95{
96 struct xenbus_driver *drv;
97 struct xenbus_device *dev;
98
99 dev = device_get_softc(_dev);
100 drv = dev->driver;
101
102 if (!drv->ids)
103 return 0;
104
105 return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
106}
107#endif
108
109
110/* device/<type>/<id> => <type>-<id> */
111static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
112{
113 nodename = strchr(nodename, '/');
114 if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) {
115 log(LOG_WARNING, "XENBUS: bad frontend %s\n", nodename);
116 return -EINVAL;
117 }
118
119 strlcpy(bus_id, nodename + 1, BUS_ID_SIZE);
120 if (!strchr(bus_id, '/')) {
121 log(LOG_WARNING, "XENBUS: bus_id %s no slash\n", bus_id);
122 return -EINVAL;
123 }
124 *strchr(bus_id, '/') = '-';
125 return 0;
126}
127
128
129static void free_otherend_details(struct xenbus_device *dev)
130{
131 kfree((void*)(uintptr_t)dev->otherend);
132 dev->otherend = NULL;
133}
134
135
136static void free_otherend_watch(struct xenbus_device *dev)
137{
138 if (dev->otherend_watch.node) {
139 unregister_xenbus_watch(&dev->otherend_watch);
140 kfree(dev->otherend_watch.node);
141 dev->otherend_watch.node = NULL;
142 }
143}
144
145int
146read_otherend_details(struct xenbus_device *xendev, char *id_node,
147 char *path_node)
148{
149 int err = xenbus_gather(XBT_NIL, xendev->nodename,
150 id_node, "%i", &xendev->otherend_id,
151 path_node, NULL, &xendev->otherend,
152 NULL);
153 if (err) {
154 xenbus_dev_fatal(xendev, err,
155 "reading other end details from %s",
156 xendev->nodename);
157 return err;
158 }
159 if (strlen(xendev->otherend) == 0 ||
160 !xenbus_exists(XBT_NIL, xendev->otherend, "")) {
161 xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
162 xendev->nodename);
163 kfree((void *)(uintptr_t)xendev->otherend);
164 xendev->otherend = NULL;
165 return -ENOENT;
166 }
167
168 return 0;
169}
170
171
172static int read_backend_details(struct xenbus_device *xendev)
173{
174 return read_otherend_details(xendev, "backend-id", "backend");
175}
176
177#ifdef notyet
178/* XXX - move to probe backend */
179static int read_frontend_details(struct xenbus_device *xendev)
180{
181 if (strncmp(xendev->nodename, "backend", 7))
182 return -ENOENT;
183 return read_otherend_details(xendev, "frontend-id", "frontend");
184}
185#endif
186
187/* Bus type for frontend drivers. */
188static int xenbus_probe_frontend(const char *type, const char *name);
189static struct xen_bus_type xenbus_frontend = {
190 .root = "device",
191 .levels = 2, /* device/type/<id> */
192 .get_bus_id = frontend_bus_id,
193 .probe = xenbus_probe_frontend,
194 .bus = &xenbus_device_frontend_list,
195#if 0
196 /* this initialization needs to happen dynamically */
197 .bus = {
198 .name = "xen",
199 .match = xenbus_match,
200 },
201 .dev = {
202 .bus_id = "xen",
203 },
204#endif
60struct xenbus_softc {
61 struct xenbus_watch xs_devicewatch;
62 struct task xs_probechildren;
63 struct intr_config_hook xs_attachcb;
64 device_t xs_dev;
205};
206
65};
66
207#if 0
208static int xenbus_hotplug_backend(device_t dev, char **envp,
209 int num_envp, char *buffer, int buffer_size)
210{
211 panic("implement me");
212#if 0
213 struct xenbus_device *xdev;
214 struct xenbus_driver *drv = NULL;
215 int i = 0;
216 int length = 0;
217 char *basepath_end;
218 char *frontend_id;
219
220 DPRINTK("");
221
222 if (dev == NULL)
223 return -ENODEV;
224
225 xdev = to_xenbus_device(dev);
226 if (xdev == NULL)
227 return -ENODEV;
228
229 if (dev->driver)
230 drv = to_xenbus_driver(dev->driver);
231
232 /* stuff we want to pass to /sbin/hotplug */
233 add_hotplug_env_var(envp, num_envp, &i,
234 buffer, buffer_size, &length,
235 "XENBUS_TYPE=%s", xdev->devicetype);
236
237 add_hotplug_env_var(envp, num_envp, &i,
238 buffer, buffer_size, &length,
239 "XENBUS_PATH=%s", xdev->nodename);
240
241 add_hotplug_env_var(envp, num_envp, &i,
242 buffer, buffer_size, &length,
243 "XENBUS_BASE_PATH=%s", xdev->nodename);
244
245 basepath_end = strrchr(envp[i - 1], '/');
246 length -= strlen(basepath_end);
247 *basepath_end = '\0';
248 basepath_end = strrchr(envp[i - 1], '/');
249 length -= strlen(basepath_end);
250 *basepath_end = '\0';
251
252 basepath_end++;
253 frontend_id = kmalloc(strlen(basepath_end) + 1, GFP_KERNEL);
254 strcpy(frontend_id, basepath_end);
255 add_hotplug_env_var(envp, num_envp, &i,
256 buffer, buffer_size, &length,
257 "XENBUS_FRONTEND_ID=%s", frontend_id);
258 kfree(frontend_id);
259
260 /* terminate, set to next free slot, shrink available space */
261 envp[i] = NULL;
262 envp = &envp[i];
263 num_envp -= i;
264 buffer = &buffer[length];
265 buffer_size -= length;
266
267 if (drv && drv->hotplug)
268 return drv->hotplug(xdev, envp, num_envp, buffer, buffer_size);
269
270#endif
271 return 0;
272}
273#endif
274
275#if 0
276static int xenbus_probe_backend(const char *type, const char *domid, int unit);
277static struct xen_bus_type xenbus_backend = {
278 .root = "backend",
279 .levels = 3, /* backend/type/<frontend>/<id> */
280 .get_bus_id = backend_bus_id,
281 .probe = xenbus_probe_backend,
282 /* at init time */
283 .bus = &xenbus_device_backend_list,
284#if 0
285 .bus = {
286 .name = "xen-backend",
287 .match = xenbus_match,
288 .hotplug = xenbus_hotplug_backend,
289 },
290 .dev = {
291 .bus_id = "xen-backend",
292 },
293#endif
67struct xenbus_device_ivars {
68 struct xenbus_watch xd_otherend_watch; /* must be first */
69 struct sx xd_lock;
70 device_t xd_dev;
71 char *xd_node; /* node name in xenstore */
72 char *xd_type; /* xen device type */
73 enum xenbus_state xd_state;
74 int xd_otherend_id;
75 char *xd_otherend_path;
294};
76};
295#endif
296
77
297static void otherend_changed(struct xenbus_watch *watch,
298 const char **vec, unsigned int len)
78/* Simplified asprintf. */
79char *
80kasprintf(const char *fmt, ...)
299{
81{
82 va_list ap;
83 unsigned int len;
84 char *p, dummy[1];
300
85
301 struct xenbus_device *dev = (struct xenbus_device *)watch;
302 struct xenbus_driver *drv = dev->driver;
303 XenbusState state;
304
305 /* Protect us against watches firing on old details when the otherend
306 details change, say immediately after a resume. */
307 if (!dev->otherend || strncmp(dev->otherend, vec[XS_WATCH_PATH],
308 strlen(dev->otherend))) {
309 DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
310 return;
311 }
86 va_start(ap, fmt);
87 /* FIXME: vsnprintf has a bug, NULL should work */
88 len = vsnprintf(dummy, 0, fmt, ap);
89 va_end(ap);
312
90
313 state = xenbus_read_driver_state(dev->otherend);
314
315 DPRINTK("state is %d, %s, %s", state, dev->otherend_watch.node,
316 vec[XS_WATCH_PATH]);
317
318 /*
319 * Ignore xenbus transitions during shutdown. This prevents us doing
320 * work that can fail e.g., when the rootfs is gone.
321 */
322#if 0
323 if (system_state > SYSTEM_RUNNING) {
324 struct xen_bus_type *bus = bus;
325 bus = container_of(dev->dev.bus, struct xen_bus_type, bus);
326 /* If we're frontend, drive the state machine to Closed. */
327 /* This should cause the backend to release our resources. */
328 if ((bus == &xenbus_frontend) && (state == XenbusStateClosing))
329 xenbus_frontend_closed(dev);
330 return;
331 }
332#endif
333 if (drv->otherend_changed)
334 drv->otherend_changed(dev, state);
335
91 p = kmalloc(len + 1, GFP_KERNEL);
92 if (!p)
93 return NULL;
94 va_start(ap, fmt);
95 vsprintf(p, fmt, ap);
96 va_end(ap);
97 return p;
336}
337
98}
99
338
339static int talk_to_otherend(struct xenbus_device *dev)
100static void
101xenbus_identify(driver_t *driver, device_t parent)
340{
102{
341 struct xenbus_driver *drv;
342
103
343 drv = dev->driver;
344
345 free_otherend_watch(dev);
346 free_otherend_details(dev);
347
348 return drv->read_otherend_details(dev);
104 BUS_ADD_CHILD(parent, 0, "xenbus", 0);
349}
350
105}
106
351static int watch_otherend(struct xenbus_device *dev)
352{
353 return xenbus_watch_path2(dev, dev->otherend, "state",
354 &dev->otherend_watch, otherend_changed);
355}
356
357static int
107static int
358xenbus_dev_probe(struct xenbus_device *dev)
108xenbus_probe(device_t dev)
359{
109{
360 struct xenbus_driver *drv = dev->driver;
361 const struct xenbus_device_id *id;
362 int err;
363
110 int err = 0;
111
364 DPRINTK("");
112 DPRINTK("");
365
366 if (!drv->probe) {
367 err = -ENODEV;
368 goto fail;
369 }
370
371 id = match_device(drv->ids, dev);
372 if (!id) {
373 err = -ENODEV;
374 goto fail;
375 }
376
377 err = talk_to_otherend(dev);
113
114 /* Initialize the interface to xenstore. */
115 err = xs_init();
378 if (err) {
116 if (err) {
379 log(LOG_WARNING,
380 "xenbus_probe: talk_to_otherend on %s failed.\n",
381 dev->nodename);
382 return err;
117 log(LOG_WARNING,
118 "XENBUS: Error initializing xenstore comms: %i\n", err);
119 return (ENXIO);
383 }
120 }
384
385 err = drv->probe(dev, id);
386 if (err)
387 goto fail;
388
389 err = watch_otherend(dev);
121 err = gnttab_init();
390 if (err) {
122 if (err) {
391 log(LOG_WARNING,
392 "xenbus_probe: watch_otherend on %s failed.\n",
393 dev->nodename);
394 return err;
123 log(LOG_WARNING,
124 "XENBUS: Error initializing grant table: %i\n", err);
125 return (ENXIO);
395 }
126 }
396
397 return 0;
398 fail:
399 xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
400 xenbus_switch_state(dev, XenbusStateClosed);
401 return -ENODEV;
402}
127 device_set_desc(dev, "Xen Devices");
403
128
404static void xenbus_dev_free(struct xenbus_device *xendev)
405{
406 LIST_REMOVE(xendev, list);
407 kfree(xendev);
129 return (0);
408}
409
130}
131
410int
411xenbus_remove_device(struct xenbus_device *dev)
132static enum xenbus_state
133xenbus_otherend_state(struct xenbus_device_ivars *ivars)
412{
134{
413 struct xenbus_driver *drv = dev->driver;
414
135
415 DPRINTK("");
416
417 free_otherend_watch(dev);
418 free_otherend_details(dev);
419
420 if (drv->remove)
421 drv->remove(dev);
422
423 xenbus_switch_state(dev, XenbusStateClosed);
424
425 if (drv->cleanup_device)
426 return drv->cleanup_device(dev);
427
428 xenbus_dev_free(dev);
429
430 return 0;
136 return (xenbus_read_driver_state(ivars->xd_otherend_path));
431}
432
137}
138
433#if 0
434static int
435xenbus_dev_remove(device_t _dev)
139static void
140xenbus_backend_changed(struct xenbus_watch *watch, const char **vec,
141 unsigned int len)
436{
142{
437 return xenbus_remove_device(to_xenbus_device(_dev));
438}
439#endif
143 struct xenbus_device_ivars *ivars;
144 device_t dev;
145 enum xenbus_state newstate;
440
146
441int xenbus_register_driver_common(struct xenbus_driver *drv,
442 struct xen_bus_type *bus)
443{
444 struct xenbus_device *xdev;
445
446#if 0
447 int ret;
448 /* this all happens in the driver itself
449 * doing this here simple serves to obfuscate
450 */
147 ivars = (struct xenbus_device_ivars *) watch;
148 dev = ivars->xd_dev;
451
149
452 drv->driver.name = drv->name;
453 drv->driver.bus = &bus->bus;
454 drv->driver.owner = drv->owner;
455 drv->driver.probe = xenbus_dev_probe;
456 drv->driver.remove = xenbus_dev_remove;
150 if (!ivars->xd_otherend_path
151 || strncmp(ivars->xd_otherend_path, vec[XS_WATCH_PATH],
152 strlen(ivars->xd_otherend_path)))
153 return;
457
154
458 return ret;
459#endif
460 sx_xlock(&xenwatch_mutex);
461 LIST_INSERT_HEAD(&xendrv_list, drv, list);
462 sx_xunlock(&xenwatch_mutex);
463 LIST_FOREACH(xdev, bus->bus, list) {
464 if (match_device(drv->ids, xdev)) {
465 xdev->driver = drv;
466 xenbus_dev_probe(xdev);
467 }
468 }
469 return 0;
155 newstate = xenbus_otherend_state(ivars);
156 XENBUS_BACKEND_CHANGED(dev, newstate);
470}
471
157}
158
472int xenbus_register_frontend(struct xenbus_driver *drv)
159static int
160xenbus_device_exists(device_t dev, const char *node)
473{
161{
474 drv->read_otherend_details = read_backend_details;
162 device_t *kids;
163 struct xenbus_device_ivars *ivars;
164 int i, count, result;
475
165
476 return xenbus_register_driver_common(drv, &xenbus_frontend);
477}
478EXPORT_SYMBOL(xenbus_register_frontend);
166 if (device_get_children(dev, &kids, &count))
167 return (FALSE);
479
168
480
481void xenbus_unregister_driver(struct xenbus_driver *drv)
482{
483#if 0
484 driver_unregister(&drv->driver);
485#endif
486}
487EXPORT_SYMBOL(xenbus_unregister_driver);
488
489struct xb_find_info
490{
491 struct xenbus_device *dev;
492 const char *nodename;
493};
494
495static struct xenbus_device *
496xenbus_device_find(const char *nodename, struct xendev_list_head *bus)
497{
498 struct xenbus_device *xdev;
499 LIST_FOREACH(xdev, bus, list) {
500 if (streq(xdev->nodename, nodename)) {
501 return xdev;
502#if 0
503 get_device(dev);
504#endif
169 result = FALSE;
170 for (i = 0; i < count; i++) {
171 ivars = device_get_ivars(kids[i]);
172 if (!strcmp(ivars->xd_node, node)) {
173 result = TRUE;
174 break;
505 }
506 }
175 }
176 }
507 return NULL;
508}
509#if 0
510static int cleanup_dev(device_t dev, void *data)
511{
512 struct xenbus_device *xendev = device_get_softc(dev);
513 struct xb_find_info *info = data;
514 int len = strlen(info->nodename);
177 free(kids, M_TEMP);
515
178
516 DPRINTK("%s", info->nodename);
517
518 if (!strncmp(xendev->nodename, info->nodename, len)) {
519 info->dev = xendev;
520#if 0
521 get_device(dev);
522#endif
523 return 1;
524 }
525 return 0;
179 return (result);
526}
527
180}
181
528#endif
529static void xenbus_cleanup_devices(const char *path, struct xendev_list_head * bus)
182static int
183xenbus_add_device(device_t dev, const char *bus,
184 const char *type, const char *id)
530{
185{
531#if 0
532 struct xb_find_info info = { .nodename = path };
186 device_t child;
187 struct xenbus_device_ivars *ivars;
188 enum xenbus_state state;
189 char *statepath;
533
190
534 do {
535 info.dev = NULL;
536 bus_for_each_dev(bus, NULL, &info, cleanup_dev);
537 if (info.dev) {
538 device_unregister(&info.dev->dev);
539 put_device(&info.dev->dev);
540 }
541 } while (info.dev);
542#endif
543}
191 ivars = malloc(sizeof(struct xenbus_device_ivars),
192 M_DEVBUF, M_ZERO|M_WAITOK);
193 ivars->xd_node = kasprintf("%s/%s/%s", bus, type, id);
544
194
545#if 0
546void xenbus_dev_release(device_t dev)
547{
548 /*
549 * nothing to do softc gets freed with the device
550 */
551
552}
553#endif
554/* Simplified asprintf. */
555char *kasprintf(const char *fmt, ...)
556{
557 va_list ap;
558 unsigned int len;
559 char *p, dummy[1];
195 if (xenbus_device_exists(dev, ivars->xd_node)) {
196 /*
197 * We are already tracking this node
198 */
199 free(ivars->xd_node, M_DEVBUF);
200 free(ivars, M_DEVBUF);
201 return (0);
202 }
560
203
561 va_start(ap, fmt);
562 /* FIXME: vsnprintf has a bug, NULL should work */
563 len = vsnprintf(dummy, 0, fmt, ap);
564 va_end(ap);
204 state = xenbus_read_driver_state(ivars->xd_node);
565
205
566 p = kmalloc(len + 1, GFP_KERNEL);
567 if (!p)
568 return NULL;
569 va_start(ap, fmt);
570 vsprintf(p, fmt, ap);
571 va_end(ap);
572 return p;
573}
574
575#if 0
576static ssize_t xendev_show_nodename(struct device *dev, char *buf)
577{
578 return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
579}
580DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
581
582static ssize_t xendev_show_devtype(struct device *dev, char *buf)
583{
584 return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
585}
586DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
587#endif
588
589int xenbus_probe_node(struct xen_bus_type *bus, const char *type,
590 const char *nodename)
591{
592#define CHECK_FAIL \
593 do { \
594 if (err) \
595 goto fail; \
596 } while (0) \
597
598
599
600 int err;
601 struct xenbus_device *xendev;
602 struct xenbus_driver *xdrv;
603 size_t stringlen;
604 char *tmpstring;
605
606 XenbusState state = xenbus_read_driver_state(nodename);
607
608 if (bus->error)
609 return (bus->error);
610
611
612 if (state != XenbusStateInitialising) {
206 if (state != XenbusStateInitialising) {
613 /* Device is not new, so ignore it. This can happen if a
614 device is going away after switching to Closed. */
615 return 0;
207 /*
208 * Device is not new, so ignore it. This can
209 * happen if a device is going away after
210 * switching to Closed.
211 */
212 free(ivars->xd_node, M_DEVBUF);
213 free(ivars, M_DEVBUF);
214 return (0);
616 }
215 }
617
618 stringlen = strlen(nodename) + 1 + strlen(type) + 1;
619 xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
620 if (!xendev)
621 return -ENOMEM;
622 memset(xendev, 0, sizeof(*xendev));
623 xendev->state = XenbusStateInitialising;
624
625 /* Copy the strings into the extra space. */
626
627 tmpstring = (char *)(xendev + 1);
628 strcpy(tmpstring, nodename);
629 xendev->nodename = tmpstring;
630
631 tmpstring += strlen(tmpstring) + 1;
632 strcpy(tmpstring, type);
633 xendev->devicetype = tmpstring;
216
634 /*
217 /*
635 * equivalent to device registration
636 * events
218 * Find the backend details
637 */
219 */
638 LIST_INSERT_HEAD(bus->bus, xendev, list);
639 LIST_FOREACH(xdrv, &xendrv_list, list) {
640 if (match_device(xdrv->ids, xendev)) {
641 xendev->driver = xdrv;
642 if (!xenbus_dev_probe(xendev))
643 break;
644 }
645 }
220 xenbus_gather(XBT_NIL, ivars->xd_node,
221 "backend-id", "%i", &ivars->xd_otherend_id,
222 "backend", NULL, &ivars->xd_otherend_path,
223 NULL);
646
224
647#if 0
648 xendev->dev.parent = &bus->dev;
649 xendev->dev.bus = &bus->bus;
650 xendev->dev.release = xenbus_dev_release;
651
652 err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
653 CHECK_FAIL;
654
655 /* Register with generic device framework. */
656 err = device_register(&xendev->dev);
657 CHECK_FAIL;
658
659 device_create_file(&xendev->dev, &dev_attr_nodename);
660 device_create_file(&xendev->dev, &dev_attr_devtype);
661#endif
662 return 0;
663
664#undef CHECK_FAIL
665#if 0
666 fail:
667 xenbus_dev_free(xendev);
668#endif
669 return err;
670}
225 sx_init(&ivars->xd_lock, "xdlock");
226 ivars->xd_type = strdup(type, M_DEVBUF);
227 ivars->xd_state = XenbusStateInitialising;
671
228
672/* device/<typename>/<name> */
673static int xenbus_probe_frontend(const char *type, const char *name)
674{
675 char *nodename;
676 int err;
229 statepath = malloc(strlen(ivars->xd_otherend_path)
230 + strlen("/state") + 1, M_DEVBUF, M_NOWAIT);
231 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
677
232
678 nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
679 if (!nodename)
680 return -ENOMEM;
233 ivars->xd_otherend_watch.node = statepath;
234 ivars->xd_otherend_watch.callback = xenbus_backend_changed;
681
235
682 DPRINTK("%s", nodename);
236 child = device_add_child(dev, NULL, -1);
237 ivars->xd_dev = child;
238 device_set_ivars(child, ivars);
683
239
684 err = xenbus_probe_node(&xenbus_frontend, type, nodename);
685 kfree(nodename);
686 return err;
240 return (0);
687}
688
241}
242
689static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
243static int
244xenbus_enumerate_type(device_t dev, const char *bus, const char *type)
690{
245{
691 int err = 0;
692 char **dir;
246 char **dir;
693 unsigned int dir_n = 0;
694 int i;
247 unsigned int i, count;
695
248
696 dir = xenbus_directory(XBT_NIL, bus->root, type, &dir_n);
249 dir = xenbus_directory(XBT_NIL, bus, type, &count);
697 if (IS_ERR(dir))
250 if (IS_ERR(dir))
698 return PTR_ERR(dir);
251 return (EINVAL);
252 for (i = 0; i < count; i++)
253 xenbus_add_device(dev, bus, type, dir[i]);
699
254
700 for (i = 0; i < dir_n; i++) {
701 err = bus->probe(type, dir[i]);
702 if (err)
703 break;
704 }
705 kfree(dir);
706 return err;
255 free(dir, M_DEVBUF);
256
257 return (0);
707}
708
258}
259
709int xenbus_probe_devices(struct xen_bus_type *bus)
260static int
261xenbus_enumerate_bus(device_t dev, const char *bus)
710{
262{
711 int err = 0;
712 char **dir;
263 char **dir;
713 unsigned int i, dir_n;
264 unsigned int i, count;
714
265
715 dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n);
266 dir = xenbus_directory(XBT_NIL, bus, "", &count);
716 if (IS_ERR(dir))
267 if (IS_ERR(dir))
717 return PTR_ERR(dir);
718
719 for (i = 0; i < dir_n; i++) {
720 err = xenbus_probe_device_type(bus, dir[i]);
721 if (err)
722 break;
268 return (EINVAL);
269 for (i = 0; i < count; i++) {
270 xenbus_enumerate_type(dev, bus, dir[i]);
723 }
271 }
724 kfree(dir);
272 free(dir, M_DEVBUF);
725
273
726 return err;
274 return (0);
727}
728
275}
276
729static unsigned int char_count(const char *str, char c)
277static int
278xenbus_probe_children(device_t dev)
730{
279{
731 unsigned int i, ret = 0;
280 device_t *kids;
281 struct xenbus_device_ivars *ivars;
282 int i, count;
732
283
733 for (i = 0; str[i]; i++)
734 if (str[i] == c)
735 ret++;
736 return ret;
737}
284 /*
285 * Probe any new devices and register watches for any that
286 * attach successfully. Since part of the protocol which
287 * establishes a connection with the other end is interrupt
288 * driven, we sleep until the device reaches a stable state
289 * (closed or connected).
290 */
291 if (device_get_children(dev, &kids, &count) == 0) {
292 for (i = 0; i < count; i++) {
293 if (device_get_state(kids[i]) != DS_NOTPRESENT)
294 continue;
738
295
739static int strsep_len(const char *str, char c, unsigned int len)
740{
741 unsigned int i;
742
743 for (i = 0; str[i]; i++)
744 if (str[i] == c) {
745 if (len == 0)
746 return i;
747 len--;
296 if (device_probe_and_attach(kids[i]))
297 continue;
298 ivars = device_get_ivars(kids[i]);
299 register_xenbus_watch(
300 &ivars->xd_otherend_watch);
301 sx_xlock(&ivars->xd_lock);
302 while (ivars->xd_state != XenbusStateClosed
303 && ivars->xd_state != XenbusStateConnected)
304 sx_sleep(&ivars->xd_state, &ivars->xd_lock,
305 0, "xdattach", 0);
306 sx_xunlock(&ivars->xd_lock);
748 }
307 }
749 return (len == 0) ? i : -ERANGE;
750}
751
752void dev_changed(const char *node, struct xen_bus_type *bus)
753{
754 int exists, rootlen;
755 struct xenbus_device *dev;
756 char type[BUS_ID_SIZE];
757 const char *p;
758 char *root;
759
760 DPRINTK("");
761 if (char_count(node, '/') < 2)
762 return;
763
764 exists = xenbus_exists(XBT_NIL, node, "");
765 if (!exists) {
766 xenbus_cleanup_devices(node, bus->bus);
767 return;
308 free(kids, M_TEMP);
768 }
769
309 }
310
770 /* backend/<type>/... or device/<type>/... */
771 p = strchr(node, '/') + 1;
772 snprintf(type, BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p);
773 type[BUS_ID_SIZE-1] = '\0';
774
775 rootlen = strsep_len(node, '/', bus->levels);
776 if (rootlen < 0)
777 return;
778 root = kasprintf("%.*s", rootlen, node);
779 if (!root)
780 return;
781
782 dev = xenbus_device_find(root, bus->bus);
783 if (!dev)
784 xenbus_probe_node(bus, type, root);
785#if 0
786 else
787 put_device(&dev->dev);
788#endif
789 kfree(root);
311 return (0);
790}
791
312}
313
792static void frontend_changed(struct xenbus_watch *watch,
793 const char **vec, unsigned int len)
314static void
315xenbus_probe_children_cb(void *arg, int pending)
794{
316{
795 DPRINTK("");
317 device_t dev = (device_t) arg;
796
318
797 dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
319 xenbus_probe_children(dev);
798}
799
320}
321
800/* We watch for devices appearing and vanishing. */
801static struct xenbus_watch fe_watch = {
802 .node = "device",
803 .callback = frontend_changed,
804};
805
806#ifdef notyet
807
808static int suspend_dev(device_t dev, void *data)
322static void
323xenbus_devices_changed(struct xenbus_watch *watch,
324 const char **vec, unsigned int len)
809{
325{
810 int err = 0;
811 struct xenbus_driver *drv;
812 struct xenbus_device *xdev;
326 struct xenbus_softc *sc = (struct xenbus_softc *) watch;
327 device_t dev = sc->xs_dev;
328 char *node, *bus, *type, *id, *p;
813
329
814 DPRINTK("");
330 node = strdup(vec[XS_WATCH_PATH], M_DEVBUF);;
331 p = strchr(node, '/');
332 if (!p)
333 goto out;
334 bus = node;
335 *p = 0;
336 type = p + 1;
815
337
816 xdev = device_get_softc(dev);
338 p = strchr(type, '/');
339 if (!p)
340 goto out;
341 *p = 0;
342 id = p + 1;
817
343
818 drv = xdev->driver;
344 p = strchr(id, '/');
345 if (p)
346 *p = 0;
819
347
820 if (device_get_driver(dev) == NULL)
821 return 0;
822
823 if (drv->suspend)
824 err = drv->suspend(xdev);
825#if 0
826 /* bus_id ? */
827 if (err)
828 log(LOG_WARNING, "xenbus: suspend %s failed: %i\n",
829 dev->bus_id, err);
830#endif
831 return 0;
348 xenbus_add_device(dev, bus, type, id);
349 taskqueue_enqueue(taskqueue_thread, &sc->xs_probechildren);
350out:
351 free(node, M_DEVBUF);
832}
833
352}
353
354static void
355xenbus_attach_deferred(void *arg)
356{
357 device_t dev = (device_t) arg;
358 struct xenbus_softc *sc = device_get_softc(dev);
359 int error;
360
361 error = xenbus_enumerate_bus(dev, "device");
362 if (error)
363 return;
364 xenbus_probe_children(dev);
834
365
366 sc->xs_dev = dev;
367 sc->xs_devicewatch.node = "device";
368 sc->xs_devicewatch.callback = xenbus_devices_changed;
835
369
836static int resume_dev(device_t dev, void *data)
837{
838 int err;
839 struct xenbus_driver *drv;
840 struct xenbus_device *xdev;
370 TASK_INIT(&sc->xs_probechildren, 0, xenbus_probe_children_cb, dev);
841
371
842 DPRINTK("");
372 register_xenbus_watch(&sc->xs_devicewatch);
843
373
844 if (device_get_driver(dev) == NULL)
845 return 0;
846 xdev = device_get_softc(dev);
847 drv = xdev->driver;
374 config_intrhook_disestablish(&sc->xs_attachcb);
375}
848
376
849 err = talk_to_otherend(xdev);
850#if 0
851 if (err) {
852 log(LOG_WARNING,
853 "xenbus: resume (talk_to_otherend) %s failed: %i\n",
854 dev->bus_id, err);
855 return err;
856 }
857#endif
858 if (drv->resume)
859 err = drv->resume(xdev);
377static int
378xenbus_attach(device_t dev)
379{
380 struct xenbus_softc *sc = device_get_softc(dev);
860
381
861 err = watch_otherend(xdev);
862#if 0
863 /* bus_id? */
864 if (err)
865 log(LOG_WARNING,
866 "xenbus: resume %s failed: %i\n", dev->bus_id, err);
867#endif
868 return err;
382 sc->xs_attachcb.ich_func = xenbus_attach_deferred;
383 sc->xs_attachcb.ich_arg = dev;
384 config_intrhook_establish(&sc->xs_attachcb);
385
386 return (0);
869}
870
387}
388
871#endif
872void xenbus_suspend(void)
389static void
390xenbus_suspend(device_t dev)
873{
874 DPRINTK("");
875 panic("implement me");
876#if 0
877 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
878 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
879#endif
880 xs_suspend();
881}
391{
392 DPRINTK("");
393 panic("implement me");
394#if 0
395 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
396 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
397#endif
398 xs_suspend();
399}
882EXPORT_SYMBOL(xenbus_suspend);
883
400
884void xenbus_resume(void)
401static void
402xenbus_resume(device_t dev)
885{
886 xb_init_comms();
887 xs_resume();
888 panic("implement me");
889#if 0
890 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
891 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
892#endif
893}
403{
404 xb_init_comms();
405 xs_resume();
406 panic("implement me");
407#if 0
408 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
409 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
410#endif
411}
894EXPORT_SYMBOL(xenbus_resume);
895
412
896#if 0
897static device_t
898xenbus_add_child(device_t bus, int order, const char *name, int unit)
899{
900 device_t child;
901
902 child = device_add_child_ordered(bus, order, name, unit);
903
904 return(child);
905}
906#endif
907
908/* A flag to determine if xenstored is 'ready' (i.e. has started) */
909int xenstored_ready = 0;
910
911
912int register_xenstore_notifier(xenstore_event_handler_t func, void *arg, int priority)
413static int
414xenbus_print_child(device_t dev, device_t child)
913{
415{
914 int ret = 0;
416 struct xenbus_device_ivars *ivars = device_get_ivars(child);
417 int retval = 0;
915
418
916 if (xenstored_ready > 0)
917 ret = func(NULL);
918 else
919 eventhandler_register(xenstore_chain, "xenstore", func, arg, priority);
419 retval += bus_print_child_header(dev, child);
420 retval += printf(" at %s", ivars->xd_node);
421 retval += bus_print_child_footer(dev, child);
920
422
921 return ret;
423 return (retval);
922}
424}
923EXPORT_SYMBOL(register_xenstore_notifier);
924#if 0
925void unregister_xenstore_notifier(struct notifier_block *nb)
425
426static int
427xenbus_read_ivar(device_t dev, device_t child, int index,
428 uintptr_t * result)
926{
429{
927 notifier_chain_unregister(&xenstore_chain, nb);
928}
929EXPORT_SYMBOL(unregister_xenstore_notifier);
930#endif
430 struct xenbus_device_ivars *ivars = device_get_ivars(child);
931
431
432 switch (index) {
433 case XENBUS_IVAR_NODE:
434 *result = (uintptr_t) ivars->xd_node;
435 return (0);
436 case XENBUS_IVAR_TYPE:
437 *result = (uintptr_t) ivars->xd_type;
438 return (0);
439 case XENBUS_IVAR_STATE:
440 *result = (uintptr_t) ivars->xd_state;
441 return (0);
932
442
443 case XENBUS_IVAR_OTHEREND_ID:
444 *result = (uintptr_t) ivars->xd_otherend_id;
445 return (0);
933
446
934#ifdef DOM0
935static struct proc_dir_entry *xsd_mfn_intf;
936static struct proc_dir_entry *xsd_port_intf;
447 case XENBUS_IVAR_OTHEREND_PATH:
448 *result = (uintptr_t) ivars->xd_otherend_path;
449 return (0);
450 }
937
451
938
939static int xsd_mfn_read(char *page, char **start, off_t off,
940 int count, int *eof, void *data)
941{
942 int len;
943 len = sprintf(page, "%ld", xen_start_info->store_mfn);
944 *eof = 1;
945 return len;
452 return (ENOENT);
946}
947
453}
454
948static int xsd_port_read(char *page, char **start, off_t off,
949 int count, int *eof, void *data)
455static int
456xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
950{
457{
951 int len;
458 struct xenbus_device_ivars *ivars = device_get_ivars(child);
459 enum xenbus_state newstate;
460 int currstate;
461 int error;
952
462
953 len = sprintf(page, "%d", xen_start_info->store_evtchn);
954 *eof = 1;
955 return len;
956}
463 switch (index) {
464 case XENBUS_IVAR_STATE:
465 newstate = (enum xenbus_state) value;
466 sx_xlock(&ivars->xd_lock);
467 if (ivars->xd_state == newstate)
468 goto out;
957
469
958#endif
470 error = xenbus_scanf(XBT_NIL, ivars->xd_node, "state",
471 "%d", &currstate);
472 if (error < 0)
473 goto out;
959
474
960static int dom0 = 0;
475 error = xenbus_printf(XBT_NIL, ivars->xd_node, "state",
476 "%d", newstate);
477 if (error) {
478 if (newstate != XenbusStateClosing) /* Avoid looping */
479 xenbus_dev_fatal(dev, error, "writing new state");
480 goto out;
481 }
482 ivars->xd_state = newstate;
483 wakeup(&ivars->xd_state);
484 out:
485 sx_xunlock(&ivars->xd_lock);
486 return (0);
961
487
962static int
963xenbus_probe_sysinit(void *unused)
964{
965 int err = 0;
966
967 DPRINTK("");
968
969 LIST_INIT(&xenbus_device_frontend_list);
970 LIST_INIT(&xenbus_device_backend_list);
971 LIST_INIT(&xendrv_list);
972#if 0
973 if (xen_init() < 0) {
974 DPRINTK("failed");
975 return -ENODEV;
488 case XENBUS_IVAR_NODE:
489 case XENBUS_IVAR_TYPE:
490 case XENBUS_IVAR_OTHEREND_ID:
491 case XENBUS_IVAR_OTHEREND_PATH:
492 /*
493 * These variables are read-only.
494 */
495 return (EINVAL);
976 }
496 }
977
978
979 /* Register ourselves with the kernel bus & device subsystems */
980 bus_register(&xenbus_frontend.bus);
981 bus_register(&xenbus_backend.bus);
982 device_register(&xenbus_frontend.dev);
983 device_register(&xenbus_backend.dev);
984#endif
985
986 /*
987 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
988 */
989 dom0 = (xen_start_info->store_evtchn == 0);
990
991
992#ifdef DOM0
993 if (dom0) {
994
995 unsigned long page;
996 evtchn_op_t op = { 0 };
997 int ret;
998
999
1000 /* Allocate page. */
1001 page = get_zeroed_page(GFP_KERNEL);
1002 if (!page)
1003 return -ENOMEM;
1004
1005 /* We don't refcnt properly, so set reserved on page.
1006 * (this allocation is permanent) */
1007 SetPageReserved(virt_to_page(page));
1008
1009 xen_start_info->store_mfn =
1010 pfn_to_mfn(virt_to_phys((void *)page) >>
1011 PAGE_SHIFT);
1012
1013 /* Next allocate a local port which xenstored can bind to */
1014 op.cmd = EVTCHNOP_alloc_unbound;
1015 op.u.alloc_unbound.dom = DOMID_SELF;
1016 op.u.alloc_unbound.remote_dom = 0;
1017
1018 ret = HYPERVISOR_event_channel_op(&op);
1019 BUG_ON(ret);
1020 xen_start_info->store_evtchn = op.u.alloc_unbound.port;
1021
1022 /* And finally publish the above info in /proc/xen */
1023 if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400)))
1024 xsd_mfn_intf->read_proc = xsd_mfn_read;
1025 if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
1026 xsd_port_intf->read_proc = xsd_port_read;
1027 }
1028#endif
1029 /* Initialize the interface to xenstore. */
1030 err = xs_init();
1031 if (err) {
1032 log(LOG_WARNING,
1033 "XENBUS: Error initializing xenstore comms: %i\n", err);
1034 return err;
1035 }
1036
1037 return 0;
497 return (ENOENT);
1038}
1039
498}
499
1040
1041static int
1042xenbus_probe_sysinit2(void *unused)
1043{
1044 if (!dom0) {
1045 xenstored_ready = 1;
500SYSCTL_DECL(_dev);
501SYSCTL_NODE(_dev, OID_AUTO, xen, CTLFLAG_RD, NULL, "Xen");
1046#if 0
502#if 0
1047 xenbus_dev = BUS_ADD_CHILD(parent, 0, "xenbus", 0);
1048 if (xenbus_dev == NULL)
1049 panic("xenbus: could not attach");
1050 xenbus_backend_dev = BUS_ADD_CHILD(parent, 0, "xb_be", 0);
1051 if (xenbus_backend_dev == NULL)
1052 panic("xenbus: could not attach");
503SYSCTL_INT(_dev_xen, OID_AUTO, xsd_port, CTLFLAG_RD, &xen_store_evtchn, 0, "");
504SYSCTL_ULONG(_dev_xen, OID_AUTO, xsd_kva, CTLFLAG_RD, (u_long *) &xen_store, 0, "");
1053#endif
505#endif
1054 BUG_ON((xenstored_ready <= 0));
1055
1056
506
1057
1058 /* Enumerate devices in xenstore. */
1059 xenbus_probe_devices(&xenbus_frontend);
1060 register_xenbus_watch(&fe_watch);
1061 xenbus_backend_probe_and_watch();
1062
1063 /* Notify others that xenstore is up */
1064 EVENTHANDLER_INVOKE(xenstore_event);
1065 }
1066 return (0);
1067}
1068
1069
1070SYSINIT(xenbus_probe_sysinit, SI_SUB_PSEUDO, SI_ORDER_FIRST, xenbus_probe_sysinit, NULL);
1071SYSINIT(xenbus_probe_sysinit2, SI_SUB_PSEUDO, SI_ORDER_ANY,
1072 xenbus_probe_sysinit2, NULL);
1073
1074#if 0
1075static device_method_t xenbus_methods[] = {
1076 /* Device interface */
507static device_method_t xenbus_methods[] = {
508 /* Device interface */
1077#if 0
1078 DEVMETHOD(device_identify, xenbus_identify),
509 DEVMETHOD(device_identify, xenbus_identify),
1079 DEVMETHOD(device_probe, xenbus_probe),
1080 DEVMETHOD(device_attach, xenbus_attach),
510 DEVMETHOD(device_probe, xenbus_probe),
511 DEVMETHOD(device_attach, xenbus_attach),
1081
1082 DEVMETHOD(device_detach, bus_generic_detach),
1083 DEVMETHOD(device_shutdown, bus_generic_shutdown),
512 DEVMETHOD(device_detach, bus_generic_detach),
513 DEVMETHOD(device_shutdown, bus_generic_shutdown),
1084#endif
1085 DEVMETHOD(device_suspend, xenbus_suspend),
1086 DEVMETHOD(device_resume, xenbus_resume),
1087
1088 /* Bus interface */
514 DEVMETHOD(device_suspend, xenbus_suspend),
515 DEVMETHOD(device_resume, xenbus_resume),
516
517 /* Bus interface */
1089 DEVMETHOD(bus_print_child, bus_generic_print_child),
1090 DEVMETHOD(bus_add_child, xenbus_add_child),
1091 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
1092 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
1093#if 0
1094 DEVMETHOD(bus_set_resource, bus_generic_set_resource),
1095 DEVMETHOD(bus_get_resource, bus_generic_get_resource),
1096#endif
1097 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
1098 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
1099#if 0
1100 DEVMETHOD(bus_delete_resource, bus_generic_delete_resource),
1101#endif
1102 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1103 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1104 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
1105 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
518 DEVMETHOD(bus_print_child, xenbus_print_child),
519 DEVMETHOD(bus_read_ivar, xenbus_read_ivar),
520 DEVMETHOD(bus_write_ivar, xenbus_write_ivar),
1106
1107 { 0, 0 }
1108};
1109
1110static char driver_name[] = "xenbus";
1111static driver_t xenbus_driver = {
1112 driver_name,
1113 xenbus_methods,
521
522 { 0, 0 }
523};
524
525static char driver_name[] = "xenbus";
526static driver_t xenbus_driver = {
527 driver_name,
528 xenbus_methods,
1114 sizeof(struct xenbus_device),
529 sizeof(struct xenbus_softc),
1115};
1116devclass_t xenbus_devclass;
1117
530};
531devclass_t xenbus_devclass;
532
1118DRIVER_MODULE(xenbus, nexus, xenbus_driver, xenbus_devclass, 0, 0);
1119
533#ifdef XENHVM
534DRIVER_MODULE(xenbus, xenpci, xenbus_driver, xenbus_devclass, 0, 0);
535#else
536DRIVER_MODULE(xenbus, nexus, xenbus_driver, xenbus_devclass, 0, 0);
1120#endif
537#endif
1121
1122
1123
1124
1125
1126/*
1127 * Local variables:
1128 * c-file-style: "bsd"
1129 * indent-tabs-mode: t
1130 * c-indent-level: 4
1131 * c-basic-offset: 8
1132 * tab-width: 4
1133 * End:
1134 */