summaryrefslogtreecommitdiffstats
path: root/sys/xen/xenbus/xenbus_probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/xen/xenbus/xenbus_probe.c')
-rw-r--r--sys/xen/xenbus/xenbus_probe.c602
1 files changed, 0 insertions, 602 deletions
diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c
deleted file mode 100644
index b1e9a21..0000000
--- a/sys/xen/xenbus/xenbus_probe.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/******************************************************************************
- * Talks to Xen Store to figure out what devices we have.
- *
- * Copyright (C) 2008 Doug Rabson
- * Copyright (C) 2005 Rusty Russell, IBM Corporation
- * Copyright (C) 2005 Mike Wray, Hewlett-Packard
- * Copyright (C) 2005 XenSource Ltd
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#if 0
-#define DPRINTK(fmt, args...) \
- printf("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
-#else
-#define DPRINTK(fmt, args...) ((void)0)
-#endif
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/sysctl.h>
-#include <sys/syslog.h>
-#include <sys/systm.h>
-#include <sys/sx.h>
-#include <sys/taskqueue.h>
-
-#include <machine/xen/xen-os.h>
-#include <machine/stdarg.h>
-
-#include <xen/gnttab.h>
-#include <xen/xenbus/xenbusvar.h>
-#include <xen/xenbus/xenbus_comms.h>
-
-struct xenbus_softc {
- struct xenbus_watch xs_devicewatch;
- struct task xs_probechildren;
- struct intr_config_hook xs_attachcb;
- device_t xs_dev;
-};
-
-struct xenbus_device_ivars {
- struct xenbus_watch xd_otherend_watch; /* must be first */
- struct sx xd_lock;
- device_t xd_dev;
- char *xd_node; /* node name in xenstore */
- char *xd_type; /* xen device type */
- enum xenbus_state xd_state;
- int xd_otherend_id;
- char *xd_otherend_path;
-};
-
-/* Simplified asprintf. */
-char *
-kasprintf(const char *fmt, ...)
-{
- va_list ap;
- unsigned int len;
- char *p, dummy[1];
-
- va_start(ap, fmt);
- /* FIXME: vsnprintf has a bug, NULL should work */
- len = vsnprintf(dummy, 0, fmt, ap);
- va_end(ap);
-
- p = malloc(len + 1, M_DEVBUF, M_WAITOK);
- va_start(ap, fmt);
- vsprintf(p, fmt, ap);
- va_end(ap);
- return p;
-}
-
-static void
-xenbus_identify(driver_t *driver, device_t parent)
-{
-
- BUS_ADD_CHILD(parent, 0, "xenbus", 0);
-}
-
-static int
-xenbus_probe(device_t dev)
-{
- int err = 0;
-
- DPRINTK("");
-
- /* Initialize the interface to xenstore. */
- err = xs_init();
- if (err) {
- log(LOG_WARNING,
- "XENBUS: Error initializing xenstore comms: %i\n", err);
- return (ENXIO);
- }
- err = gnttab_init();
- if (err) {
- log(LOG_WARNING,
- "XENBUS: Error initializing grant table: %i\n", err);
- return (ENXIO);
- }
- device_set_desc(dev, "Xen Devices");
-
- return (0);
-}
-
-static enum xenbus_state
-xenbus_otherend_state(struct xenbus_device_ivars *ivars)
-{
-
- return (xenbus_read_driver_state(ivars->xd_otherend_path));
-}
-
-static void
-xenbus_backend_changed(struct xenbus_watch *watch, const char **vec,
- unsigned int len)
-{
- struct xenbus_device_ivars *ivars;
- device_t dev;
- enum xenbus_state newstate;
-
- ivars = (struct xenbus_device_ivars *) watch;
- dev = ivars->xd_dev;
-
- if (!ivars->xd_otherend_path
- || strncmp(ivars->xd_otherend_path, vec[XS_WATCH_PATH],
- strlen(ivars->xd_otherend_path)))
- return;
-
- newstate = xenbus_otherend_state(ivars);
- XENBUS_BACKEND_CHANGED(dev, newstate);
-}
-
-static int
-xenbus_device_exists(device_t dev, const char *node)
-{
- device_t *kids;
- struct xenbus_device_ivars *ivars;
- int i, count, result;
-
- if (device_get_children(dev, &kids, &count))
- return (FALSE);
-
- result = FALSE;
- for (i = 0; i < count; i++) {
- ivars = device_get_ivars(kids[i]);
- if (!strcmp(ivars->xd_node, node)) {
- result = TRUE;
- break;
- }
- }
- free(kids, M_TEMP);
-
- return (result);
-}
-
-static int
-xenbus_add_device(device_t dev, const char *bus,
- const char *type, const char *id)
-{
- device_t child;
- struct xenbus_device_ivars *ivars;
- enum xenbus_state state;
- char *statepath;
- int error;
-
- ivars = malloc(sizeof(struct xenbus_device_ivars),
- M_DEVBUF, M_ZERO|M_WAITOK);
- ivars->xd_node = kasprintf("%s/%s/%s", bus, type, id);
-
- if (xenbus_device_exists(dev, ivars->xd_node)) {
- /*
- * We are already tracking this node
- */
- free(ivars->xd_node, M_DEVBUF);
- free(ivars, M_DEVBUF);
- return (0);
- }
-
- state = xenbus_read_driver_state(ivars->xd_node);
-
- if (state != XenbusStateInitialising) {
- /*
- * Device is not new, so ignore it. This can
- * happen if a device is going away after
- * switching to Closed.
- */
- free(ivars->xd_node, M_DEVBUF);
- free(ivars, M_DEVBUF);
- return (0);
- }
-
- /*
- * Find the backend details
- */
- error = xenbus_gather(XBT_NIL, ivars->xd_node,
- "backend-id", "%i", &ivars->xd_otherend_id,
- "backend", NULL, &ivars->xd_otherend_path,
- NULL);
- if (error)
- return (error);
-
- sx_init(&ivars->xd_lock, "xdlock");
- ivars->xd_type = strdup(type, M_DEVBUF);
- ivars->xd_state = XenbusStateInitialising;
-
- statepath = malloc(strlen(ivars->xd_otherend_path)
- + strlen("/state") + 1, M_DEVBUF, M_WAITOK);
- sprintf(statepath, "%s/state", ivars->xd_otherend_path);
-
- ivars->xd_otherend_watch.node = statepath;
- ivars->xd_otherend_watch.callback = xenbus_backend_changed;
-
- child = device_add_child(dev, NULL, -1);
- ivars->xd_dev = child;
- device_set_ivars(child, ivars);
-
- return (0);
-}
-
-static int
-xenbus_enumerate_type(device_t dev, const char *bus, const char *type)
-{
- char **dir;
- unsigned int i, count;
- int error;
-
- error = xenbus_directory(XBT_NIL, bus, type, &count, &dir);
- if (error)
- return (error);
- for (i = 0; i < count; i++)
- xenbus_add_device(dev, bus, type, dir[i]);
-
- free(dir, M_DEVBUF);
-
- return (0);
-}
-
-static int
-xenbus_enumerate_bus(device_t dev, const char *bus)
-{
- char **dir;
- unsigned int i, count;
- int error;
-
- error = xenbus_directory(XBT_NIL, bus, "", &count, &dir);
- if (error)
- return (error);
- for (i = 0; i < count; i++) {
- xenbus_enumerate_type(dev, bus, dir[i]);
- }
- free(dir, M_DEVBUF);
-
- return (0);
-}
-
-static int
-xenbus_probe_children(device_t dev)
-{
- device_t *kids;
- struct xenbus_device_ivars *ivars;
- int i, count;
-
- /*
- * Probe any new devices and register watches for any that
- * attach successfully. Since part of the protocol which
- * establishes a connection with the other end is interrupt
- * driven, we sleep until the device reaches a stable state
- * (closed or connected).
- */
- if (device_get_children(dev, &kids, &count) == 0) {
- for (i = 0; i < count; i++) {
- if (device_get_state(kids[i]) != DS_NOTPRESENT)
- continue;
-
- if (device_probe_and_attach(kids[i]))
- continue;
- ivars = device_get_ivars(kids[i]);
- register_xenbus_watch(
- &ivars->xd_otherend_watch);
- sx_xlock(&ivars->xd_lock);
- while (ivars->xd_state != XenbusStateClosed
- && ivars->xd_state != XenbusStateConnected)
- sx_sleep(&ivars->xd_state, &ivars->xd_lock,
- 0, "xdattach", 0);
- sx_xunlock(&ivars->xd_lock);
- }
- free(kids, M_TEMP);
- }
-
- return (0);
-}
-
-static void
-xenbus_probe_children_cb(void *arg, int pending)
-{
- device_t dev = (device_t) arg;
-
- xenbus_probe_children(dev);
-}
-
-static void
-xenbus_devices_changed(struct xenbus_watch *watch,
- const char **vec, unsigned int len)
-{
- struct xenbus_softc *sc = (struct xenbus_softc *) watch;
- device_t dev = sc->xs_dev;
- char *node, *bus, *type, *id, *p;
-
- node = strdup(vec[XS_WATCH_PATH], M_DEVBUF);
- p = strchr(node, '/');
- if (!p)
- goto out;
- bus = node;
- *p = 0;
- type = p + 1;
-
- p = strchr(type, '/');
- if (!p)
- goto out;
- *p = 0;
- id = p + 1;
-
- p = strchr(id, '/');
- if (p)
- *p = 0;
-
- xenbus_add_device(dev, bus, type, id);
- taskqueue_enqueue(taskqueue_thread, &sc->xs_probechildren);
-out:
- free(node, M_DEVBUF);
-}
-
-static void
-xenbus_attach_deferred(void *arg)
-{
- device_t dev = (device_t) arg;
- struct xenbus_softc *sc = device_get_softc(dev);
- int error;
-
- error = xenbus_enumerate_bus(dev, "device");
- if (error)
- return;
- xenbus_probe_children(dev);
-
- sc->xs_dev = dev;
- sc->xs_devicewatch.node = "device";
- sc->xs_devicewatch.callback = xenbus_devices_changed;
-
- TASK_INIT(&sc->xs_probechildren, 0, xenbus_probe_children_cb, dev);
-
- register_xenbus_watch(&sc->xs_devicewatch);
-
- config_intrhook_disestablish(&sc->xs_attachcb);
-}
-
-static int
-xenbus_attach(device_t dev)
-{
- struct xenbus_softc *sc = device_get_softc(dev);
-
- sc->xs_attachcb.ich_func = xenbus_attach_deferred;
- sc->xs_attachcb.ich_arg = dev;
- config_intrhook_establish(&sc->xs_attachcb);
-
- return (0);
-}
-
-static int
-xenbus_suspend(device_t dev)
-{
- int error;
-
- DPRINTK("");
-
- error = bus_generic_suspend(dev);
- if (error)
- return (error);
-
- xs_suspend();
-
- return (0);
-}
-
-static int
-xenbus_resume(device_t dev)
-{
- device_t *kids;
- struct xenbus_device_ivars *ivars;
- int i, count, error;
- char *statepath;
-
- xb_init_comms();
- xs_resume();
-
- /*
- * We must re-examine each device and find the new path for
- * its backend.
- */
- if (device_get_children(dev, &kids, &count) == 0) {
- for (i = 0; i < count; i++) {
- if (device_get_state(kids[i]) == DS_NOTPRESENT)
- continue;
-
- ivars = device_get_ivars(kids[i]);
-
- unregister_xenbus_watch(
- &ivars->xd_otherend_watch);
- ivars->xd_state = XenbusStateInitialising;
-
- /*
- * Find the new backend details and
- * re-register our watch.
- */
- free(ivars->xd_otherend_path, M_DEVBUF);
- error = xenbus_gather(XBT_NIL, ivars->xd_node,
- "backend-id", "%i", &ivars->xd_otherend_id,
- "backend", NULL, &ivars->xd_otherend_path,
- NULL);
- if (error)
- return (error);
-
- DEVICE_RESUME(kids[i]);
-
- statepath = malloc(strlen(ivars->xd_otherend_path)
- + strlen("/state") + 1, M_DEVBUF, M_WAITOK);
- sprintf(statepath, "%s/state", ivars->xd_otherend_path);
-
- free(ivars->xd_otherend_watch.node, M_DEVBUF);
- ivars->xd_otherend_watch.node = statepath;
- register_xenbus_watch(
- &ivars->xd_otherend_watch);
-
-#if 0
- /*
- * Can't do this yet since we are running in
- * the xenwatch thread and if we sleep here,
- * we will stop delivering watch notifications
- * and the device will never come back online.
- */
- sx_xlock(&ivars->xd_lock);
- while (ivars->xd_state != XenbusStateClosed
- && ivars->xd_state != XenbusStateConnected)
- sx_sleep(&ivars->xd_state, &ivars->xd_lock,
- 0, "xdresume", 0);
- sx_xunlock(&ivars->xd_lock);
-#endif
- }
- free(kids, M_TEMP);
- }
-
- return (0);
-}
-
-static int
-xenbus_print_child(device_t dev, device_t child)
-{
- struct xenbus_device_ivars *ivars = device_get_ivars(child);
- int retval = 0;
-
- retval += bus_print_child_header(dev, child);
- retval += printf(" at %s", ivars->xd_node);
- retval += bus_print_child_footer(dev, child);
-
- return (retval);
-}
-
-static int
-xenbus_read_ivar(device_t dev, device_t child, int index,
- uintptr_t * result)
-{
- struct xenbus_device_ivars *ivars = device_get_ivars(child);
-
- switch (index) {
- case XENBUS_IVAR_NODE:
- *result = (uintptr_t) ivars->xd_node;
- return (0);
-
- case XENBUS_IVAR_TYPE:
- *result = (uintptr_t) ivars->xd_type;
- return (0);
-
- case XENBUS_IVAR_STATE:
- *result = (uintptr_t) ivars->xd_state;
- return (0);
-
- case XENBUS_IVAR_OTHEREND_ID:
- *result = (uintptr_t) ivars->xd_otherend_id;
- return (0);
-
- case XENBUS_IVAR_OTHEREND_PATH:
- *result = (uintptr_t) ivars->xd_otherend_path;
- return (0);
- }
-
- return (ENOENT);
-}
-
-static int
-xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
-{
- struct xenbus_device_ivars *ivars = device_get_ivars(child);
- enum xenbus_state newstate;
- int currstate;
- int error;
-
- switch (index) {
- case XENBUS_IVAR_STATE:
- newstate = (enum xenbus_state) value;
- sx_xlock(&ivars->xd_lock);
- if (ivars->xd_state == newstate)
- goto out;
-
- error = xenbus_scanf(XBT_NIL, ivars->xd_node, "state",
- NULL, "%d", &currstate);
- if (error)
- goto out;
-
- error = xenbus_printf(XBT_NIL, ivars->xd_node, "state",
- "%d", newstate);
- if (error) {
- if (newstate != XenbusStateClosing) /* Avoid looping */
- xenbus_dev_fatal(dev, error, "writing new state");
- goto out;
- }
- ivars->xd_state = newstate;
- wakeup(&ivars->xd_state);
- out:
- sx_xunlock(&ivars->xd_lock);
- return (0);
-
- case XENBUS_IVAR_NODE:
- case XENBUS_IVAR_TYPE:
- case XENBUS_IVAR_OTHEREND_ID:
- case XENBUS_IVAR_OTHEREND_PATH:
- /*
- * These variables are read-only.
- */
- return (EINVAL);
- }
-
- return (ENOENT);
-}
-
-SYSCTL_NODE(_dev, OID_AUTO, xen, CTLFLAG_RD, NULL, "Xen");
-SYSCTL_INT(_dev_xen, OID_AUTO, xsd_port, CTLFLAG_RD, &xen_store_evtchn, 0, "");
-SYSCTL_ULONG(_dev_xen, OID_AUTO, xsd_kva, CTLFLAG_RD, (u_long *) &xen_store, 0, "");
-
-static device_method_t xenbus_methods[] = {
- /* Device interface */
- DEVMETHOD(device_identify, xenbus_identify),
- DEVMETHOD(device_probe, xenbus_probe),
- DEVMETHOD(device_attach, xenbus_attach),
- DEVMETHOD(device_detach, bus_generic_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, xenbus_suspend),
- DEVMETHOD(device_resume, xenbus_resume),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, xenbus_print_child),
- DEVMETHOD(bus_read_ivar, xenbus_read_ivar),
- DEVMETHOD(bus_write_ivar, xenbus_write_ivar),
-
- { 0, 0 }
-};
-
-static char driver_name[] = "xenbus";
-static driver_t xenbus_driver = {
- driver_name,
- xenbus_methods,
- sizeof(struct xenbus_softc),
-};
-devclass_t xenbus_devclass;
-
-#ifdef XENHVM
-DRIVER_MODULE(xenbus, xenpci, xenbus_driver, xenbus_devclass, 0, 0);
-#else
-DRIVER_MODULE(xenbus, nexus, xenbus_driver, xenbus_devclass, 0, 0);
-#endif
OpenPOWER on IntegriCloud