xenbus_probe.c revision 1.2 1 /* $NetBSD: xenbus_probe.c,v 1.2 2006/03/06 20:21:35 bouyer Exp $ */
2 /******************************************************************************
3 * Talks to Xen Store to figure out what devices we have.
4 *
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
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.2 2006/03/06 20:21:35 bouyer Exp $");
33
34 #if 0
35 #define DPRINTK(fmt, args...) \
36 printf("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
37 #else
38 #define DPRINTK(fmt, args...) ((void)0)
39 #endif
40
41 #include <sys/types.h>
42 #include <sys/null.h>
43 #include <sys/errno.h>
44 #include <sys/malloc.h>
45 #include <sys/systm.h>
46 #include <sys/param.h>
47 #include <sys/kthread.h>
48
49 #include <machine/stdarg.h>
50
51 #include <machine/hypervisor.h>
52 #include <machine/xenbus.h>
53 #include <machine/evtchn.h>
54
55 #include "xenbus_comms.h"
56
57 extern struct semaphore xenwatch_mutex;
58
59 #define streq(a, b) (strcmp((a), (b)) == 0)
60
61 static int xenbus_match(struct device *, struct cfdata *, void *);
62 static void xenbus_attach(struct device *, struct device *, void *);
63 static int xenbus_print(void *, const char *);
64
65 static void xenbus_kthread_create(void *);
66 static void xenbus_probe_init(void *);
67
68 CFATTACH_DECL(xenbus, sizeof(struct device), xenbus_match, xenbus_attach,
69 NULL, NULL);
70
71 struct device *xenbus_device;
72
73 int
74 xenbus_match(struct device *parent, struct cfdata *match, void *aux)
75 {
76 struct xenbus_attach_args *xa = (struct xenbus_attach_args *)aux;
77
78 if (strcmp(xa->xa_device, "xenbus") == 0)
79 return 1;
80 return 0;
81 }
82
83 static void
84 xenbus_attach(struct device *parent, struct device *self, void *aux)
85 {
86 aprint_normal(": Xen Virtual Bus Interface\n");
87 xenbus_device = self;
88 xb_init_comms(self);
89 config_pending_incr();
90 kthread_create(xenbus_kthread_create, NULL);
91 }
92
93 void
94 xenbus_kthread_create(void *unused)
95 {
96 struct proc *p;
97 int err;
98 err = kthread_create1(xenbus_probe_init, NULL, &p, "xenbus_probe");
99 if (err)
100 printf("kthread_create1(xenbus_probe): %d\n", err);
101 }
102
103
104 #if 0
105 static char *kasprintf(const char *fmt, ...);
106
107 static struct notifier_block *xenstore_chain;
108
109 /* If something in array of ids matches this device, return it. */
110 static const struct xenbus_device_id *
111 match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
112 {
113 for (; !streq(arr->devicetype, ""); arr++) {
114 if (streq(arr->devicetype, dev->devicetype))
115 return arr;
116 }
117 return NULL;
118 }
119
120 static int xenbus_match_device(struct device *_dev, struct device_driver *_drv)
121 {
122 struct xenbus_driver *drv = to_xenbus_driver(_drv);
123
124 if (!drv->ids)
125 return 0;
126
127 return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
128 }
129 #endif
130
131 struct xen_bus_type
132 {
133 const char *root;
134 unsigned int levels;
135 };
136
137 #if 0
138 /* device/<type>/<id> => <type>-<id> */
139 static int
140 frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
141 {
142 nodename = strchr(nodename, '/');
143 if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) {
144 printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename);
145 return EINVAL;
146 }
147
148 strlcpy(bus_id, nodename + 1, BUS_ID_SIZE);
149 if (!strchr(bus_id, '/')) {
150 printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id);
151 return EINVAL;
152 }
153 *strchr(bus_id, '/') = '-';
154 return 0;
155 }
156 #endif
157
158 static int
159 read_otherend_details(struct xenbus_device *xendev,
160 const char *id_node, const char *path_node)
161 {
162 int err;
163 char *val, *ep;
164
165 err = xenbus_read(NULL, xendev->xbusd_path, id_node, NULL, &val);
166 if (err) {
167 printf("reading other end details %s from %s\n",
168 id_node, xendev->xbusd_path);
169 xenbus_dev_fatal(xendev, err,
170 "reading other end details %s from %s",
171 id_node, xendev->xbusd_path);
172 return err;
173 }
174 xendev->xbusd_otherend_id = strtoul(val, &ep, 10);
175 if (val[0] == '\0' || *ep != '\0') {
176 printf("reading other end details %s from %s: %s is not a number\n", id_node, xendev->xbusd_path, val);
177 xenbus_dev_fatal(xendev, err,
178 "reading other end details %s from %s: %s is not a number",
179 id_node, xendev->xbusd_path, val);
180 free(val, M_DEVBUF);
181 return EFTYPE;
182 }
183 free(val, M_DEVBUF);
184 err = xenbus_read(NULL, xendev->xbusd_path, path_node, NULL, &val);
185 if (err) {
186 printf("reading other end details %s from %s (%d)\n",
187 path_node, xendev->xbusd_path, err);
188 xenbus_dev_fatal(xendev, err,
189 "reading other end details %s from %s",
190 path_node, xendev->xbusd_path);
191 return err;
192 }
193 xendev->xbusd_otherend = val;
194
195 if (strlen(xendev->xbusd_otherend) == 0 ||
196 !xenbus_exists(NULL, xendev->xbusd_otherend, "")) {
197 printf("missing other end from %s\n", xendev->xbusd_path);
198 xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
199 xendev->xbusd_path);
200 free(xendev->xbusd_otherend, M_DEVBUF);
201 xendev->xbusd_otherend = NULL;
202 return ENOENT;
203 }
204
205 return 0;
206 }
207
208 static int
209 read_backend_details(struct xenbus_device *xendev)
210 {
211 return read_otherend_details(xendev, "backend-id", "backend");
212 }
213
214
215 #ifdef DOM0OPS
216 static int
217 read_frontend_details(struct xenbus_device *xendev)
218 {
219 return read_otherend_details(xendev, "frontend-id", "frontend");
220 }
221 #endif
222
223
224 #if 0
225 static void
226 free_otherend_details(struct xenbus_device *dev)
227 {
228 free(dev->xbusd_otherend, M_DEVBUF);
229 dev->xbusd_otherend = NULL;
230 }
231
232
233 static void
234 free_otherend_watch(struct xenbus_device *dev)
235 {
236 if (dev->xbusd_otherend_watch.node) {
237 unregister_xenbus_watch(&dev->xbusd_otherend_watch);
238 // XXX free(dev->xbusd_otherend_watch.node, M_DEVBUF);
239 dev->xbusd_otherend_watch.node = NULL;
240 }
241 }
242
243
244 /* Bus type for frontend drivers. */
245 static int xenbus_probe_frontend(const char *type, const char *name);
246 #endif
247 static struct xen_bus_type xenbus_frontend = {
248 .root = "device",
249 .levels = 2, /* device/type/<id> */
250 };
251
252 #if 0
253 /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
254 static int
255 backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
256 {
257 int domid, err;
258 const char *devid, *type, *frontend;
259 unsigned int typelen;
260
261 type = strchr(nodename, '/');
262 if (!type)
263 return EINVAL;
264 type++;
265 typelen = strcspn(type, "/");
266 if (!typelen || type[typelen] != '/')
267 return EINVAL;
268
269 devid = strrchr(nodename, '/') + 1;
270
271 err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
272 "frontend", NULL, &frontend,
273 NULL);
274 if (err)
275 return err;
276 if (strlen(frontend) == 0)
277 err = ERANGE;
278
279 if (!err && !xenbus_exists(NULL, frontend, ""))
280 err = ENOENT;
281
282 if (err) {
283 free(frontend, M_DEVBUF);
284 return err;
285 }
286
287 if (snprintf(bus_id, BUS_ID_SIZE,
288 "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
289 return ENOSPC;
290 return 0;
291 }
292
293 static int
294 xenbus_hotplug_backend(struct device *dev, char **envp,
295 int num_envp, char *buffer, int buffer_size)
296 {
297 struct xenbus_device *xdev;
298 struct xenbus_driver *drv = NULL;
299 int i = 0;
300 int length = 0;
301 char *basepath_end;
302 char *frontend_id;
303
304 DPRINTK("");
305
306 if (dev == NULL)
307 return ENODEV;
308
309 xdev = to_xenbus_device(dev);
310 if (xdev == NULL)
311 return ENODEV;
312
313 if (dev->driver)
314 drv = to_xenbus_driver(dev->driver);
315
316 /* stuff we want to pass to /sbin/hotplug */
317 add_hotplug_env_var(envp, num_envp, &i,
318 buffer, buffer_size, &length,
319 "XENBUS_TYPE=%s", xdev->devicetype);
320
321 add_hotplug_env_var(envp, num_envp, &i,
322 buffer, buffer_size, &length,
323 "XENBUS_PATH=%s", xdev->xbusd_path);
324
325 add_hotplug_env_var(envp, num_envp, &i,
326 buffer, buffer_size, &length,
327 "XENBUS_BASE_PATH=%s", xdev->xbusd_path);
328
329 basepath_end = strrchr(envp[i - 1], '/');
330 length -= strlen(basepath_end);
331 *basepath_end = '\0';
332 basepath_end = strrchr(envp[i - 1], '/');
333 length -= strlen(basepath_end);
334 *basepath_end = '\0';
335
336 basepath_end++;
337 frontend_id = kmalloc(strlen(basepath_end) + 1, GFP_KERNEL);
338 strcpy(frontend_id, basepath_end);
339 add_hotplug_env_var(envp, num_envp, &i,
340 buffer, buffer_size, &length,
341 "XENBUS_FRONTEND_ID=%s", frontend_id);
342 free(frontend_id, M_DEVBUF);
343
344 /* terminate, set to next free slot, shrink available space */
345 envp[i] = NULL;
346 envp = &envp[i];
347 num_envp -= i;
348 buffer = &buffer[length];
349 buffer_size -= length;
350
351 if (drv && drv->hotplug)
352 return drv->hotplug(xdev, envp, num_envp, buffer,
353 buffer_size);
354
355 return 0;
356 }
357
358 static int xenbus_probe_backend(const char *type, const char *domid);
359 #endif
360
361 static struct xen_bus_type xenbus_backend = {
362 .root = "backend",
363 .levels = 3, /* backend/type/<frontend>/<id> */
364 };
365
366 #if 0
367 static void
368 otherend_changed(struct xenbus_watch *watch,
369 const char **vec, unsigned int len)
370 {
371 struct xenbus_device *dev =
372 container_of(watch, struct xenbus_device, otherend_watch);
373 struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
374 XenbusState state;
375
376 /* Protect us against watches firing on old details when the otherend
377 details change, say immediately after a resume. */
378 if (!dev->xbusd_otherend ||
379 strncmp(dev->xbusd_otherend, vec[XS_WATCH_PATH],
380 strlen(dev->xbusd_otherend))) {
381 DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
382 return;
383 }
384
385 state = xenbus_read_driver_state(dev->xbusd_otherend);
386
387 DPRINTK("state is %d, %s, %s",
388 state, dev->xbusd_otherend_watch.node, vec[XS_WATCH_PATH]);
389 if (drv->otherend_changed)
390 drv->otherend_changed(dev, state);
391 }
392
393 static int
394 talk_to_otherend(struct xenbus_device *dev)
395 {
396 struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
397 int err;
398
399 free_otherend_watch(dev);
400 free_otherend_details(dev);
401
402 err = drv->read_otherend_details(dev);
403 if (err)
404 return err;
405
406 return xenbus_watch_path2(dev, dev->xbusd_otherend, "state",
407 &dev->otherend_watch, otherend_changed);
408 }
409
410
411 static int
412 xenbus_dev_probe(struct device *_dev)
413 {
414 struct xenbus_device *dev = to_xenbus_device(_dev);
415 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
416 const struct xenbus_device_id *id;
417 int err;
418
419 DPRINTK("");
420
421 err = talk_to_otherend(dev);
422 if (err) {
423 printk(KERN_WARNING
424 "xenbus_probe: talk_to_otherend on %s failed.\n",
425 dev->xbusd_path);
426 return err;
427 }
428
429 if (!drv->probe) {
430 err = ENODEV;
431 goto fail;
432 }
433
434 id = match_device(drv->ids, dev);
435 if (!id) {
436 err = ENODEV;
437 goto fail;
438 }
439
440 err = drv->probe(dev, id);
441 if (err)
442 goto fail;
443
444 return 0;
445 fail:
446 xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->xbusd_path);
447 xenbus_switch_state(dev, NULL, XenbusStateClosed);
448 return ENODEV;
449
450 }
451
452 static int
453 xenbus_dev_remove(struct device *_dev)
454 {
455 struct xenbus_device *dev = to_xenbus_device(_dev);
456 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
457
458 DPRINTK("");
459
460 free_otherend_watch(dev);
461 free_otherend_details(dev);
462
463 if (drv->remove)
464 drv->remove(dev);
465
466 xenbus_switch_state(dev, NULL, XenbusStateClosed);
467 return 0;
468 }
469
470 static int
471 xenbus_register_driver_common(struct xenbus_driver *drv,
472 struct xen_bus_type *bus)
473 {
474 int ret;
475
476 drv->driver.name = drv->name;
477 drv->driver.bus = &bus->bus;
478 drv->driver.owner = drv->owner;
479 drv->driver.probe = xenbus_dev_probe;
480 drv->driver.remove = xenbus_dev_remove;
481
482 down(&xenwatch_mutex);
483 ret = driver_register(&drv->driver);
484 up(&xenwatch_mutex);
485 return ret;
486 }
487
488 int
489 xenbus_register_frontend(struct xenbus_driver *drv)
490 {
491 drv->read_otherend_details = read_backend_details;
492
493 return xenbus_register_driver_common(drv, &xenbus_frontend);
494 }
495
496 int
497 xenbus_register_backend(struct xenbus_driver *drv)
498 {
499 drv->read_otherend_details = read_frontend_details;
500
501 return xenbus_register_driver_common(drv, &xenbus_backend);
502 }
503
504 void
505 xenbus_unregister_driver(struct xenbus_driver *drv)
506 {
507 driver_unregister(&drv->driver);
508 }
509
510 struct xb_find_info
511 {
512 struct xenbus_device *dev;
513 const char *nodename;
514 };
515
516 static int
517 cmp_dev(struct device *dev, void *data)
518 {
519 struct xenbus_device *xendev = to_xenbus_device(dev);
520 struct xb_find_info *info = data;
521
522 if (streq(xendev->xbusd_path, info->nodename)) {
523 info->dev = xendev;
524 get_device(dev);
525 return 1;
526 }
527 return 0;
528 }
529
530 struct xenbus_device *
531 xenbus_device_find(const char *nodename, struct bus_type *bus)
532 {
533 struct xb_find_info info = { .dev = NULL, .nodename = nodename };
534
535 bus_for_each_dev(bus, NULL, &info, cmp_dev);
536 return info.dev;
537 }
538
539 static int
540 cleanup_dev(struct device *dev, void *data)
541 {
542 struct xenbus_device *xendev = to_xenbus_device(dev);
543 struct xb_find_info *info = data;
544 int len = strlen(info->nodename);
545
546 DPRINTK("%s", info->nodename);
547
548 if (!strncmp(xendev->xbusd_path, info->nodename, len)) {
549 info->dev = xendev;
550 get_device(dev);
551 return 1;
552 }
553 return 0;
554 }
555
556 static void
557 xenbus_cleanup_devices(const char *path, struct bus_type *bus)
558 {
559 struct xb_find_info info = { .nodename = path };
560
561 do {
562 info.dev = NULL;
563 bus_for_each_dev(bus, NULL, &info, cleanup_dev);
564 if (info.dev) {
565 device_unregister(&info.dev->dev);
566 put_device(&info.dev->dev);
567 }
568 } while (info.dev);
569 }
570
571 static void
572 xenbus_dev_free(struct xenbus_device *xendev)
573 {
574 free(xendev, M_DEVBUF);
575 }
576
577 static void
578 xenbus_dev_release(struct device *dev)
579 {
580 if (dev) {
581 xenbus_dev_free(to_xenbus_device(dev));
582 }
583 }
584
585 /* Simplified asprintf. */
586 static char *kasprintf(const char *fmt, ...)
587 {
588 va_list ap;
589 unsigned int len;
590 char *p, dummy[1];
591
592 va_start(ap, fmt);
593 /* FIXME: vsnprintf has a bug, NULL should work */
594 len = vsnprintf(dummy, 0, fmt, ap);
595 va_end(ap);
596
597 p = malloc(len + 1, M_DEVBUF, M_NOWAIT);
598 if (!p)
599 return NULL;
600 va_start(ap, fmt);
601 vsprintf(p, fmt, ap);
602 va_end(ap);
603 return p;
604 }
605 #endif
606
607 #if 0
608 static ssize_t
609 xendev_show_nodename(struct device *dev, char *buf)
610 {
611 return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
612 }
613 // XXX implement
614 DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
615
616 static ssize_t
617 xendev_show_devtype(struct device *dev, char *buf)
618 {
619 return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
620 }
621 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
622
623
624 static int
625 xenbus_probe_node(struct xen_bus_type *bus,
626 const char *type,
627 const char *nodename)
628 {
629 #define CHECK_FAIL \
630 do { \
631 if (err) \
632 goto fail; \
633 } \
634 while (0) \
635
636
637 struct xenbus_device *xendev;
638 size_t stringlen;
639 char *tmpstring;
640
641 XenbusState state = xenbus_read_driver_state(nodename);
642
643 printf("xenbus_probe_node %s %s %s %d\n", bus->root, type, nodename, state);
644 if (state != XenbusStateInitialising) {
645 /* Device is not new, so ignore it. This can happen if a
646 device is going away after switching to Closed. */
647 return 0;
648 }
649
650
651 stringlen = strlen(nodename) + 1 + strlen(type) + 1;
652 xendev = malloc(sizeof(*xendev) + stringlen, M_DEVBUF, M_NOWAIT);
653 if (!xendev)
654 return ENOMEM;
655 memset(xendev, 0, sizeof(*xendev));
656
657 /* Copy the strings into the extra space. */
658
659 tmpstring = (char *)(xendev + 1);
660 strcpy(tmpstring, nodename);
661 xendev->nodename = tmpstring;
662
663 tmpstring += strlen(tmpstring) + 1;
664 strcpy(tmpstring, type);
665 xendev->devicetype = tmpstring;
666
667 #if 0
668 xendev->dev.parent = &bus->dev;
669 xendev->dev.bus = &bus->bus;
670 xendev->dev.release = xenbus_dev_release;
671
672 err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
673 CHECK_FAIL;
674
675 /* Register with generic device framework. */
676 err = device_register(&xendev->dev);
677 CHECK_FAIL;
678
679 device_create_file(&xendev->dev, &dev_attr_nodename);
680 device_create_file(&xendev->dev, &dev_attr_devtype);
681
682 #endif
683 return 0;
684
685 #undef CHECK_FAIL
686 #if 0
687 fail:
688 xenbus_dev_free(xendev);
689 return err;
690 #endif
691 }
692 #endif
693
694 #if 0
695 /* device/<typename>/<name> */
696 static int
697 xenbus_probe_frontend(const char *type, const char *name)
698 {
699 char *nodename;
700 int err;
701
702 nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
703 if (!nodename)
704 return ENOMEM;
705
706 DPRINTK("%s", nodename);
707
708 err = xenbus_probe_node(&xenbus_frontend, type, nodename);
709 free(nodename, M_DEVBUF);
710 return err;
711 }
712
713 /* backend/<typename>/<frontend-uuid>/<name> */
714 static int
715 xenbus_probe_backend_unit(const char *dir,
716 const char *type,
717 const char *name)
718 {
719 char *nodename;
720 int err;
721
722 nodename = kasprintf("%s/%s", dir, name);
723 if (!nodename)
724 return ENOMEM;
725
726 DPRINTK("%s", nodename);
727
728 err = xenbus_probe_node(&xenbus_backend, type, nodename);
729 free(nodename, M_DEVBUF);
730 return err;
731 }
732
733 /* backend/<typename>/<frontend-domid> */
734 static int
735 xenbus_probe_backend(const char *type, const char *domid)
736 {
737 char *nodename;
738 int err;
739 char **dir;
740 unsigned int i, dir_n = 0;
741
742 DPRINTK("");
743
744 nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid);
745 if (!nodename)
746 return ENOMEM;
747
748 err = xenbus_directory(NULL, nodename, "", &dir_n, &dir);
749 DPRINTK("xenbus_probe_backend err %d dir_n %d", err, dir_n);
750 if (err) {
751 free(nodename, M_DEVBUF);
752 return err;
753 }
754
755 for (i = 0; i < dir_n; i++) {
756 err = xenbus_probe_backend_unit(nodename, type, dir[i]);
757 if (err)
758 break;
759 }
760 free(dir, M_DEVBUF);
761 free(nodename, M_DEVBUF);
762 return err;
763 }
764 #endif
765
766 static int
767 xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
768 {
769 int err;
770 char **dir;
771 unsigned int dir_n = 0;
772 int i;
773 struct xenbus_device *xbusd;
774 struct xenbusdev_attach_args xa;
775 char *ep;
776
777 DPRINTK("probe %s type %s", bus->root, type);
778 err = xenbus_directory(NULL, bus->root, type, &dir_n, &dir);
779 DPRINTK("directory err %d dir_n %d", err, dir_n);
780 if (err)
781 return err;
782
783 for (i = 0; i < dir_n; i++) {
784 xbusd = malloc(sizeof(*xbusd), M_DEVBUF, M_WAITOK);
785 if (xbusd == NULL)
786 panic("can't malloc xbusd");
787
788 snprintf(__UNCONST(xbusd->xbusd_path),
789 sizeof(xbusd->xbusd_path), "%s/%s/%s",
790 bus->root, type, dir[i]);
791 DPRINTK("xenbus_probe_device_type probe %s\n",
792 xbusd->xbusd_path);
793 xa.xa_xbusd = xbusd;
794 xa.xa_type = type;
795 xa.xa_id = strtoul(dir[i], &ep, 0);
796 if (dir[i][0] == '\0' || *ep != '\0') {
797 printf("xenbus device type %s: id %s is not a number\n",
798 type, dir[i]);
799 err = EFTYPE;
800 free(xbusd, M_DEVBUF);
801 break;
802 }
803 err = read_backend_details(xbusd);
804 if (err != 0) {
805 printf("xenbus: can't get backend details "
806 "for %s (%d)\n", xbusd->xbusd_path, err);
807 break;
808 }
809 if (config_found_ia(xenbus_device, "xenbus", &xa,
810 xenbus_print) == NULL)
811 free(xbusd, M_DEVBUF);
812 }
813 free(dir, M_DEVBUF);
814 return err;
815 }
816
817 static int
818 xenbus_print(void *aux, const char *pnp)
819 {
820 struct xenbusdev_attach_args *xa = aux;
821
822 if (pnp) {
823 if (strcmp(xa->xa_type, "vbd") == 0)
824 aprint_normal("xbd");
825 else if (strcmp(xa->xa_type, "vif") == 0)
826 aprint_normal("xennet");
827 else
828 aprint_normal("unknown type %s", xa->xa_type);
829 aprint_normal(" at %s", pnp);
830 }
831 aprint_normal(" id %d", xa->xa_id);
832 return(UNCONF);
833 }
834
835 static int
836 xenbus_probe_devices(struct xen_bus_type *bus)
837 {
838 int err;
839 char **dir;
840 unsigned int i, dir_n;
841
842 DPRINTK("probe %s", bus->root);
843 err = xenbus_directory(NULL, bus->root, "", &dir_n, &dir);
844 DPRINTK("directory err %d dir_n %d", err, dir_n);
845 if (err)
846 return err;
847
848 for (i = 0; i < dir_n; i++) {
849 err = xenbus_probe_device_type(bus, dir[i]);
850 if (err)
851 break;
852 }
853 free(dir, M_DEVBUF);
854 return err;
855 }
856
857 #if 0
858 static unsigned int
859 char_count(const char *str, char c)
860 {
861 unsigned int i, ret = 0;
862
863 for (i = 0; str[i]; i++)
864 if (str[i] == c)
865 ret++;
866 return ret;
867 }
868
869 static int
870 strsep_len(const char *str, char c, unsigned int len)
871 {
872 unsigned int i;
873
874 for (i = 0; str[i]; i++)
875 if (str[i] == c) {
876 if (len == 0)
877 return i;
878 len--;
879 }
880 return (len == 0) ? i : -ERANGE;
881 }
882
883 static void
884 dev_changed(const char *node, struct xen_bus_type *bus)
885 {
886 int exists, rootlen;
887 struct xenbus_device *dev;
888 char type[BUS_ID_SIZE];
889 const char *p, *root;
890
891 if (char_count(node, '/') < 2)
892 return;
893
894 exists = xenbus_exists(NULL, node, "");
895 if (!exists) {
896 xenbus_cleanup_devices(node, &bus->bus);
897 return;
898 }
899
900 /* backend/<type>/... or device/<type>/... */
901 p = strchr(node, '/') + 1;
902 snprintf(type, BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p);
903 type[BUS_ID_SIZE-1] = '\0';
904
905 rootlen = strsep_len(node, '/', bus->levels);
906 if (rootlen < 0)
907 return;
908 root = kasprintf("%.*s", rootlen, node);
909 if (!root)
910 return;
911
912 dev = xenbus_device_find(root, &bus->bus);
913 if (!dev)
914 xenbus_probe_node(bus, type, root);
915 else
916 put_device(&dev->dev);
917
918 free(root, M_DEVBUF);
919 }
920 #endif
921
922 static void
923 frontend_changed(struct xenbus_watch *watch,
924 const char **vec, unsigned int len)
925 {
926 DPRINTK("");
927 printf("frontend_changed %s\n", vec[XS_WATCH_PATH]);
928
929 //dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
930 }
931
932 static void
933 backend_changed(struct xenbus_watch *watch,
934 const char **vec, unsigned int len)
935 {
936 DPRINTK("");
937
938 printf("backend_changed %s\n", vec[XS_WATCH_PATH]);
939 //dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
940 }
941
942
943 /* We watch for devices appearing and vanishing. */
944 static struct xenbus_watch fe_watch = {
945 .node = "device",
946 .callback = frontend_changed,
947 };
948
949 static struct xenbus_watch be_watch = {
950 .node = "backend",
951 .callback = backend_changed,
952 };
953
954 #if 0
955 static int suspend_dev(struct device *dev, void *data)
956 {
957 int err = 0;
958 struct xenbus_driver *drv;
959 struct xenbus_device *xdev;
960
961 DPRINTK("");
962
963 if (dev->driver == NULL)
964 return 0;
965 drv = to_xenbus_driver(dev->driver);
966 xdev = container_of(dev, struct xenbus_device, dev);
967 if (drv->suspend)
968 err = drv->suspend(xdev);
969 if (err)
970 printk(KERN_WARNING
971 "xenbus: suspend %s failed: %i\n", dev->bus_id, err);
972 return 0;
973 }
974
975 static int
976 resume_dev(struct device *dev, void *data)
977 {
978 int err;
979 struct xenbus_driver *drv;
980 struct xenbus_device *xdev;
981
982 DPRINTK("");
983
984 if (dev->driver == NULL)
985 return 0;
986 drv = to_xenbus_driver(dev->driver);
987 xdev = container_of(dev, struct xenbus_device, dev);
988
989 err = talk_to_otherend(xdev);
990 if (err) {
991 printk(KERN_WARNING
992 "xenbus: resume (talk_to_otherend) %s failed: %i\n",
993 dev->bus_id, err);
994 return err;
995 }
996
997 if (drv->resume)
998 err = drv->resume(xdev);
999 if (err)
1000 printk(KERN_WARNING
1001 "xenbus: resume %s failed: %i\n", dev->bus_id, err);
1002 return err;
1003 }
1004
1005 void
1006 xenbus_suspend(void)
1007 {
1008 DPRINTK("");
1009
1010 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
1011 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
1012 xs_suspend();
1013 }
1014
1015 void xenbus_resume(struct device *dev)
1016 {
1017 xb_init_comms(dev);
1018 xs_resume();
1019 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
1020 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
1021 }
1022 #endif
1023
1024
1025 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
1026 int xenstored_ready = 0;
1027
1028
1029 #if 0
1030 int
1031 register_xenstore_notifier(struct notifier_block *nb)
1032 {
1033 int ret = 0;
1034
1035 if (xenstored_ready > 0)
1036 ret = nb->notifier_call(nb, 0, NULL);
1037 else
1038 notifier_chain_register(&xenstore_chain, nb);
1039
1040 return ret;
1041 }
1042
1043 void unregister_xenstore_notifier(struct notifier_block *nb)
1044 {
1045 notifier_chain_unregister(&xenstore_chain, nb);
1046 }
1047 #endif
1048
1049
1050
1051 void
1052 xenbus_probe(void *unused)
1053 {
1054 KASSERT((xenstored_ready > 0));
1055
1056 /* Enumerate devices in xenstore. */
1057 xenbus_probe_devices(&xenbus_frontend);
1058 xenbus_probe_devices(&xenbus_backend);
1059
1060 /* Watch for changes. */
1061 register_xenbus_watch(&fe_watch);
1062 register_xenbus_watch(&be_watch);
1063
1064 /* Notify others that xenstore is up */
1065 //notifier_call_chain(&xenstore_chain, 0, NULL);
1066 }
1067
1068 #if 0
1069 static struct proc_dir_entry *xsd_mfn_intf;
1070 static struct proc_dir_entry *xsd_port_intf;
1071
1072
1073 static int
1074 xsd_mfn_read(char *page, char **start, off_t off,
1075 int count, int *eof, void *data)
1076 {
1077 int len;
1078 len = sprintf(page, "%ld", xen_start_info.store_mfn);
1079 *eof = 1;
1080 return len;
1081 }
1082
1083 static int
1084 xsd_port_read(char *page, char **start, off_t off,
1085 int count, int *eof, void *data)
1086 {
1087 int len;
1088
1089 len = sprintf(page, "%d", xen_start_info.store_evtchn);
1090 *eof = 1;
1091 return len;
1092 }
1093 #endif
1094
1095
1096 static void
1097 xenbus_probe_init(void *unused)
1098 {
1099 int err = 0, dom0;
1100
1101 DPRINTK("");
1102
1103 #if 0
1104 if (xen_init() < 0) {
1105 DPRINTK("failed");
1106 return -ENODEV;
1107 }
1108
1109
1110
1111 /* Register ourselves with the kernel bus & device subsystems */
1112 bus_register(&xenbus_frontend.bus);
1113 bus_register(&xenbus_backend.bus);
1114 device_register(&xenbus_frontend.dev);
1115 device_register(&xenbus_backend.dev);
1116 #endif
1117
1118 /*
1119 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
1120 */
1121 dom0 = (xen_start_info.store_evtchn == 0);
1122 #if 0
1123 if (dom0) {
1124 unsigned long page;
1125 evtchn_op_t op = { 0 };
1126 int ret;
1127
1128
1129 // XXX implement
1130 /* Allocate page. */
1131 page = get_zeroed_page(GFP_KERNEL);
1132 if (!page)
1133 return -ENOMEM;
1134
1135 /* We don't refcnt properly, so set reserved on page.
1136 * (this allocation is permanent) */
1137 SetPageReserved(virt_to_page(page));
1138
1139 xen_start_info->store_mfn =
1140 pfn_to_mfn(virt_to_phys((void *)page) >>
1141 PAGE_SHIFT);
1142
1143 /* Next allocate a local port which xenstored can bind to */
1144 op.cmd = EVTCHNOP_alloc_unbound;
1145 op.u.alloc_unbound.dom = DOMID_SELF;
1146 op.u.alloc_unbound.remote_dom = 0;
1147
1148 ret = HYPERVISOR_event_channel_op(&op);
1149 if (ret == 0)
1150 panic("can't register xenstore event");
1151 xen_start_info->store_evtchn = op.u.alloc_unbound.port;
1152
1153 // XXX implement
1154 /* And finally publish the above info in /proc/xen */
1155 if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400)))
1156 xsd_mfn_intf->read_proc = xsd_mfn_read;
1157 if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
1158 xsd_port_intf->read_proc = xsd_port_read;
1159 }
1160 #endif
1161
1162 /* Initialize the interface to xenstore. */
1163 err = xs_init();
1164 if (err) {
1165 printf("XENBUS: Error initializing xenstore comms: %i\n", err);
1166 kthread_exit(err);
1167 }
1168
1169 if (!dom0) {
1170 xenstored_ready = 1;
1171 xenbus_probe(NULL);
1172 }
1173
1174 DPRINTK("done");
1175 config_pending_decr();
1176 kthread_exit(0);
1177 }
1178
1179 /*
1180 * Local variables:
1181 * c-file-style: "linux"
1182 * indent-tabs-mode: t
1183 * c-indent-level: 8
1184 * c-basic-offset: 8
1185 * tab-width: 8
1186 * End:
1187 */
1188