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