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