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