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