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