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