Home | History | Annotate | Line # | Download | only in xenbus
xenbus_probe.c revision 1.14.16.1
      1  1.14.16.1   garbled /* $NetBSD: xenbus_probe.c,v 1.14.16.1 2007/10/03 19:26:17 garbled 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.14.16.1   garbled __KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.14.16.1 2007/10/03 19:26:17 garbled 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.13      yamt #include <machine/shutdown_xenbus.h>
     56        1.1    bouyer 
     57        1.1    bouyer #include "xenbus_comms.h"
     58        1.1    bouyer 
     59        1.1    bouyer extern struct semaphore xenwatch_mutex;
     60        1.1    bouyer 
     61        1.1    bouyer #define streq(a, b) (strcmp((a), (b)) == 0)
     62        1.1    bouyer 
     63        1.2    bouyer static int  xenbus_match(struct device *, struct cfdata *, void *);
     64        1.2    bouyer static void xenbus_attach(struct device *, struct device *, void *);
     65        1.2    bouyer static int  xenbus_print(void *, const char *);
     66        1.2    bouyer 
     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.11    bouyer SLIST_HEAD(, xenbus_backend_driver) xenbus_backend_driver_list =
     78       1.11    bouyer 	SLIST_HEAD_INITIALIZER(xenbus_backend_driver);
     79        1.2    bouyer 
     80        1.2    bouyer int
     81        1.2    bouyer xenbus_match(struct device *parent, struct cfdata *match, void *aux)
     82        1.2    bouyer {
     83        1.2    bouyer 	struct xenbus_attach_args *xa = (struct xenbus_attach_args *)aux;
     84        1.2    bouyer 
     85        1.2    bouyer 	if (strcmp(xa->xa_device, "xenbus") == 0)
     86        1.2    bouyer 		return 1;
     87        1.2    bouyer 	return 0;
     88        1.2    bouyer }
     89        1.2    bouyer 
     90        1.2    bouyer static void
     91        1.2    bouyer xenbus_attach(struct device *parent, struct device *self, void *aux)
     92        1.2    bouyer {
     93  1.14.16.1   garbled 	int err;
     94  1.14.16.1   garbled 
     95        1.2    bouyer 	aprint_normal(": Xen Virtual Bus Interface\n");
     96        1.5    bouyer 	xenbus_sc = self;
     97        1.2    bouyer 	config_pending_incr();
     98  1.14.16.1   garbled 
     99  1.14.16.1   garbled 	err = kthread_create(PRI_NONE, 0, NULL, xenbus_probe_init, NULL,
    100  1.14.16.1   garbled 	    NULL, "xenbus_probe");
    101  1.14.16.1   garbled 	if (err)
    102  1.14.16.1   garbled 		printf("kthread_create(xenbus_probe): %d\n", err);
    103        1.2    bouyer }
    104        1.2    bouyer 
    105        1.2    bouyer void
    106       1.11    bouyer xenbus_backend_register(struct xenbus_backend_driver *xbakd)
    107       1.11    bouyer {
    108       1.11    bouyer 	SLIST_INSERT_HEAD(&xenbus_backend_driver_list, xbakd, xbakd_entries);
    109       1.11    bouyer }
    110       1.11    bouyer 
    111        1.2    bouyer static int
    112        1.2    bouyer read_otherend_details(struct xenbus_device *xendev,
    113        1.2    bouyer 				 const char *id_node, const char *path_node)
    114        1.2    bouyer {
    115        1.2    bouyer 	int err;
    116        1.2    bouyer 	char *val, *ep;
    117        1.1    bouyer 
    118        1.2    bouyer 	err = xenbus_read(NULL, xendev->xbusd_path, id_node, NULL, &val);
    119        1.2    bouyer 	if (err) {
    120        1.2    bouyer 		printf("reading other end details %s from %s\n",
    121        1.2    bouyer 		    id_node, xendev->xbusd_path);
    122        1.2    bouyer 		xenbus_dev_fatal(xendev, err,
    123        1.2    bouyer 				 "reading other end details %s from %s",
    124        1.2    bouyer 				 id_node, xendev->xbusd_path);
    125        1.2    bouyer 		return err;
    126        1.2    bouyer 	}
    127        1.2    bouyer 	xendev->xbusd_otherend_id = strtoul(val, &ep, 10);
    128        1.2    bouyer 	if (val[0] == '\0' || *ep != '\0') {
    129        1.2    bouyer 		printf("reading other end details %s from %s: %s is not a number\n", id_node, xendev->xbusd_path, val);
    130        1.2    bouyer 		xenbus_dev_fatal(xendev, err,
    131        1.2    bouyer 		    "reading other end details %s from %s: %s is not a number",
    132        1.2    bouyer 		    id_node, xendev->xbusd_path, val);
    133        1.2    bouyer 		free(val, M_DEVBUF);
    134        1.2    bouyer 		return EFTYPE;
    135        1.2    bouyer 	}
    136        1.2    bouyer 	free(val, M_DEVBUF);
    137        1.2    bouyer 	err = xenbus_read(NULL, xendev->xbusd_path, path_node, NULL, &val);
    138        1.1    bouyer 	if (err) {
    139        1.2    bouyer 		printf("reading other end details %s from %s (%d)\n",
    140        1.2    bouyer 		    path_node, xendev->xbusd_path, err);
    141        1.1    bouyer 		xenbus_dev_fatal(xendev, err,
    142        1.2    bouyer 				 "reading other end details %s from %s",
    143        1.2    bouyer 				 path_node, xendev->xbusd_path);
    144        1.1    bouyer 		return err;
    145        1.1    bouyer 	}
    146        1.3    bouyer 	DPRINTK("read_otherend_details: read %s/%s returned %s\n",
    147        1.3    bouyer 	    xendev->xbusd_path, path_node, val);
    148        1.2    bouyer 	xendev->xbusd_otherend = val;
    149        1.2    bouyer 
    150        1.2    bouyer 	if (strlen(xendev->xbusd_otherend) == 0 ||
    151        1.2    bouyer 	    !xenbus_exists(NULL, xendev->xbusd_otherend, "")) {
    152        1.2    bouyer 		printf("missing other end from %s\n", xendev->xbusd_path);
    153        1.1    bouyer 		xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
    154        1.2    bouyer 				 xendev->xbusd_path);
    155        1.2    bouyer 		free(xendev->xbusd_otherend, M_DEVBUF);
    156        1.2    bouyer 		xendev->xbusd_otherend = NULL;
    157        1.2    bouyer 		return ENOENT;
    158        1.1    bouyer 	}
    159        1.1    bouyer 
    160        1.1    bouyer 	return 0;
    161        1.1    bouyer }
    162        1.1    bouyer 
    163        1.2    bouyer static int
    164        1.2    bouyer read_backend_details(struct xenbus_device *xendev)
    165        1.1    bouyer {
    166        1.1    bouyer 	return read_otherend_details(xendev, "backend-id", "backend");
    167        1.1    bouyer }
    168        1.1    bouyer 
    169        1.1    bouyer 
    170        1.2    bouyer static int
    171        1.2    bouyer read_frontend_details(struct xenbus_device *xendev)
    172        1.1    bouyer {
    173        1.1    bouyer 	return read_otherend_details(xendev, "frontend-id", "frontend");
    174        1.1    bouyer }
    175        1.1    bouyer 
    176        1.3    bouyer #if unused
    177        1.2    bouyer static void
    178        1.2    bouyer free_otherend_details(struct xenbus_device *dev)
    179        1.1    bouyer {
    180        1.2    bouyer 	free(dev->xbusd_otherend, M_DEVBUF);
    181        1.2    bouyer 	dev->xbusd_otherend = NULL;
    182        1.1    bouyer }
    183        1.3    bouyer #endif
    184        1.1    bouyer 
    185        1.1    bouyer 
    186        1.2    bouyer static void
    187        1.2    bouyer free_otherend_watch(struct xenbus_device *dev)
    188        1.1    bouyer {
    189        1.2    bouyer 	if (dev->xbusd_otherend_watch.node) {
    190        1.2    bouyer 		unregister_xenbus_watch(&dev->xbusd_otherend_watch);
    191        1.3    bouyer 		free(dev->xbusd_otherend_watch.node, M_DEVBUF);
    192        1.2    bouyer 		dev->xbusd_otherend_watch.node = NULL;
    193        1.1    bouyer 	}
    194        1.1    bouyer }
    195        1.1    bouyer 
    196        1.2    bouyer static void
    197        1.2    bouyer otherend_changed(struct xenbus_watch *watch,
    198        1.1    bouyer 			     const char **vec, unsigned int len)
    199        1.1    bouyer {
    200        1.3    bouyer 	struct xenbus_device *xdev = watch->xbw_dev;
    201        1.1    bouyer 	XenbusState state;
    202        1.1    bouyer 
    203        1.1    bouyer 	/* Protect us against watches firing on old details when the otherend
    204        1.1    bouyer 	   details change, say immediately after a resume. */
    205        1.3    bouyer 	if (!xdev->xbusd_otherend ||
    206        1.3    bouyer 	    strncmp(xdev->xbusd_otherend, vec[XS_WATCH_PATH],
    207        1.3    bouyer 		    strlen(xdev->xbusd_otherend))) {
    208        1.1    bouyer 		DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
    209        1.1    bouyer 		return;
    210        1.1    bouyer 	}
    211        1.1    bouyer 
    212        1.3    bouyer 	state = xenbus_read_driver_state(xdev->xbusd_otherend);
    213        1.1    bouyer 
    214        1.1    bouyer 	DPRINTK("state is %d, %s, %s",
    215        1.3    bouyer 		state, xdev->xbusd_otherend_watch.node, vec[XS_WATCH_PATH]);
    216        1.5    bouyer 	if (state == XenbusStateClosed) {
    217        1.5    bouyer 		int error;
    218       1.11    bouyer 		if (xdev->xbusd_type == XENBUS_BACKEND_DEVICE) {
    219       1.11    bouyer 			error = xdev->xbusd_u.b.b_detach(
    220       1.11    bouyer 			    xdev->xbusd_u.b.b_cookie);
    221       1.11    bouyer 			if (error) {
    222       1.11    bouyer 				printf("could not detach %s: %d\n",
    223       1.11    bouyer 				    xdev->xbusd_path, error);
    224       1.11    bouyer 				return;
    225       1.11    bouyer 			}
    226       1.11    bouyer 		} else {
    227       1.11    bouyer 			error = config_detach(xdev->xbusd_u.f.f_dev,
    228       1.11    bouyer 			    DETACH_FORCE);
    229       1.11    bouyer 			if (error) {
    230       1.11    bouyer 				printf("could not detach %s: %d\n",
    231       1.11    bouyer 				    xdev->xbusd_u.f.f_dev->dv_xname, error);
    232       1.11    bouyer 				return;
    233       1.11    bouyer 			}
    234        1.5    bouyer 		}
    235        1.5    bouyer 		xenbus_free_device(xdev);
    236        1.5    bouyer 		return;
    237        1.5    bouyer 	}
    238        1.3    bouyer 	if (xdev->xbusd_otherend_changed)
    239       1.11    bouyer 		xdev->xbusd_otherend_changed(
    240       1.11    bouyer 		    (xdev->xbusd_type == XENBUS_BACKEND_DEVICE) ?
    241       1.11    bouyer 		    xdev->xbusd_u.b.b_cookie : xdev->xbusd_u.f.f_dev, state);
    242        1.1    bouyer }
    243        1.1    bouyer 
    244        1.2    bouyer static int
    245        1.2    bouyer talk_to_otherend(struct xenbus_device *dev)
    246        1.1    bouyer {
    247        1.1    bouyer 	free_otherend_watch(dev);
    248        1.1    bouyer 
    249        1.2    bouyer 	return xenbus_watch_path2(dev, dev->xbusd_otherend, "state",
    250        1.3    bouyer 				  &dev->xbusd_otherend_watch,
    251        1.3    bouyer 				  otherend_changed);
    252        1.1    bouyer }
    253        1.1    bouyer 
    254        1.5    bouyer static struct xenbus_device *
    255        1.5    bouyer xenbus_lookup_device_path(const char *path)
    256        1.5    bouyer {
    257        1.5    bouyer 	struct xenbus_device *xbusd;
    258        1.5    bouyer 
    259        1.5    bouyer 	SLIST_FOREACH(xbusd, &xenbus_device_list, xbusd_entries) {
    260        1.5    bouyer 		if (strcmp(xbusd->xbusd_path, path) == 0)
    261        1.5    bouyer 			return xbusd;
    262        1.5    bouyer 	}
    263        1.5    bouyer 	return NULL;
    264        1.5    bouyer }
    265        1.5    bouyer 
    266        1.2    bouyer static int
    267       1.11    bouyer xenbus_probe_device_type(const char *path, const char *type,
    268       1.11    bouyer     int (*create)(struct xenbus_device *))
    269        1.1    bouyer {
    270       1.11    bouyer 	int err, i, msize;
    271       1.11    bouyer 	unsigned long state;
    272        1.1    bouyer 	char **dir;
    273        1.1    bouyer 	unsigned int dir_n = 0;
    274        1.2    bouyer 	struct xenbus_device *xbusd;
    275        1.2    bouyer 	struct xenbusdev_attach_args xa;
    276        1.2    bouyer 	char *ep;
    277        1.2    bouyer 
    278       1.11    bouyer 	DPRINTK("probe %s type %s", path, type);
    279       1.11    bouyer 	err = xenbus_directory(NULL, path, "", &dir_n, &dir);
    280        1.2    bouyer 	DPRINTK("directory err %d dir_n %d", err, dir_n);
    281        1.2    bouyer 	if (err)
    282        1.2    bouyer 		return err;
    283        1.1    bouyer 
    284        1.1    bouyer 	for (i = 0; i < dir_n; i++) {
    285        1.5    bouyer 		/*
    286        1.5    bouyer 		 * add size of path to size of xenbus_device. xenbus_device
    287        1.5    bouyer 		 * already has room for one char in xbusd_path.
    288        1.5    bouyer 		 */
    289       1.11    bouyer 		msize = sizeof(*xbusd) + strlen(path) + strlen(dir[i]) + 2;
    290        1.5    bouyer 		xbusd = malloc(msize, M_DEVBUF, M_WAITOK | M_ZERO);
    291        1.2    bouyer 		if (xbusd == NULL)
    292        1.2    bouyer 			panic("can't malloc xbusd");
    293        1.2    bouyer 
    294        1.2    bouyer 		snprintf(__UNCONST(xbusd->xbusd_path),
    295       1.11    bouyer 		    msize - sizeof(*xbusd) + 1, "%s/%s", path, dir[i]);
    296        1.5    bouyer 		if (xenbus_lookup_device_path(xbusd->xbusd_path) != NULL) {
    297        1.5    bouyer 			/* device already registered */
    298        1.5    bouyer 			free(xbusd, M_DEVBUF);
    299        1.5    bouyer 			continue;
    300        1.5    bouyer 		}
    301       1.11    bouyer 		err = xenbus_read_ul(NULL, xbusd->xbusd_path, "state",
    302       1.12    bouyer 		    &state, 10);
    303       1.11    bouyer 		if (err) {
    304       1.11    bouyer 			printf("xenbus: can't get state "
    305       1.11    bouyer 			    "for %s (%d)\n", xbusd->xbusd_path, err);
    306       1.11    bouyer 			free(xbusd, M_DEVBUF);
    307       1.11    bouyer 			continue;
    308       1.11    bouyer 		}
    309       1.11    bouyer 		if (state != XenbusStateInitialising) {
    310       1.11    bouyer 			/* device is not new */
    311       1.11    bouyer 			free(xbusd, M_DEVBUF);
    312       1.11    bouyer 			continue;
    313       1.11    bouyer 		}
    314        1.5    bouyer 
    315        1.3    bouyer 		xbusd->xbusd_otherend_watch.xbw_dev = xbusd;
    316        1.2    bouyer 		DPRINTK("xenbus_probe_device_type probe %s\n",
    317        1.2    bouyer 		    xbusd->xbusd_path);
    318       1.11    bouyer 		if (create != NULL) {
    319       1.11    bouyer 			xbusd->xbusd_type = XENBUS_BACKEND_DEVICE;
    320       1.11    bouyer 			err = read_frontend_details(xbusd);
    321       1.11    bouyer 			if (err != 0) {
    322       1.11    bouyer 				printf("xenbus: can't get frontend details "
    323       1.11    bouyer 				    "for %s (%d)\n", xbusd->xbusd_path, err);
    324       1.11    bouyer 				break;
    325       1.11    bouyer 			}
    326       1.11    bouyer 			if (create(xbusd)) {
    327       1.11    bouyer 				free(xbusd, M_DEVBUF);
    328       1.11    bouyer 				continue;
    329       1.11    bouyer 			}
    330       1.11    bouyer 		} else {
    331       1.11    bouyer 			xbusd->xbusd_type = XENBUS_FRONTEND_DEVICE;
    332       1.11    bouyer 			xa.xa_xbusd = xbusd;
    333       1.11    bouyer 			xa.xa_type = type;
    334       1.11    bouyer 			xa.xa_id = strtoul(dir[i], &ep, 0);
    335       1.11    bouyer 			if (dir[i][0] == '\0' || *ep != '\0') {
    336       1.11    bouyer 				printf("xenbus device type %s: id %s is not a"
    337       1.11    bouyer 				    " number\n", type, dir[i]);
    338       1.11    bouyer 				err = EFTYPE;
    339       1.11    bouyer 				free(xbusd, M_DEVBUF);
    340       1.11    bouyer 				break;
    341       1.11    bouyer 			}
    342       1.11    bouyer 			err = read_backend_details(xbusd);
    343       1.11    bouyer 			if (err != 0) {
    344       1.11    bouyer 				printf("xenbus: can't get backend details "
    345       1.11    bouyer 				    "for %s (%d)\n", xbusd->xbusd_path, err);
    346       1.11    bouyer 				break;
    347       1.11    bouyer 			}
    348       1.11    bouyer 			xbusd->xbusd_u.f.f_dev = config_found_ia(xenbus_sc,
    349       1.11    bouyer 			    "xenbus", &xa, xenbus_print);
    350       1.11    bouyer 			if (xbusd->xbusd_u.f.f_dev == NULL) {
    351       1.11    bouyer 				free(xbusd, M_DEVBUF);
    352       1.11    bouyer 				continue;
    353       1.11    bouyer 			}
    354        1.3    bouyer 		}
    355       1.11    bouyer 		SLIST_INSERT_HEAD(&xenbus_device_list,
    356       1.11    bouyer 		    xbusd, xbusd_entries);
    357       1.11    bouyer 		talk_to_otherend(xbusd);
    358        1.1    bouyer 	}
    359        1.2    bouyer 	free(dir, M_DEVBUF);
    360        1.1    bouyer 	return err;
    361        1.1    bouyer }
    362        1.1    bouyer 
    363        1.2    bouyer static int
    364        1.2    bouyer xenbus_print(void *aux, const char *pnp)
    365        1.2    bouyer {
    366        1.2    bouyer 	struct xenbusdev_attach_args *xa = aux;
    367        1.2    bouyer 
    368        1.2    bouyer 	if (pnp) {
    369        1.2    bouyer 		if (strcmp(xa->xa_type, "vbd") == 0)
    370        1.2    bouyer 			aprint_normal("xbd");
    371        1.2    bouyer 		else if (strcmp(xa->xa_type, "vif") == 0)
    372        1.2    bouyer 			aprint_normal("xennet");
    373        1.2    bouyer 		else
    374        1.2    bouyer 			aprint_normal("unknown type %s", xa->xa_type);
    375        1.2    bouyer 		aprint_normal(" at %s", pnp);
    376        1.2    bouyer 	}
    377        1.2    bouyer 	aprint_normal(" id %d", xa->xa_id);
    378        1.2    bouyer 	return(UNCONF);
    379        1.2    bouyer }
    380        1.2    bouyer 
    381        1.2    bouyer static int
    382       1.11    bouyer xenbus_probe_frontends(void)
    383        1.1    bouyer {
    384        1.2    bouyer 	int err;
    385        1.1    bouyer 	char **dir;
    386        1.1    bouyer 	unsigned int i, dir_n;
    387       1.11    bouyer 	char path[30];
    388        1.1    bouyer 
    389       1.11    bouyer 	DPRINTK("probe device");
    390       1.11    bouyer 	err = xenbus_directory(NULL, "device", "", &dir_n, &dir);
    391        1.2    bouyer 	DPRINTK("directory err %d dir_n %d", err, dir_n);
    392        1.2    bouyer 	if (err)
    393        1.2    bouyer 		return err;
    394        1.1    bouyer 
    395        1.1    bouyer 	for (i = 0; i < dir_n; i++) {
    396       1.11    bouyer 		snprintf(path, sizeof(path), "device/%s", dir[i]);
    397       1.11    bouyer 		err = xenbus_probe_device_type(path, dir[i], NULL);
    398        1.1    bouyer 		if (err)
    399        1.1    bouyer 			break;
    400        1.1    bouyer 	}
    401        1.2    bouyer 	free(dir, M_DEVBUF);
    402        1.1    bouyer 	return err;
    403        1.1    bouyer }
    404        1.1    bouyer 
    405       1.11    bouyer static int
    406       1.11    bouyer xenbus_probe_backends(void)
    407       1.11    bouyer {
    408       1.11    bouyer 	int err;
    409       1.11    bouyer 	char **dirt, **dirid;
    410       1.11    bouyer 	unsigned int type, id, dirt_n, dirid_n;
    411       1.11    bouyer 	char path[30];
    412       1.11    bouyer 	struct xenbus_backend_driver *xbakd;
    413       1.11    bouyer 
    414       1.11    bouyer 	DPRINTK("probe backend");
    415       1.11    bouyer 	err = xenbus_directory(NULL, "backend", "", &dirt_n, &dirt);
    416       1.11    bouyer 	DPRINTK("directory err %d dirt_n %d", err, dirt_n);
    417       1.11    bouyer 	if (err)
    418       1.11    bouyer 		return err;
    419       1.11    bouyer 
    420       1.11    bouyer 	for (type = 0; type < dirt_n; type++) {
    421       1.11    bouyer 		SLIST_FOREACH(xbakd, &xenbus_backend_driver_list,
    422       1.11    bouyer 		    xbakd_entries) {
    423       1.11    bouyer 			if (strcmp(dirt[type], xbakd->xbakd_type) == 0)
    424       1.11    bouyer 				break;
    425       1.11    bouyer 		}
    426       1.11    bouyer 		if (xbakd == NULL)
    427       1.11    bouyer 			continue;
    428       1.11    bouyer 		err = xenbus_directory(NULL, "backend", dirt[type],
    429       1.11    bouyer 		    &dirid_n, &dirid);
    430       1.11    bouyer 		DPRINTK("directory backend/%s err %d dirid_n %d",
    431       1.11    bouyer 		    dirt[type], err, dirid_n);
    432       1.14  christos 		if (err) {
    433       1.14  christos 			free(dirt, M_DEVBUF); /* to be checked */
    434       1.11    bouyer 			return err;
    435       1.14  christos 		}
    436       1.11    bouyer 		for (id = 0; id < dirid_n; id++) {
    437       1.11    bouyer 			snprintf(path, sizeof(path), "backend/%s/%s",
    438       1.11    bouyer 			    dirt[type], dirid[id]);
    439       1.11    bouyer 			err = xenbus_probe_device_type(path, dirt[type],
    440       1.11    bouyer 			    xbakd->xbakd_create);
    441       1.11    bouyer 			if (err)
    442       1.11    bouyer 				break;
    443       1.11    bouyer 		}
    444       1.11    bouyer 		free(dirid, M_DEVBUF);
    445       1.11    bouyer 	}
    446       1.11    bouyer 	free(dirt, M_DEVBUF);
    447       1.11    bouyer 	return err;
    448       1.11    bouyer }
    449       1.11    bouyer 
    450        1.5    bouyer int
    451        1.5    bouyer xenbus_free_device(struct xenbus_device *xbusd)
    452        1.5    bouyer {
    453        1.5    bouyer 	KASSERT(xenbus_lookup_device_path(xbusd->xbusd_path) == xbusd);
    454        1.5    bouyer 	SLIST_REMOVE(&xenbus_device_list, xbusd, xenbus_device, xbusd_entries);
    455        1.5    bouyer 	free_otherend_watch(xbusd);
    456        1.5    bouyer 	free(xbusd->xbusd_otherend, M_DEVBUF);
    457        1.5    bouyer 	xenbus_switch_state(xbusd, NULL, XenbusStateClosed);
    458        1.5    bouyer 	free(xbusd, M_DEVBUF);
    459        1.5    bouyer 	return 0;
    460        1.5    bouyer }
    461        1.5    bouyer 
    462        1.2    bouyer static void
    463        1.2    bouyer frontend_changed(struct xenbus_watch *watch,
    464        1.1    bouyer 			     const char **vec, unsigned int len)
    465        1.1    bouyer {
    466       1.11    bouyer 	DPRINTK("frontend_changed %s\n", vec[XS_WATCH_PATH]);
    467       1.11    bouyer 	xenbus_probe_frontends();
    468        1.1    bouyer }
    469        1.1    bouyer 
    470        1.2    bouyer static void
    471        1.2    bouyer backend_changed(struct xenbus_watch *watch,
    472        1.1    bouyer 			    const char **vec, unsigned int len)
    473        1.1    bouyer {
    474       1.11    bouyer 	DPRINTK("backend_changed %s\n", vec[XS_WATCH_PATH]);
    475       1.11    bouyer 	xenbus_probe_backends();
    476        1.1    bouyer }
    477        1.1    bouyer 
    478        1.2    bouyer 
    479        1.1    bouyer /* We watch for devices appearing and vanishing. */
    480        1.3    bouyer static struct xenbus_watch fe_watch;
    481        1.1    bouyer 
    482        1.3    bouyer static struct xenbus_watch be_watch;
    483        1.1    bouyer 
    484        1.1    bouyer /* A flag to determine if xenstored is 'ready' (i.e. has started) */
    485        1.1    bouyer int xenstored_ready = 0;
    486        1.1    bouyer 
    487        1.2    bouyer void
    488        1.2    bouyer xenbus_probe(void *unused)
    489        1.1    bouyer {
    490        1.2    bouyer 	KASSERT((xenstored_ready > 0));
    491        1.1    bouyer 
    492        1.1    bouyer 	/* Enumerate devices in xenstore. */
    493       1.11    bouyer 	xenbus_probe_frontends();
    494       1.11    bouyer 	xenbus_probe_backends();
    495        1.1    bouyer 
    496        1.1    bouyer 	/* Watch for changes. */
    497        1.3    bouyer 	fe_watch.node = malloc(strlen("device" + 1), M_DEVBUF, M_NOWAIT);
    498        1.3    bouyer 	strcpy(fe_watch.node, "device");
    499        1.3    bouyer 	fe_watch.xbw_callback = frontend_changed;
    500        1.1    bouyer 	register_xenbus_watch(&fe_watch);
    501        1.3    bouyer 	be_watch.node = malloc(strlen("backend" + 1), M_DEVBUF, M_NOWAIT);
    502        1.3    bouyer 	strcpy(be_watch.node, "backend");
    503        1.3    bouyer 	be_watch.xbw_callback = backend_changed;
    504        1.1    bouyer 	register_xenbus_watch(&be_watch);
    505       1.13      yamt 	shutdown_xenbus_setup();
    506        1.1    bouyer 
    507        1.1    bouyer 	/* Notify others that xenstore is up */
    508        1.2    bouyer 	//notifier_call_chain(&xenstore_chain, 0, NULL);
    509        1.1    bouyer }
    510        1.1    bouyer 
    511        1.2    bouyer static void
    512        1.2    bouyer xenbus_probe_init(void *unused)
    513        1.1    bouyer {
    514        1.1    bouyer 	int err = 0, dom0;
    515        1.1    bouyer 
    516        1.1    bouyer 	DPRINTK("");
    517        1.1    bouyer 
    518        1.5    bouyer 	SLIST_INIT(&xenbus_device_list);
    519        1.5    bouyer 
    520        1.1    bouyer 	/*
    521        1.1    bouyer 	** Domain0 doesn't have a store_evtchn or store_mfn yet.
    522        1.1    bouyer 	*/
    523        1.2    bouyer 	dom0 = (xen_start_info.store_evtchn == 0);
    524        1.1    bouyer 	if (dom0) {
    525        1.7    bouyer #if defined(DOM0OPS)
    526        1.7    bouyer 		vaddr_t page;
    527        1.7    bouyer 		paddr_t ma;
    528        1.1    bouyer 		evtchn_op_t op = { 0 };
    529        1.1    bouyer 		int ret;
    530        1.1    bouyer 
    531        1.1    bouyer 		/* Allocate page. */
    532        1.7    bouyer 		page = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
    533        1.7    bouyer 		    UVM_KMF_ZERO | UVM_KMF_WIRED);
    534        1.1    bouyer 		if (!page)
    535        1.7    bouyer 			panic("can't get xenstore page");
    536        1.1    bouyer 
    537        1.7    bouyer 		(void)pmap_extract_ma(pmap_kernel(), page, &ma);
    538        1.7    bouyer 		xen_start_info.store_mfn = ma >> PAGE_SHIFT;
    539        1.7    bouyer 		xenstore_interface = (void *)page;
    540        1.1    bouyer 
    541        1.1    bouyer 		/* Next allocate a local port which xenstored can bind to */
    542        1.1    bouyer 		op.cmd = EVTCHNOP_alloc_unbound;
    543        1.1    bouyer 		op.u.alloc_unbound.dom        = DOMID_SELF;
    544        1.1    bouyer 		op.u.alloc_unbound.remote_dom = 0;
    545        1.1    bouyer 
    546        1.1    bouyer 		ret = HYPERVISOR_event_channel_op(&op);
    547        1.7    bouyer 		if (ret)
    548        1.2    bouyer 			panic("can't register xenstore event");
    549        1.7    bouyer 		xen_start_info.store_evtchn = op.u.alloc_unbound.port;
    550        1.1    bouyer 
    551        1.7    bouyer 		/* And finally publish the above info in /kern/xen */
    552        1.9    bouyer 		xenbus_kernfs_init();
    553        1.7    bouyer #else /* DOM0OPS */
    554        1.7    bouyer 		return ; /* can't get a working xenstore in this case */
    555        1.7    bouyer #endif /* DOM0OPS */
    556        1.1    bouyer 	}
    557        1.1    bouyer 
    558       1.10    bouyer 	/* register event handler */
    559       1.10    bouyer 	xb_init_comms((struct device *)xenbus_sc);
    560       1.10    bouyer 
    561        1.1    bouyer 	/* Initialize the interface to xenstore. */
    562        1.1    bouyer 	err = xs_init();
    563        1.1    bouyer 	if (err) {
    564        1.2    bouyer 		printf("XENBUS: Error initializing xenstore comms: %i\n", err);
    565        1.2    bouyer 		kthread_exit(err);
    566        1.1    bouyer 	}
    567        1.1    bouyer 
    568        1.1    bouyer 	if (!dom0) {
    569        1.1    bouyer 		xenstored_ready = 1;
    570        1.1    bouyer 		xenbus_probe(NULL);
    571        1.1    bouyer 	}
    572        1.1    bouyer 
    573        1.2    bouyer 	DPRINTK("done");
    574        1.2    bouyer 	config_pending_decr();
    575       1.11    bouyer #ifdef DOM0OPS
    576       1.11    bouyer 	if (dom0) {
    577       1.11    bouyer 		int s;
    578       1.11    bouyer 		s = spltty();
    579       1.11    bouyer 		while (xenstored_ready == 0) {
    580       1.11    bouyer 			tsleep(&xenstored_ready, PRIBIO, "xsready", 0);
    581       1.11    bouyer 			xenbus_probe(NULL);
    582       1.11    bouyer 		}
    583       1.11    bouyer 		splx(s);
    584       1.11    bouyer 	}
    585       1.11    bouyer #endif
    586        1.2    bouyer 	kthread_exit(0);
    587        1.1    bouyer }
    588        1.1    bouyer 
    589        1.1    bouyer /*
    590        1.1    bouyer  * Local variables:
    591        1.1    bouyer  *  c-file-style: "linux"
    592        1.1    bouyer  *  indent-tabs-mode: t
    593        1.1    bouyer  *  c-indent-level: 8
    594        1.1    bouyer  *  c-basic-offset: 8
    595        1.1    bouyer  *  tab-width: 8
    596        1.1    bouyer  * End:
    597        1.1    bouyer  */
    598