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