Home | History | Annotate | Line # | Download | only in xenbus
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