1ff662b5cSJustin T. Gibbs /******************************************************************************
2ff662b5cSJustin T. Gibbs * Talks to Xen Store to figure out what devices we have.
3ff662b5cSJustin T. Gibbs *
4ff662b5cSJustin T. Gibbs * Copyright (C) 2009, 2010 Spectra Logic Corporation
5ff662b5cSJustin T. Gibbs * Copyright (C) 2008 Doug Rabson
6ff662b5cSJustin T. Gibbs * Copyright (C) 2005 Rusty Russell, IBM Corporation
7ff662b5cSJustin T. Gibbs * Copyright (C) 2005 Mike Wray, Hewlett-Packard
8ff662b5cSJustin T. Gibbs * Copyright (C) 2005 XenSource Ltd
9ff662b5cSJustin T. Gibbs *
10ff662b5cSJustin T. Gibbs * This file may be distributed separately from the Linux kernel, or
11ff662b5cSJustin T. Gibbs * incorporated into other software packages, subject to the following license:
12ff662b5cSJustin T. Gibbs *
13ff662b5cSJustin T. Gibbs * Permission is hereby granted, free of charge, to any person obtaining a copy
14ff662b5cSJustin T. Gibbs * of this source file (the "Software"), to deal in the Software without
15ff662b5cSJustin T. Gibbs * restriction, including without limitation the rights to use, copy, modify,
16ff662b5cSJustin T. Gibbs * merge, publish, distribute, sublicense, and/or sell copies of the Software,
17ff662b5cSJustin T. Gibbs * and to permit persons to whom the Software is furnished to do so, subject to
18ff662b5cSJustin T. Gibbs * the following conditions:
19ff662b5cSJustin T. Gibbs *
20ff662b5cSJustin T. Gibbs * The above copyright notice and this permission notice shall be included in
21ff662b5cSJustin T. Gibbs * all copies or substantial portions of the Software.
22ff662b5cSJustin T. Gibbs *
23ff662b5cSJustin T. Gibbs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24ff662b5cSJustin T. Gibbs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25ff662b5cSJustin T. Gibbs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26ff662b5cSJustin T. Gibbs * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27ff662b5cSJustin T. Gibbs * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28ff662b5cSJustin T. Gibbs * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29ff662b5cSJustin T. Gibbs * IN THE SOFTWARE.
30ff662b5cSJustin T. Gibbs */
31ff662b5cSJustin T. Gibbs
32ff662b5cSJustin T. Gibbs /**
33ff662b5cSJustin T. Gibbs * \file xenbusb_front.c
34ff662b5cSJustin T. Gibbs *
35ff662b5cSJustin T. Gibbs * XenBus management of the NewBus bus containing the frontend instances of
36ff662b5cSJustin T. Gibbs * Xen split devices.
37ff662b5cSJustin T. Gibbs */
38fdafd315SWarner Losh
39ff662b5cSJustin T. Gibbs #include <sys/param.h>
40ff662b5cSJustin T. Gibbs #include <sys/bus.h>
41ff662b5cSJustin T. Gibbs #include <sys/kernel.h>
42ff662b5cSJustin T. Gibbs #include <sys/lock.h>
43ff662b5cSJustin T. Gibbs #include <sys/malloc.h>
44ff662b5cSJustin T. Gibbs #include <sys/module.h>
45ff662b5cSJustin T. Gibbs #include <sys/sbuf.h>
46ff662b5cSJustin T. Gibbs #include <sys/sysctl.h>
47ff662b5cSJustin T. Gibbs #include <sys/syslog.h>
48ff662b5cSJustin T. Gibbs #include <sys/systm.h>
49ff662b5cSJustin T. Gibbs #include <sys/sx.h>
50ff662b5cSJustin T. Gibbs #include <sys/taskqueue.h>
51ff662b5cSJustin T. Gibbs
52ff662b5cSJustin T. Gibbs #include <machine/stdarg.h>
53ff662b5cSJustin T. Gibbs
5476acc41fSJustin T. Gibbs #include <xen/xen-os.h>
55ff662b5cSJustin T. Gibbs #include <xen/gnttab.h>
56ff662b5cSJustin T. Gibbs #include <xen/xenbus/xenbusvar.h>
57ff662b5cSJustin T. Gibbs #include <xen/xenbus/xenbusb.h>
58ff662b5cSJustin T. Gibbs
59ff662b5cSJustin T. Gibbs /*------------------ Private Device Attachment Functions --------------------*/
60ff662b5cSJustin T. Gibbs /**
61bc9432d0SGordon Bergling * \brief Probe for the existence of the XenBus front bus.
62ff662b5cSJustin T. Gibbs *
63ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this XenBus front bus instance.
64ff662b5cSJustin T. Gibbs *
65ff662b5cSJustin T. Gibbs * \return Always returns 0 indicating success.
66ff662b5cSJustin T. Gibbs */
67ff662b5cSJustin T. Gibbs static int
xenbusb_front_probe(device_t dev)68ff662b5cSJustin T. Gibbs xenbusb_front_probe(device_t dev)
69ff662b5cSJustin T. Gibbs {
70ff662b5cSJustin T. Gibbs device_set_desc(dev, "Xen Frontend Devices");
71ff662b5cSJustin T. Gibbs
72ff662b5cSJustin T. Gibbs return (0);
73ff662b5cSJustin T. Gibbs }
74ff662b5cSJustin T. Gibbs
75ff662b5cSJustin T. Gibbs /**
76ff662b5cSJustin T. Gibbs * \brief Attach the XenBus front bus.
77ff662b5cSJustin T. Gibbs *
78ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this XenBus front bus instance.
79ff662b5cSJustin T. Gibbs *
80ff662b5cSJustin T. Gibbs * \return On success, 0. Otherwise an errno value indicating the
81ff662b5cSJustin T. Gibbs * type of failure.
82ff662b5cSJustin T. Gibbs */
83ff662b5cSJustin T. Gibbs static int
xenbusb_front_attach(device_t dev)84ff662b5cSJustin T. Gibbs xenbusb_front_attach(device_t dev)
85ff662b5cSJustin T. Gibbs {
86ff662b5cSJustin T. Gibbs return (xenbusb_attach(dev, "device", /*id_components*/1));
87ff662b5cSJustin T. Gibbs }
88ff662b5cSJustin T. Gibbs
89ff662b5cSJustin T. Gibbs /**
90ff662b5cSJustin T. Gibbs * \brief Enumerate all devices of the given type on this bus.
91ff662b5cSJustin T. Gibbs *
92ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this XenBus front bus instance.
93ff662b5cSJustin T. Gibbs * \param type String indicating the device sub-tree (e.g. "vfb", "vif")
94ff662b5cSJustin T. Gibbs * to enumerate.
95ff662b5cSJustin T. Gibbs *
96ff662b5cSJustin T. Gibbs * \return On success, 0. Otherwise an errno value indicating the
97ff662b5cSJustin T. Gibbs * type of failure.
98ff662b5cSJustin T. Gibbs *
99ff662b5cSJustin T. Gibbs * Devices that are found are entered into the NewBus hierarchy via
100ff662b5cSJustin T. Gibbs * xenbusb_add_device(). xenbusb_add_device() ignores duplicate detects
101ff662b5cSJustin T. Gibbs * and ignores duplicate devices, so it can be called unconditionally
102ff662b5cSJustin T. Gibbs * for any device found in the XenStore.
103ff662b5cSJustin T. Gibbs */
104ff662b5cSJustin T. Gibbs static int
xenbusb_front_enumerate_type(device_t dev,const char * type)105ff662b5cSJustin T. Gibbs xenbusb_front_enumerate_type(device_t dev, const char *type)
106ff662b5cSJustin T. Gibbs {
107ff662b5cSJustin T. Gibbs struct xenbusb_softc *xbs;
108ff662b5cSJustin T. Gibbs const char **dir;
109ff662b5cSJustin T. Gibbs unsigned int i, count;
110ff662b5cSJustin T. Gibbs int error;
111ff662b5cSJustin T. Gibbs
112ff662b5cSJustin T. Gibbs xbs = device_get_softc(dev);
113ff662b5cSJustin T. Gibbs error = xs_directory(XST_NIL, xbs->xbs_node, type, &count, &dir);
114ff662b5cSJustin T. Gibbs if (error)
115ff662b5cSJustin T. Gibbs return (error);
116ff662b5cSJustin T. Gibbs for (i = 0; i < count; i++)
117ff662b5cSJustin T. Gibbs xenbusb_add_device(dev, type, dir[i]);
118ff662b5cSJustin T. Gibbs
119ff662b5cSJustin T. Gibbs free(dir, M_XENSTORE);
120ff662b5cSJustin T. Gibbs
121ff662b5cSJustin T. Gibbs return (0);
122ff662b5cSJustin T. Gibbs }
123ff662b5cSJustin T. Gibbs
124ff662b5cSJustin T. Gibbs /**
125ff662b5cSJustin T. Gibbs * \brief Determine and store the XenStore path for the other end of
126ff662b5cSJustin T. Gibbs * a split device whose local end is represented by ivars.
127ff662b5cSJustin T. Gibbs *
128ff662b5cSJustin T. Gibbs * If successful, the xd_otherend_path field of the child's instance
129ff662b5cSJustin T. Gibbs * variables will be updated.
130ff662b5cSJustin T. Gibbs *
131ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this XenBus front bus instance.
132ff662b5cSJustin T. Gibbs * \param ivars Instance variables from the XenBus child device for
133ff662b5cSJustin T. Gibbs * which to perform this function.
134ff662b5cSJustin T. Gibbs *
135ff662b5cSJustin T. Gibbs * \return On success, 0. Otherwise an errno value indicating the
136ff662b5cSJustin T. Gibbs * type of failure.
137ff662b5cSJustin T. Gibbs */
138ff662b5cSJustin T. Gibbs static int
xenbusb_front_get_otherend_node(device_t dev,struct xenbus_device_ivars * ivars)139ff662b5cSJustin T. Gibbs xenbusb_front_get_otherend_node(device_t dev, struct xenbus_device_ivars *ivars)
140ff662b5cSJustin T. Gibbs {
141ff662b5cSJustin T. Gibbs char *otherend_path;
142ff662b5cSJustin T. Gibbs int error;
143ff662b5cSJustin T. Gibbs
144ff662b5cSJustin T. Gibbs if (ivars->xd_otherend_path != NULL) {
145ff662b5cSJustin T. Gibbs free(ivars->xd_otherend_path, M_XENBUS);
146ff662b5cSJustin T. Gibbs ivars->xd_otherend_path = NULL;
147ff662b5cSJustin T. Gibbs }
148ff662b5cSJustin T. Gibbs
149ff662b5cSJustin T. Gibbs error = xs_gather(XST_NIL, ivars->xd_node,
150ff662b5cSJustin T. Gibbs "backend-id", "%i", &ivars->xd_otherend_id,
151ff662b5cSJustin T. Gibbs "backend", NULL, &otherend_path,
152ff662b5cSJustin T. Gibbs NULL);
153ff662b5cSJustin T. Gibbs
154ff662b5cSJustin T. Gibbs if (error == 0) {
155ff662b5cSJustin T. Gibbs ivars->xd_otherend_path = strdup(otherend_path, M_XENBUS);
156283d6f72SJustin T. Gibbs ivars->xd_otherend_path_len = strlen(otherend_path);
157ff662b5cSJustin T. Gibbs free(otherend_path, M_XENSTORE);
158ff662b5cSJustin T. Gibbs }
159ff662b5cSJustin T. Gibbs return (error);
160ff662b5cSJustin T. Gibbs }
161ff662b5cSJustin T. Gibbs
162ff662b5cSJustin T. Gibbs /*-------------------- Private Device Attachment Data -----------------------*/
163ff662b5cSJustin T. Gibbs static device_method_t xenbusb_front_methods[] = {
164ff662b5cSJustin T. Gibbs /* Device interface */
165ff662b5cSJustin T. Gibbs DEVMETHOD(device_identify, xenbusb_identify),
166ff662b5cSJustin T. Gibbs DEVMETHOD(device_probe, xenbusb_front_probe),
167ff662b5cSJustin T. Gibbs DEVMETHOD(device_attach, xenbusb_front_attach),
168ff662b5cSJustin T. Gibbs DEVMETHOD(device_detach, bus_generic_detach),
169ff662b5cSJustin T. Gibbs DEVMETHOD(device_shutdown, bus_generic_shutdown),
170ff662b5cSJustin T. Gibbs DEVMETHOD(device_suspend, bus_generic_suspend),
1712ca7463bSJustin T. Gibbs DEVMETHOD(device_resume, xenbusb_resume),
172ff662b5cSJustin T. Gibbs
173ff662b5cSJustin T. Gibbs /* Bus Interface */
174ff662b5cSJustin T. Gibbs DEVMETHOD(bus_print_child, xenbusb_print_child),
175ff662b5cSJustin T. Gibbs DEVMETHOD(bus_read_ivar, xenbusb_read_ivar),
176ff662b5cSJustin T. Gibbs DEVMETHOD(bus_write_ivar, xenbusb_write_ivar),
177ff662b5cSJustin T. Gibbs DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
178ff662b5cSJustin T. Gibbs DEVMETHOD(bus_release_resource, bus_generic_release_resource),
179ff662b5cSJustin T. Gibbs DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
180ff662b5cSJustin T. Gibbs DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
181ff662b5cSJustin T. Gibbs
182ff662b5cSJustin T. Gibbs /* XenBus Bus Interface */
183ff662b5cSJustin T. Gibbs DEVMETHOD(xenbusb_enumerate_type, xenbusb_front_enumerate_type),
184ff662b5cSJustin T. Gibbs DEVMETHOD(xenbusb_get_otherend_node, xenbusb_front_get_otherend_node),
185*3e5e0e2fSElliott Mitchell
186*3e5e0e2fSElliott Mitchell DEVMETHOD_END
187ff662b5cSJustin T. Gibbs };
188ff662b5cSJustin T. Gibbs
189ff662b5cSJustin T. Gibbs DEFINE_CLASS_0(xenbusb_front, xenbusb_front_driver, xenbusb_front_methods,
190ff662b5cSJustin T. Gibbs sizeof(struct xenbusb_softc));
191ff662b5cSJustin T. Gibbs
192f929eb1eSJohn Baldwin DRIVER_MODULE(xenbusb_front, xenstore, xenbusb_front_driver, 0, 0);
193