xref: /illumos-gate/usr/src/uts/common/xen/os/xvdi.c (revision 6e24ea8f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Xen virtual device driver interfaces
31  */
32 
33 /*
34  * todo:
35  * + name space clean up:
36  *	xvdi_* - public xen interfaces, for use by all leaf drivers
37  *	xd_* - public xen data structures
38  *	i_xvdi_* - implementation private functions
39  *	xendev_* - xendev driver interfaces, both internal and in cb_ops/bus_ops
40  * + add mdb dcmds to dump ring status
41  * + implement xvdi_xxx to wrap xenbus_xxx read/write function
42  * + convert (xendev_ring_t *) into xvdi_ring_handle_t
43  */
44 #include <sys/conf.h>
45 #include <sys/param.h>
46 #include <sys/kmem.h>
47 #include <vm/seg_kmem.h>
48 #include <sys/debug.h>
49 #include <sys/modctl.h>
50 #include <sys/autoconf.h>
51 #include <sys/ddi_impldefs.h>
52 #include <sys/ddi_subrdefs.h>
53 #include <sys/ddi.h>
54 #include <sys/sunddi.h>
55 #include <sys/sunndi.h>
56 #include <sys/sunldi.h>
57 #include <sys/fs/dv_node.h>
58 #include <sys/avintr.h>
59 #include <sys/psm.h>
60 #include <sys/spl.h>
61 #include <sys/promif.h>
62 #include <sys/list.h>
63 #include <sys/bootconf.h>
64 #include <sys/bootsvcs.h>
65 #include <sys/bootinfo.h>
66 #include <sys/note.h>
67 #ifdef XPV_HVM_DRIVER
68 #include <sys/xpv_support.h>
69 #include <sys/hypervisor.h>
70 #include <public/grant_table.h>
71 #include <public/xen.h>
72 #include <public/io/xenbus.h>
73 #include <public/io/xs_wire.h>
74 #include <public/event_channel.h>
75 #include <public/io/xenbus.h>
76 #else /* XPV_HVM_DRIVER */
77 #include <sys/hypervisor.h>
78 #include <sys/xen_mmu.h>
79 #include <xen/sys/xenbus_impl.h>
80 #include <sys/evtchn_impl.h>
81 #endif /* XPV_HVM_DRIVER */
82 #include <sys/gnttab.h>
83 #include <xen/sys/xendev.h>
84 #include <vm/hat_i86.h>
85 #include <sys/scsi/generic/inquiry.h>
86 #include <util/sscanf.h>
87 #include <xen/public/io/xs_wire.h>
88 
89 
90 #define	isdigit(ch)	((ch) >= '0' && (ch) <= '9')
91 #define	isxdigit(ch)	(isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
92 			((ch) >= 'A' && (ch) <= 'F'))
93 
94 static void xvdi_ring_init_sring(xendev_ring_t *);
95 static void xvdi_ring_init_front_ring(xendev_ring_t *, size_t, size_t);
96 #ifndef XPV_HVM_DRIVER
97 static void xvdi_ring_init_back_ring(xendev_ring_t *, size_t, size_t);
98 #endif
99 static void xvdi_reinit_ring(dev_info_t *, grant_ref_t *, xendev_ring_t *);
100 
101 static int i_xvdi_add_watches(dev_info_t *);
102 static void i_xvdi_rem_watches(dev_info_t *);
103 
104 static int i_xvdi_add_watch_oestate(dev_info_t *);
105 static void i_xvdi_rem_watch_oestate(dev_info_t *);
106 static void i_xvdi_oestate_cb(struct xenbus_device *, XenbusState);
107 static void i_xvdi_oestate_handler(void *);
108 
109 static int i_xvdi_add_watch_hpstate(dev_info_t *);
110 static void i_xvdi_rem_watch_hpstate(dev_info_t *);
111 static void i_xvdi_hpstate_cb(struct xenbus_watch *, const char **,
112     unsigned int);
113 static void i_xvdi_hpstate_handler(void *);
114 
115 static int i_xvdi_add_watch_bepath(dev_info_t *);
116 static void i_xvdi_rem_watch_bepath(dev_info_t *);
117 static void i_xvdi_bepath_cb(struct xenbus_watch *, const char **,
118     unsigned in);
119 
120 static void xendev_offline_device(void *);
121 
122 static void i_xvdi_probe_path_cb(struct xenbus_watch *, const char **,
123     unsigned int);
124 static void i_xvdi_probe_path_handler(void *);
125 
126 typedef struct xd_cfg {
127 	xendev_devclass_t devclass;
128 	char *xsdev;
129 	char *xs_path_fe;
130 	char *xs_path_be;
131 	char *node_fe;
132 	char *node_be;
133 	char *device_type;
134 	int xd_ipl;
135 	int flags;
136 } i_xd_cfg_t;
137 
138 #define	XD_DOM_ZERO	0x01	/* dom0 only. */
139 #define	XD_DOM_GUEST	0x02	/* Guest domains (i.e. non-dom0). */
140 #define	XD_DOM_IO	0x04	/* IO domains. */
141 
142 #define	XD_DOM_ALL	(XD_DOM_ZERO | XD_DOM_GUEST)
143 
144 static i_xd_cfg_t xdci[] = {
145 	{ XEN_CONSOLE, NULL, NULL, NULL, "xencons", NULL,
146 	    "console", IPL_CONS, XD_DOM_ALL, },
147 
148 	{ XEN_VNET, "vif", "device/vif", "backend/vif", "xnf", "xnb",
149 	    "network", IPL_VIF, XD_DOM_ALL, },
150 
151 	{ XEN_VBLK, "vbd", "device/vbd", "backend/vbd", "xdf", "xdb",
152 	    "block", IPL_VBD, XD_DOM_ALL, },
153 
154 	{ XEN_XENBUS, NULL, NULL, NULL, "xenbus", NULL,
155 	    NULL, 0, XD_DOM_ALL, },
156 
157 	{ XEN_DOMCAPS, NULL, NULL, NULL, "domcaps", NULL,
158 	    NULL, 0, XD_DOM_ALL, },
159 
160 	{ XEN_BALLOON, NULL, NULL, NULL, "balloon", NULL,
161 	    NULL, 0, XD_DOM_ALL, },
162 
163 	{ XEN_EVTCHN, NULL, NULL, NULL, "evtchn", NULL,
164 	    NULL, 0, XD_DOM_ZERO, },
165 
166 	{ XEN_PRIVCMD, NULL, NULL, NULL, "privcmd", NULL,
167 	    NULL, 0, XD_DOM_ZERO, },
168 };
169 #define	NXDC	(sizeof (xdci) / sizeof (xdci[0]))
170 
171 static void i_xvdi_enum_fe(dev_info_t *, i_xd_cfg_t *);
172 static void i_xvdi_enum_be(dev_info_t *, i_xd_cfg_t *);
173 static void i_xvdi_enum_worker(dev_info_t *, i_xd_cfg_t *, char *);
174 
175 /*
176  * Xen device channel device access and DMA attributes
177  */
178 static ddi_device_acc_attr_t xendev_dc_accattr = {
179 	DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC
180 };
181 
182 static ddi_dma_attr_t xendev_dc_dmaattr = {
183 	DMA_ATTR_V0,		/* version of this structure */
184 	0,			/* lowest usable address */
185 	0xffffffffffffffffULL,	/* highest usable address */
186 	0x7fffffff,		/* maximum DMAable byte count */
187 	MMU_PAGESIZE,		/* alignment in bytes */
188 	0x7ff,			/* bitmap of burst sizes */
189 	1,			/* minimum transfer */
190 	0xffffffffU,		/* maximum transfer */
191 	0xffffffffffffffffULL,	/* maximum segment length */
192 	1,			/* maximum number of segments */
193 	1,			/* granularity */
194 	0,			/* flags (reserved) */
195 };
196 
197 static dev_info_t *xendev_dip = NULL;
198 
199 #define	XVDI_DBG_STATE	0x01
200 #define	XVDI_DBG_PROBE	0x02
201 
202 #ifdef DEBUG
203 int i_xvdi_debug = 0;
204 
205 #define	XVDI_DPRINTF(flag, format, ...)			\
206 {							\
207 	if (i_xvdi_debug & (flag))			\
208 		prom_printf((format), __VA_ARGS__);	\
209 }
210 #else
211 #define	XVDI_DPRINTF(flag, format, ...)
212 #endif /* DEBUG */
213 
214 static i_xd_cfg_t *
215 i_xvdi_devclass2cfg(xendev_devclass_t devclass)
216 {
217 	i_xd_cfg_t *xdcp;
218 	int i;
219 
220 	for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++)
221 		if (xdcp->devclass == devclass)
222 			return (xdcp);
223 
224 	return (NULL);
225 }
226 
227 int
228 xvdi_init_dev(dev_info_t *dip)
229 {
230 	xendev_devclass_t devcls;
231 	int vdevnum;
232 	domid_t domid;
233 	struct xendev_ppd *pdp;
234 	i_xd_cfg_t *xdcp;
235 	boolean_t backend;
236 	char xsnamebuf[TYPICALMAXPATHLEN];
237 	char *xsname;
238 
239 	devcls = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
240 	    DDI_PROP_DONTPASS, "devclass", XEN_INVAL);
241 	vdevnum = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
242 	    DDI_PROP_DONTPASS, "vdev", VDEV_NOXS);
243 	domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
244 	    DDI_PROP_DONTPASS, "domain", DOMID_SELF);
245 
246 	backend = (domid != DOMID_SELF);
247 	xdcp = i_xvdi_devclass2cfg(devcls);
248 	if (xdcp->device_type != NULL)
249 		(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
250 		    "device_type", xdcp->device_type);
251 
252 	pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP);
253 	pdp->xd_domain = domid;
254 	pdp->xd_vdevnum = vdevnum;
255 	pdp->xd_devclass = devcls;
256 	pdp->xd_evtchn = INVALID_EVTCHN;
257 	mutex_init(&pdp->xd_lk, NULL, MUTEX_DRIVER, NULL);
258 	ddi_set_parent_data(dip, pdp);
259 
260 	/*
261 	 * devices that do not need to interact with xenstore
262 	 */
263 	if (vdevnum == VDEV_NOXS) {
264 		(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
265 		    "unit-address", "0");
266 		if (devcls == XEN_CONSOLE)
267 			(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
268 			    "pm-hardware-state", "needs-suspend-resume");
269 		return (DDI_SUCCESS);
270 	}
271 
272 	/*
273 	 * PV devices that need to probe xenstore
274 	 */
275 
276 	(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
277 	    "pm-hardware-state", "needs-suspend-resume");
278 
279 	xsname = xsnamebuf;
280 	if (!backend)
281 		(void) snprintf(xsnamebuf, sizeof (xsnamebuf),
282 		    "%s/%d", xdcp->xs_path_fe, vdevnum);
283 	else
284 		(void) snprintf(xsnamebuf, sizeof (xsnamebuf),
285 		    "%s/%d/%d", xdcp->xs_path_be, domid, vdevnum);
286 	if ((xenbus_read_driver_state(xsname) >= XenbusStateClosing)) {
287 		/* Don't try to init a dev that may be closing */
288 		mutex_destroy(&pdp->xd_lk);
289 		kmem_free(pdp, sizeof (*pdp));
290 		ddi_set_parent_data(dip, NULL);
291 		return (DDI_FAILURE);
292 	}
293 
294 	pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP);
295 	pdp->xd_xsdev.devicetype = xdcp->xsdev;
296 	pdp->xd_xsdev.frontend = (backend ? 0 : 1);
297 	pdp->xd_xsdev.data = dip;
298 	pdp->xd_xsdev.otherend_id = (backend ? domid : -1);
299 	if (i_xvdi_add_watches(dip) != DDI_SUCCESS) {
300 		cmn_err(CE_WARN, "xvdi_init_dev: "
301 		    "cannot add watches for %s", xsname);
302 		xvdi_uninit_dev(dip);
303 		return (DDI_FAILURE);
304 	}
305 
306 	/*
307 	 * frontend device will use "unit-addr" as
308 	 * the bus address, which will be set here
309 	 */
310 	if (!backend) {
311 		char *prop_str;
312 		unsigned int prop_len, addr, i;
313 		boolean_t use_vdev;
314 		char addr_str[9]; /* hold 32-bit hex */
315 
316 		switch (devcls) {
317 		case XEN_VNET:
318 			if (xenbus_read(XBT_NULL, xsname,
319 			    "mac", (void *)&prop_str, &prop_len) == 0) {
320 				(void) ndi_prop_update_string(DDI_DEV_T_NONE,
321 				    dip, "mac", prop_str);
322 				kmem_free(prop_str, prop_len);
323 			}
324 			prop_str = NULL;
325 			if (xenbus_scanf(XBT_NULL, xsname, "handle", "%u",
326 			    &addr) == 0) {
327 
328 				(void) snprintf(addr_str, sizeof (addr_str),
329 				    "%x", addr);
330 				(void) ndi_prop_update_string(DDI_DEV_T_NONE,
331 				    dip, "unit-address", addr_str);
332 			}
333 			break;
334 		case XEN_VBLK:
335 			if (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend,
336 			    "dev", (void *)&prop_str, &prop_len) != 0)
337 				break;
338 
339 			/*
340 			 * Save a copy of the xenstore "dev" property
341 			 * on the device node.
342 			 */
343 			(void) ndi_prop_update_string(DDI_DEV_T_NONE,
344 			    dip, "xenstore-dev", prop_str);
345 
346 			/*
347 			 * Verify that the "dev" property associated with the
348 			 * otherend device is a 32-bit hex value.  Normally
349 			 * we use this value as the "unit-address" (which is
350 			 * the same as the solaris device bus address).  If
351 			 * the "dev" property is not a32-bit hex value then
352 			 * that usually means we're in an HVM environment
353 			 * where the disk names have been specified via
354 			 * non-integer values.  In this case we'll fall
355 			 * back to using the devices vdev value (which is
356 			 * really just its xenstore id) as its unit-address.
357 			 */
358 			i = 0;
359 			use_vdev = B_FALSE;
360 			while (prop_str[i] != '\0') {
361 				if ((!isxdigit(prop_str[i++])) ||
362 				    (prop_str[i++] >= 8)) {
363 					use_vdev = B_TRUE;
364 					break;
365 				}
366 			}
367 			if (use_vdev) {
368 				/*
369 				 * Use the xenstore device id as the
370 				 * devices "unit-address".
371 				 */
372 				addr = vdevnum;
373 			} else {
374 				/*
375 				 * Use the xenstore "dev" property as the
376 				 * devices "unit-address".
377 				 */
378 				(void) sscanf(prop_str, "%x", &addr);
379 			}
380 			kmem_free(prop_str, prop_len);
381 			(void) snprintf(addr_str, sizeof (addr_str),
382 			    "%x", addr);
383 			(void) ndi_prop_update_string(DDI_DEV_T_NONE,
384 			    dip, "unit-address", addr_str);
385 			break;
386 		default:
387 			break;
388 		}
389 	}
390 
391 	return (DDI_SUCCESS);
392 }
393 
394 void
395 xvdi_uninit_dev(dev_info_t *dip)
396 {
397 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
398 
399 	if (pdp != NULL) {
400 		/* Remove any registered callbacks. */
401 		xvdi_remove_event_handler(dip, NULL);
402 
403 		/* Remove any registered watches. */
404 		i_xvdi_rem_watches(dip);
405 
406 		/* tell other end to close */
407 		if (pdp->xd_xsdev.otherend_id != (domid_t)-1)
408 			(void) xvdi_switch_state(dip, XBT_NULL,
409 			    XenbusStateClosed);
410 
411 		if (pdp->xd_xsdev.nodename != NULL)
412 			kmem_free((char *)(pdp->xd_xsdev.nodename),
413 			    strlen(pdp->xd_xsdev.nodename) + 1);
414 
415 		ddi_set_parent_data(dip, NULL);
416 
417 		mutex_destroy(&pdp->xd_lk);
418 		kmem_free(pdp, sizeof (*pdp));
419 	}
420 }
421 
422 /*
423  * Bind the event channel for this device instance.
424  * Currently we only support one evtchn per device instance.
425  */
426 int
427 xvdi_bind_evtchn(dev_info_t *dip, evtchn_port_t evtchn)
428 {
429 	struct xendev_ppd *pdp;
430 	domid_t oeid;
431 	int r;
432 
433 	pdp = ddi_get_parent_data(dip);
434 	ASSERT(pdp != NULL);
435 	ASSERT(pdp->xd_evtchn == INVALID_EVTCHN);
436 
437 	mutex_enter(&pdp->xd_lk);
438 	if (pdp->xd_devclass == XEN_CONSOLE) {
439 		if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
440 			pdp->xd_evtchn = xen_info->console.domU.evtchn;
441 		} else {
442 			pdp->xd_evtchn = INVALID_EVTCHN;
443 			mutex_exit(&pdp->xd_lk);
444 			return (DDI_SUCCESS);
445 		}
446 	} else {
447 		oeid = pdp->xd_xsdev.otherend_id;
448 		if (oeid == (domid_t)-1) {
449 			mutex_exit(&pdp->xd_lk);
450 			return (DDI_FAILURE);
451 		}
452 
453 		if ((r = xen_bind_interdomain(oeid, evtchn, &pdp->xd_evtchn))) {
454 			xvdi_dev_error(dip, r, "bind event channel");
455 			mutex_exit(&pdp->xd_lk);
456 			return (DDI_FAILURE);
457 		}
458 	}
459 #ifndef XPV_HVM_DRIVER
460 	pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
461 #endif
462 	mutex_exit(&pdp->xd_lk);
463 
464 	return (DDI_SUCCESS);
465 }
466 
467 /*
468  * Allocate an event channel for this device instance.
469  * Currently we only support one evtchn per device instance.
470  */
471 int
472 xvdi_alloc_evtchn(dev_info_t *dip)
473 {
474 	struct xendev_ppd *pdp;
475 	domid_t oeid;
476 	int rv;
477 
478 	pdp = ddi_get_parent_data(dip);
479 	ASSERT(pdp != NULL);
480 	ASSERT(pdp->xd_evtchn == INVALID_EVTCHN);
481 
482 	mutex_enter(&pdp->xd_lk);
483 	if (pdp->xd_devclass == XEN_CONSOLE) {
484 		if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
485 			pdp->xd_evtchn = xen_info->console.domU.evtchn;
486 		} else {
487 			pdp->xd_evtchn = INVALID_EVTCHN;
488 			mutex_exit(&pdp->xd_lk);
489 			return (DDI_SUCCESS);
490 		}
491 	} else {
492 		oeid = pdp->xd_xsdev.otherend_id;
493 		if (oeid == (domid_t)-1) {
494 			mutex_exit(&pdp->xd_lk);
495 			return (DDI_FAILURE);
496 		}
497 
498 		if ((rv = xen_alloc_unbound_evtchn(oeid, &pdp->xd_evtchn))) {
499 			xvdi_dev_error(dip, rv, "bind event channel");
500 			mutex_exit(&pdp->xd_lk);
501 			return (DDI_FAILURE);
502 		}
503 	}
504 #ifndef XPV_HVM_DRIVER
505 	pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
506 #endif
507 	mutex_exit(&pdp->xd_lk);
508 
509 	return (DDI_SUCCESS);
510 }
511 
512 /*
513  * Unbind the event channel for this device instance.
514  * Currently we only support one evtchn per device instance.
515  */
516 void
517 xvdi_free_evtchn(dev_info_t *dip)
518 {
519 	struct xendev_ppd *pdp;
520 
521 	pdp = ddi_get_parent_data(dip);
522 	ASSERT(pdp != NULL);
523 
524 	mutex_enter(&pdp->xd_lk);
525 	if (pdp->xd_evtchn != INVALID_EVTCHN) {
526 #ifndef XPV_HVM_DRIVER
527 		ec_unbind_irq(pdp->xd_ispec.intrspec_vec);
528 		pdp->xd_ispec.intrspec_vec = 0;
529 #endif
530 		pdp->xd_evtchn = INVALID_EVTCHN;
531 	}
532 	mutex_exit(&pdp->xd_lk);
533 }
534 
535 #ifndef XPV_HVM_DRIVER
536 /*
537  * Map an inter-domain communication ring for a virtual device.
538  * This is used by backend drivers.
539  */
540 int
541 xvdi_map_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
542     grant_ref_t gref, xendev_ring_t **ringpp)
543 {
544 	domid_t oeid;
545 	gnttab_map_grant_ref_t mapop;
546 	gnttab_unmap_grant_ref_t unmapop;
547 	caddr_t ringva;
548 	ddi_acc_hdl_t *ap;
549 	ddi_acc_impl_t *iap;
550 	xendev_ring_t *ring;
551 	int err;
552 	char errstr[] = "mapping in ring buffer";
553 
554 	ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
555 	oeid = xvdi_get_oeid(dip);
556 
557 	/* alloc va in backend dom for ring buffer */
558 	ringva = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE,
559 	    0, 0, 0, 0, VM_SLEEP);
560 
561 	/* map in ring page */
562 	hat_prepare_mapping(kas.a_hat, ringva);
563 	mapop.host_addr = (uint64_t)(uintptr_t)ringva;
564 	mapop.flags = GNTMAP_host_map;
565 	mapop.ref = gref;
566 	mapop.dom = oeid;
567 	err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &mapop, 1);
568 	if (err) {
569 		xvdi_fatal_error(dip, err, errstr);
570 		goto errout1;
571 	}
572 
573 	if (mapop.status != 0) {
574 		xvdi_fatal_error(dip, err, errstr);
575 		goto errout2;
576 	}
577 	ring->xr_vaddr = ringva;
578 	ring->xr_grant_hdl = mapop.handle;
579 	ring->xr_gref = gref;
580 
581 	/*
582 	 * init an acc handle and associate it w/ this ring
583 	 * this is only for backend drivers. we get the memory by calling
584 	 * vmem_xalloc(), instead of calling any ddi function, so we have
585 	 * to init an acc handle by ourselves
586 	 */
587 	ring->xr_acc_hdl = impl_acc_hdl_alloc(KM_SLEEP, NULL);
588 	ap = impl_acc_hdl_get(ring->xr_acc_hdl);
589 	ap->ah_vers = VERS_ACCHDL;
590 	ap->ah_dip = dip;
591 	ap->ah_xfermodes = DDI_DMA_CONSISTENT;
592 	ap->ah_acc = xendev_dc_accattr;
593 	iap = (ddi_acc_impl_t *)ap->ah_platform_private;
594 	iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR;
595 	impl_acc_hdl_init(ap);
596 	ap->ah_offset = 0;
597 	ap->ah_len = (off_t)PAGESIZE;
598 	ap->ah_addr = ring->xr_vaddr;
599 
600 	/* init backend ring */
601 	xvdi_ring_init_back_ring(ring, nentry, entrysize);
602 
603 	*ringpp = ring;
604 
605 	return (DDI_SUCCESS);
606 
607 errout2:
608 	/* unmap ring page */
609 	unmapop.host_addr = (uint64_t)(uintptr_t)ringva;
610 	unmapop.handle = ring->xr_grant_hdl;
611 	unmapop.dev_bus_addr = NULL;
612 	(void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
613 	hat_release_mapping(kas.a_hat, ringva);
614 errout1:
615 	vmem_xfree(heap_arena, ringva, PAGESIZE);
616 	kmem_free(ring, sizeof (xendev_ring_t));
617 	return (DDI_FAILURE);
618 }
619 
620 /*
621  * Unmap a ring for a virtual device.
622  * This is used by backend drivers.
623  */
624 void
625 xvdi_unmap_ring(xendev_ring_t *ring)
626 {
627 	gnttab_unmap_grant_ref_t unmapop;
628 
629 	ASSERT((ring != NULL) && (ring->xr_vaddr != NULL));
630 
631 	impl_acc_hdl_free(ring->xr_acc_hdl);
632 	unmapop.host_addr = (uint64_t)(uintptr_t)ring->xr_vaddr;
633 	unmapop.handle = ring->xr_grant_hdl;
634 	unmapop.dev_bus_addr = NULL;
635 	(void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
636 	hat_release_mapping(kas.a_hat, ring->xr_vaddr);
637 	vmem_xfree(heap_arena, ring->xr_vaddr, PAGESIZE);
638 	kmem_free(ring, sizeof (xendev_ring_t));
639 }
640 #endif /* XPV_HVM_DRIVER */
641 
642 /*
643  * Re-initialise an inter-domain communications ring for the backend domain.
644  * ring will be re-initialized after re-grant succeed
645  * ring will be freed if fails to re-grant access to backend domain
646  * so, don't keep useful data in the ring
647  * used only in frontend driver
648  */
649 static void
650 xvdi_reinit_ring(dev_info_t *dip, grant_ref_t *gref, xendev_ring_t *ringp)
651 {
652 	paddr_t rpaddr;
653 	maddr_t rmaddr;
654 
655 	ASSERT((ringp != NULL) && (ringp->xr_paddr != 0));
656 	rpaddr = ringp->xr_paddr;
657 
658 	rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? rpaddr : pa_to_ma(rpaddr);
659 	gnttab_grant_foreign_access_ref(ringp->xr_gref, xvdi_get_oeid(dip),
660 	    rmaddr >> PAGESHIFT, 0);
661 	*gref = ringp->xr_gref;
662 
663 	/* init frontend ring */
664 	xvdi_ring_init_sring(ringp);
665 	xvdi_ring_init_front_ring(ringp, ringp->xr_sring.fr.nr_ents,
666 	    ringp->xr_entry_size);
667 }
668 
669 /*
670  * allocate Xen inter-domain communications ring for Xen virtual devices
671  * used only in frontend driver
672  * if *ringpp is not NULL, we'll simply re-init it
673  */
674 int
675 xvdi_alloc_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
676     grant_ref_t *gref, xendev_ring_t **ringpp)
677 {
678 	size_t len;
679 	xendev_ring_t *ring;
680 	ddi_dma_cookie_t dma_cookie;
681 	uint_t ncookies;
682 	grant_ref_t ring_gref;
683 	domid_t oeid;
684 	maddr_t rmaddr;
685 
686 	if (*ringpp) {
687 		xvdi_reinit_ring(dip, gref, *ringpp);
688 		return (DDI_SUCCESS);
689 	}
690 
691 	*ringpp = ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
692 	oeid = xvdi_get_oeid(dip);
693 
694 	/*
695 	 * Allocate page for this ring buffer
696 	 */
697 	if (ddi_dma_alloc_handle(dip, &xendev_dc_dmaattr, DDI_DMA_SLEEP,
698 	    0, &ring->xr_dma_hdl) != DDI_SUCCESS)
699 		goto err;
700 
701 	if (ddi_dma_mem_alloc(ring->xr_dma_hdl, PAGESIZE,
702 	    &xendev_dc_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
703 	    &ring->xr_vaddr, &len, &ring->xr_acc_hdl) != DDI_SUCCESS) {
704 		ddi_dma_free_handle(&ring->xr_dma_hdl);
705 		goto err;
706 	}
707 
708 	if (ddi_dma_addr_bind_handle(ring->xr_dma_hdl, NULL,
709 	    ring->xr_vaddr, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
710 	    DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_DMA_MAPPED) {
711 		ddi_dma_mem_free(&ring->xr_acc_hdl);
712 		ring->xr_vaddr = NULL;
713 		ddi_dma_free_handle(&ring->xr_dma_hdl);
714 		goto err;
715 	}
716 	ASSERT(ncookies == 1);
717 	ring->xr_paddr = dma_cookie.dmac_laddress;
718 	rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? ring->xr_paddr :
719 	    pa_to_ma(ring->xr_paddr);
720 
721 	if ((ring_gref = gnttab_grant_foreign_access(oeid,
722 	    rmaddr >> PAGESHIFT, 0)) == (grant_ref_t)-1) {
723 		(void) ddi_dma_unbind_handle(ring->xr_dma_hdl);
724 		ddi_dma_mem_free(&ring->xr_acc_hdl);
725 		ring->xr_vaddr = NULL;
726 		ddi_dma_free_handle(&ring->xr_dma_hdl);
727 		goto err;
728 	}
729 	*gref = ring->xr_gref = ring_gref;
730 
731 	/* init frontend ring */
732 	xvdi_ring_init_sring(ring);
733 	xvdi_ring_init_front_ring(ring, nentry, entrysize);
734 
735 	return (DDI_SUCCESS);
736 
737 err:
738 	kmem_free(ring, sizeof (xendev_ring_t));
739 	return (DDI_FAILURE);
740 }
741 
742 /*
743  * Release ring buffers allocated for Xen devices
744  * used for frontend driver
745  */
746 void
747 xvdi_free_ring(xendev_ring_t *ring)
748 {
749 	ASSERT((ring != NULL) && (ring->xr_vaddr != NULL));
750 
751 	(void) gnttab_end_foreign_access_ref(ring->xr_gref, 0);
752 	(void) ddi_dma_unbind_handle(ring->xr_dma_hdl);
753 	ddi_dma_mem_free(&ring->xr_acc_hdl);
754 	ddi_dma_free_handle(&ring->xr_dma_hdl);
755 	kmem_free(ring, sizeof (xendev_ring_t));
756 }
757 
758 dev_info_t *
759 xvdi_create_dev(dev_info_t *parent, xendev_devclass_t devclass,
760     domid_t dom, int vdev)
761 {
762 	dev_info_t *dip;
763 	boolean_t backend;
764 	i_xd_cfg_t *xdcp;
765 	char xsnamebuf[TYPICALMAXPATHLEN];
766 	char *type, *node = NULL, *xsname = NULL;
767 	unsigned int tlen;
768 	int ret;
769 
770 	ASSERT(DEVI_BUSY_OWNED(parent));
771 
772 	backend = (dom != DOMID_SELF);
773 	xdcp = i_xvdi_devclass2cfg(devclass);
774 	ASSERT(xdcp != NULL);
775 
776 	if (vdev != VDEV_NOXS) {
777 		if (!backend) {
778 			(void) snprintf(xsnamebuf, sizeof (xsnamebuf),
779 			    "%s/%d", xdcp->xs_path_fe, vdev);
780 			xsname = xsnamebuf;
781 			node = xdcp->node_fe;
782 		} else {
783 			(void) snprintf(xsnamebuf, sizeof (xsnamebuf),
784 			    "%s/%d/%d", xdcp->xs_path_be, dom, vdev);
785 			xsname = xsnamebuf;
786 			node = xdcp->node_be;
787 		}
788 	} else {
789 		node = xdcp->node_fe;
790 	}
791 
792 	/* Must have a driver to use. */
793 	if (node == NULL)
794 		return (NULL);
795 
796 	/*
797 	 * We need to check the state of this device before we go
798 	 * further, otherwise we'll end up with a dead loop if
799 	 * anything goes wrong.
800 	 */
801 	if ((xsname != NULL) &&
802 	    (xenbus_read_driver_state(xsname) >= XenbusStateClosing))
803 		return (NULL);
804 
805 	ndi_devi_alloc_sleep(parent, node, DEVI_SID_NODEID, &dip);
806 
807 	/*
808 	 * Driver binding uses the compatible property _before_ the
809 	 * node name, so we set the node name to the 'model' of the
810 	 * device (i.e. 'xnb' or 'xdb') and, if 'type' is present,
811 	 * encode both the model and the type in a compatible property
812 	 * (i.e. 'xnb,netfront' or 'xnb,SUNW_mac').  This allows a
813 	 * driver binding based on the <model,type> pair _before_ a
814 	 * binding based on the node name.
815 	 */
816 	if ((xsname != NULL) &&
817 	    (xenbus_read(XBT_NULL, xsname, "type", (void *)&type, &tlen)
818 	    == 0)) {
819 		size_t clen;
820 		char *c[1];
821 
822 		clen = strlen(node) + strlen(type) + 2;
823 		c[0] = kmem_alloc(clen, KM_SLEEP);
824 		(void) snprintf(c[0], clen, "%s,%s", node, type);
825 
826 		(void) ndi_prop_update_string_array(DDI_DEV_T_NONE,
827 		    dip, "compatible", (char **)c, 1);
828 
829 		kmem_free(c[0], clen);
830 		kmem_free(type, tlen);
831 	}
832 
833 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "devclass", devclass);
834 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "domain", dom);
835 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vdev", vdev);
836 
837 	if (i_ddi_devi_attached(parent))
838 		ret = ndi_devi_online(dip, 0);
839 	else
840 		ret = ndi_devi_bind_driver(dip, 0);
841 	if (ret != NDI_SUCCESS)
842 		(void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
843 
844 	return (dip);
845 }
846 
847 /*
848  * xendev_enum_class()
849  */
850 void
851 xendev_enum_class(dev_info_t *parent, xendev_devclass_t devclass)
852 {
853 	boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info);
854 	boolean_t domU = !dom0;
855 	i_xd_cfg_t *xdcp;
856 
857 	xdcp = i_xvdi_devclass2cfg(devclass);
858 	ASSERT(xdcp != NULL);
859 
860 	if (dom0 && !(xdcp->flags & XD_DOM_ZERO))
861 		return;
862 
863 	if (domU && !(xdcp->flags & XD_DOM_GUEST))
864 		return;
865 
866 	if (xdcp->xsdev == NULL) {
867 		int circ;
868 
869 		/*
870 		 * Don't need to probe this kind of device from the
871 		 * store, just create one if it doesn't exist.
872 		 */
873 
874 		ndi_devi_enter(parent, &circ);
875 		if (xvdi_find_dev(parent, devclass, DOMID_SELF, VDEV_NOXS)
876 		    == NULL)
877 			(void) xvdi_create_dev(parent, devclass,
878 			    DOMID_SELF, VDEV_NOXS);
879 		ndi_devi_exit(parent, circ);
880 	} else {
881 		/*
882 		 * Probe this kind of device from the store, both
883 		 * frontend and backend.
884 		 */
885 
886 		i_xvdi_enum_fe(parent, xdcp);
887 		i_xvdi_enum_be(parent, xdcp);
888 	}
889 }
890 
891 /*
892  * xendev_enum_all()
893  */
894 void
895 xendev_enum_all(dev_info_t *parent, boolean_t store_unavailable)
896 {
897 	int i;
898 	i_xd_cfg_t *xdcp;
899 	boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info);
900 
901 	for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) {
902 		/*
903 		 * Dom0 relies on watchpoints to create non-soft
904 		 * devices - don't attempt to iterate over the store.
905 		 */
906 		if (dom0 && (xdcp->xsdev != NULL))
907 			continue;
908 
909 		/*
910 		 * If the store is not yet available, don't attempt to
911 		 * iterate.
912 		 */
913 		if (store_unavailable && (xdcp->xsdev != NULL))
914 			continue;
915 
916 		xendev_enum_class(parent, xdcp->devclass);
917 	}
918 }
919 
920 xendev_devclass_t
921 xendev_nodename_to_devclass(char *nodename)
922 {
923 	int i;
924 	i_xd_cfg_t *xdcp;
925 
926 	/*
927 	 * This relies on the convention that variants of a base
928 	 * driver share the same prefix and that there are no drivers
929 	 * which share a common prefix with the name of any other base
930 	 * drivers.
931 	 *
932 	 * So for a base driver 'xnb' (which is the name listed in
933 	 * xdci) the variants all begin with the string 'xnb' (in fact
934 	 * they are 'xnbe', 'xnbo' and 'xnbu') and there are no other
935 	 * base drivers which have the prefix 'xnb'.
936 	 */
937 	ASSERT(nodename != NULL);
938 	for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) {
939 		if (((xdcp->node_fe != NULL) &&
940 		    (strncmp(nodename, xdcp->node_fe,
941 		    strlen(xdcp->node_fe)) == 0)) ||
942 		    ((xdcp->node_be != NULL) &&
943 		    (strncmp(nodename, xdcp->node_be,
944 		    strlen(xdcp->node_be)) == 0)))
945 
946 			return (xdcp->devclass);
947 	}
948 	return (XEN_INVAL);
949 }
950 
951 int
952 xendev_devclass_ipl(xendev_devclass_t devclass)
953 {
954 	i_xd_cfg_t *xdcp;
955 
956 	xdcp = i_xvdi_devclass2cfg(devclass);
957 	ASSERT(xdcp != NULL);
958 
959 	return (xdcp->xd_ipl);
960 }
961 
962 /*
963  * Determine if a devinfo instance exists of a particular device
964  * class, domain and xenstore virtual device number.
965  */
966 dev_info_t *
967 xvdi_find_dev(dev_info_t *parent, xendev_devclass_t devclass,
968     domid_t dom, int vdev)
969 {
970 	dev_info_t *dip;
971 
972 	ASSERT(DEVI_BUSY_OWNED(parent));
973 
974 	switch (devclass) {
975 	case XEN_CONSOLE:
976 	case XEN_XENBUS:
977 	case XEN_DOMCAPS:
978 	case XEN_BALLOON:
979 	case XEN_EVTCHN:
980 	case XEN_PRIVCMD:
981 		/* Console and soft devices have no vdev. */
982 		vdev = VDEV_NOXS;
983 		break;
984 	default:
985 		break;
986 	}
987 
988 	for (dip = ddi_get_child(parent); dip != NULL;
989 	    dip = ddi_get_next_sibling(dip)) {
990 		int *vdevnump, *domidp, *devclsp, vdevnum;
991 		uint_t ndomid, nvdevnum, ndevcls;
992 		xendev_devclass_t devcls;
993 		domid_t domid;
994 		struct xendev_ppd *pdp = ddi_get_parent_data(dip);
995 
996 		if (pdp == NULL) {
997 			if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
998 			    DDI_PROP_DONTPASS, "domain", &domidp, &ndomid) !=
999 			    DDI_PROP_SUCCESS)
1000 				continue;
1001 			ASSERT(ndomid == 1);
1002 			domid = (domid_t)*domidp;
1003 			ddi_prop_free(domidp);
1004 
1005 			if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
1006 			    DDI_PROP_DONTPASS, "vdev", &vdevnump, &nvdevnum) !=
1007 			    DDI_PROP_SUCCESS)
1008 				continue;
1009 			ASSERT(nvdevnum == 1);
1010 			vdevnum = *vdevnump;
1011 			ddi_prop_free(vdevnump);
1012 
1013 			if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
1014 			    DDI_PROP_DONTPASS, "devclass", &devclsp,
1015 			    &ndevcls) != DDI_PROP_SUCCESS)
1016 				continue;
1017 			ASSERT(ndevcls == 1);
1018 			devcls = (xendev_devclass_t)*devclsp;
1019 			ddi_prop_free(devclsp);
1020 		} else {
1021 			domid = pdp->xd_domain;
1022 			vdevnum = pdp->xd_vdevnum;
1023 			devcls = pdp->xd_devclass;
1024 		}
1025 
1026 		if ((domid == dom) && (vdevnum == vdev) && (devcls == devclass))
1027 			return (dip);
1028 	}
1029 	return (NULL);
1030 }
1031 
1032 int
1033 xvdi_get_evtchn(dev_info_t *xdip)
1034 {
1035 	struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
1036 
1037 	ASSERT(pdp != NULL);
1038 	return (pdp->xd_evtchn);
1039 }
1040 
1041 int
1042 xvdi_get_vdevnum(dev_info_t *xdip)
1043 {
1044 	struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
1045 
1046 	ASSERT(pdp != NULL);
1047 	return (pdp->xd_vdevnum);
1048 }
1049 
1050 char *
1051 xvdi_get_xsname(dev_info_t *xdip)
1052 {
1053 	struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
1054 
1055 	ASSERT(pdp != NULL);
1056 	return ((char *)(pdp->xd_xsdev.nodename));
1057 }
1058 
1059 char *
1060 xvdi_get_oename(dev_info_t *xdip)
1061 {
1062 	struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
1063 
1064 	ASSERT(pdp != NULL);
1065 	if (pdp->xd_devclass == XEN_CONSOLE)
1066 		return (NULL);
1067 	return ((char *)(pdp->xd_xsdev.otherend));
1068 }
1069 
1070 struct xenbus_device *
1071 xvdi_get_xsd(dev_info_t *xdip)
1072 {
1073 	struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
1074 
1075 	ASSERT(pdp != NULL);
1076 	return (&pdp->xd_xsdev);
1077 }
1078 
1079 domid_t
1080 xvdi_get_oeid(dev_info_t *xdip)
1081 {
1082 	struct xendev_ppd *pdp = ddi_get_parent_data(xdip);
1083 
1084 	ASSERT(pdp != NULL);
1085 	if (pdp->xd_devclass == XEN_CONSOLE)
1086 		return ((domid_t)-1);
1087 	return ((domid_t)(pdp->xd_xsdev.otherend_id));
1088 }
1089 
1090 void
1091 xvdi_dev_error(dev_info_t *dip, int errno, char *errstr)
1092 {
1093 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1094 
1095 	ASSERT(pdp != NULL);
1096 	xenbus_dev_error(&pdp->xd_xsdev, errno, errstr);
1097 }
1098 
1099 void
1100 xvdi_fatal_error(dev_info_t *dip, int errno, char *errstr)
1101 {
1102 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1103 
1104 	ASSERT(pdp != NULL);
1105 	xenbus_dev_fatal(&pdp->xd_xsdev, errno, errstr);
1106 }
1107 
1108 static void
1109 i_xvdi_oestate_handler(void *arg)
1110 {
1111 	dev_info_t *dip = arg;
1112 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1113 	XenbusState oestate = pdp->xd_xsdev.otherend_state;
1114 	ddi_eventcookie_t evc;
1115 
1116 	mutex_enter(&pdp->xd_lk);
1117 
1118 	if (pdp->xd_oe_ehid != NULL) {
1119 		/* send notification to driver */
1120 		if (ddi_get_eventcookie(dip, XS_OE_STATE,
1121 		    &evc) == DDI_SUCCESS) {
1122 			mutex_exit(&pdp->xd_lk);
1123 			(void) ndi_post_event(dip, dip, evc, &oestate);
1124 			mutex_enter(&pdp->xd_lk);
1125 		}
1126 	} else {
1127 		/*
1128 		 * take default action, if driver hasn't registered its
1129 		 * event handler yet
1130 		 */
1131 		if (oestate == XenbusStateClosing) {
1132 			(void) xvdi_switch_state(dip, XBT_NULL,
1133 			    XenbusStateClosed);
1134 		} else if (oestate == XenbusStateClosed) {
1135 			(void) xvdi_switch_state(dip, XBT_NULL,
1136 			    XenbusStateClosed);
1137 			(void) xvdi_post_event(dip, XEN_HP_REMOVE);
1138 		}
1139 	}
1140 
1141 	mutex_exit(&pdp->xd_lk);
1142 
1143 	/*
1144 	 * We'll try to remove the devinfo node of this device if the
1145 	 * other end has closed.
1146 	 */
1147 	if (oestate == XenbusStateClosed)
1148 		(void) ddi_taskq_dispatch(DEVI(ddi_get_parent(dip))->devi_taskq,
1149 		    xendev_offline_device, dip, DDI_SLEEP);
1150 }
1151 
1152 static void
1153 i_xvdi_hpstate_handler(void *arg)
1154 {
1155 	dev_info_t *dip = (dev_info_t *)arg;
1156 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1157 	ddi_eventcookie_t evc;
1158 	char *hp_status;
1159 	unsigned int hpl;
1160 
1161 	mutex_enter(&pdp->xd_lk);
1162 	if ((ddi_get_eventcookie(dip, XS_HP_STATE, &evc) == DDI_SUCCESS) &&
1163 	    (xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "",
1164 	    (void *)&hp_status, &hpl) == 0)) {
1165 
1166 		xendev_hotplug_state_t new_state = Unrecognized;
1167 
1168 		if (strcmp(hp_status, "connected") == 0)
1169 			new_state = Connected;
1170 
1171 		mutex_exit(&pdp->xd_lk);
1172 
1173 		(void) ndi_post_event(dip, dip, evc, &new_state);
1174 		kmem_free(hp_status, hpl);
1175 		return;
1176 	}
1177 	mutex_exit(&pdp->xd_lk);
1178 }
1179 
1180 void
1181 xvdi_notify_oe(dev_info_t *dip)
1182 {
1183 	struct xendev_ppd *pdp;
1184 
1185 	pdp = ddi_get_parent_data(dip);
1186 	ASSERT(pdp->xd_evtchn != INVALID_EVTCHN);
1187 	ec_notify_via_evtchn(pdp->xd_evtchn);
1188 }
1189 
1190 static void
1191 i_xvdi_bepath_cb(struct xenbus_watch *w, const char **vec, unsigned int len)
1192 {
1193 	dev_info_t *dip = (dev_info_t *)w->dev;
1194 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1195 	char *be = NULL;
1196 	unsigned int bel;
1197 
1198 	ASSERT(len > XS_WATCH_PATH);
1199 	ASSERT(vec[XS_WATCH_PATH] != NULL);
1200 
1201 	/*
1202 	 * If the backend is not the same as that we already stored,
1203 	 * re-set our watch for its' state.
1204 	 */
1205 	if ((xenbus_read(XBT_NULL, "", vec[XS_WATCH_PATH], (void *)be, &bel)
1206 	    == 0) && (strcmp(be, pdp->xd_xsdev.otherend) != 0))
1207 		(void) i_xvdi_add_watch_oestate(dip);
1208 
1209 	if (be != NULL) {
1210 		ASSERT(bel > 0);
1211 		kmem_free(be, bel);
1212 	}
1213 }
1214 
1215 static int
1216 i_xvdi_add_watch_oestate(dev_info_t *dip)
1217 {
1218 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1219 
1220 	ASSERT(pdp != NULL);
1221 	ASSERT(pdp->xd_xsdev.nodename != NULL);
1222 	ASSERT(mutex_owned(&pdp->xd_lk));
1223 
1224 	/*
1225 	 * Create taskq for delivering other end state change event to
1226 	 * this device later.
1227 	 *
1228 	 * Set nthreads to 1 to make sure that events can be delivered
1229 	 * in order.
1230 	 *
1231 	 * Note: It is _not_ guaranteed that driver can see every
1232 	 * xenstore change under the path that it is watching. If two
1233 	 * changes happen consecutively in a very short amount of
1234 	 * time, it is likely that the driver will see only the last
1235 	 * one.
1236 	 */
1237 	if (pdp->xd_oe_taskq == NULL)
1238 		if ((pdp->xd_oe_taskq = ddi_taskq_create(dip,
1239 		    "xendev_oe_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL)
1240 			return (DDI_FAILURE);
1241 
1242 	/*
1243 	 * Watch for changes to the XenbusState of otherend.
1244 	 */
1245 	pdp->xd_xsdev.otherend_state = XenbusStateUnknown;
1246 	pdp->xd_xsdev.otherend_changed = i_xvdi_oestate_cb;
1247 
1248 	if (talk_to_otherend(&pdp->xd_xsdev) != 0) {
1249 		i_xvdi_rem_watch_oestate(dip);
1250 		return (DDI_FAILURE);
1251 	}
1252 
1253 	return (DDI_SUCCESS);
1254 }
1255 
1256 static void
1257 i_xvdi_rem_watch_oestate(dev_info_t *dip)
1258 {
1259 	struct xendev_ppd *pdp;
1260 	struct xenbus_device *dev;
1261 
1262 	pdp = ddi_get_parent_data(dip);
1263 	ASSERT(pdp != NULL);
1264 	ASSERT(mutex_owned(&pdp->xd_lk));
1265 
1266 	dev = &pdp->xd_xsdev;
1267 
1268 	/* Unwatch for changes to XenbusState of otherend */
1269 	if (dev->otherend_watch.node != NULL) {
1270 		mutex_exit(&pdp->xd_lk);
1271 		unregister_xenbus_watch(&dev->otherend_watch);
1272 		mutex_enter(&pdp->xd_lk);
1273 	}
1274 
1275 	/* make sure no event handler is running */
1276 	if (pdp->xd_oe_taskq != NULL) {
1277 		mutex_exit(&pdp->xd_lk);
1278 		ddi_taskq_destroy(pdp->xd_oe_taskq);
1279 		mutex_enter(&pdp->xd_lk);
1280 		pdp->xd_oe_taskq = NULL;
1281 	}
1282 
1283 	/* clean up */
1284 	dev->otherend_state = XenbusStateUnknown;
1285 	dev->otherend_id = (domid_t)-1;
1286 	if (dev->otherend_watch.node != NULL)
1287 		kmem_free((void *)dev->otherend_watch.node,
1288 		    strlen(dev->otherend_watch.node) + 1);
1289 	dev->otherend_watch.node = NULL;
1290 	if (dev->otherend != NULL)
1291 		kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1);
1292 	dev->otherend = NULL;
1293 }
1294 
1295 static int
1296 i_xvdi_add_watch_hpstate(dev_info_t *dip)
1297 {
1298 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1299 
1300 	ASSERT(pdp != NULL);
1301 	ASSERT(pdp->xd_xsdev.frontend == 0);
1302 	ASSERT(mutex_owned(&pdp->xd_lk));
1303 
1304 	/*
1305 	 * Create taskq for delivering hotplug status change event to
1306 	 * this device later.
1307 	 *
1308 	 * Set nthreads to 1 to make sure that events can be delivered
1309 	 * in order.
1310 	 *
1311 	 * Note: It is _not_ guaranteed that driver can see every
1312 	 * hotplug status change under the path that it is
1313 	 * watching. If two changes happen consecutively in a very
1314 	 * short amount of time, it is likely that the driver only
1315 	 * sees the last one.
1316 	 */
1317 	if (pdp->xd_hp_taskq == NULL)
1318 		if ((pdp->xd_hp_taskq = ddi_taskq_create(dip,
1319 		    "xendev_hp_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL)
1320 			return (DDI_FAILURE);
1321 
1322 	if (pdp->xd_hp_watch.node == NULL) {
1323 		size_t len;
1324 		char *path;
1325 
1326 		ASSERT(pdp->xd_xsdev.nodename != NULL);
1327 
1328 		len = strlen(pdp->xd_xsdev.nodename) +
1329 		    strlen("/hotplug-status") + 1;
1330 		path = kmem_alloc(len, KM_SLEEP);
1331 		(void) snprintf(path, len, "%s/hotplug-status",
1332 		    pdp->xd_xsdev.nodename);
1333 
1334 		pdp->xd_hp_watch.node = path;
1335 		pdp->xd_hp_watch.callback = i_xvdi_hpstate_cb;
1336 		pdp->xd_hp_watch.dev = (struct xenbus_device *)dip; /* yuck! */
1337 		if (register_xenbus_watch(&pdp->xd_hp_watch) != 0) {
1338 			i_xvdi_rem_watch_hpstate(dip);
1339 			return (DDI_FAILURE);
1340 		}
1341 	}
1342 
1343 	return (DDI_SUCCESS);
1344 }
1345 
1346 static void
1347 i_xvdi_rem_watch_hpstate(dev_info_t *dip)
1348 {
1349 	struct xendev_ppd *pdp;
1350 	pdp = ddi_get_parent_data(dip);
1351 
1352 	ASSERT(pdp != NULL);
1353 	ASSERT(pdp->xd_xsdev.frontend == 0);
1354 	ASSERT(mutex_owned(&pdp->xd_lk));
1355 
1356 	/* Unwatch for changes to "hotplug-status" node for backend device. */
1357 	if (pdp->xd_hp_watch.node != NULL) {
1358 		mutex_exit(&pdp->xd_lk);
1359 		unregister_xenbus_watch(&pdp->xd_hp_watch);
1360 		mutex_enter(&pdp->xd_lk);
1361 	}
1362 
1363 	/* Make sure no event handler is running. */
1364 	if (pdp->xd_hp_taskq != NULL) {
1365 		mutex_exit(&pdp->xd_lk);
1366 		ddi_taskq_destroy(pdp->xd_hp_taskq);
1367 		mutex_enter(&pdp->xd_lk);
1368 		pdp->xd_hp_taskq = NULL;
1369 	}
1370 
1371 	/* Clean up. */
1372 	if (pdp->xd_hp_watch.node != NULL) {
1373 		kmem_free((void *)pdp->xd_hp_watch.node,
1374 		    strlen(pdp->xd_hp_watch.node) + 1);
1375 		pdp->xd_hp_watch.node = NULL;
1376 	}
1377 }
1378 
1379 static int
1380 i_xvdi_add_watches(dev_info_t *dip)
1381 {
1382 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1383 
1384 	ASSERT(pdp != NULL);
1385 
1386 	mutex_enter(&pdp->xd_lk);
1387 
1388 	if (i_xvdi_add_watch_oestate(dip) != DDI_SUCCESS) {
1389 		mutex_exit(&pdp->xd_lk);
1390 		return (DDI_FAILURE);
1391 	}
1392 
1393 	if (pdp->xd_xsdev.frontend == 1) {
1394 		/*
1395 		 * Frontend devices must watch for the backend path
1396 		 * changing.
1397 		 */
1398 		if (i_xvdi_add_watch_bepath(dip) != DDI_SUCCESS)
1399 			goto unwatch_and_fail;
1400 	} else {
1401 		/*
1402 		 * Backend devices must watch for hotplug events.
1403 		 */
1404 		if (i_xvdi_add_watch_hpstate(dip) != DDI_SUCCESS)
1405 			goto unwatch_and_fail;
1406 	}
1407 
1408 	mutex_exit(&pdp->xd_lk);
1409 
1410 	return (DDI_SUCCESS);
1411 
1412 unwatch_and_fail:
1413 	i_xvdi_rem_watch_oestate(dip);
1414 	mutex_exit(&pdp->xd_lk);
1415 
1416 	return (DDI_FAILURE);
1417 }
1418 
1419 static void
1420 i_xvdi_rem_watches(dev_info_t *dip)
1421 {
1422 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1423 
1424 	ASSERT(pdp != NULL);
1425 
1426 	mutex_enter(&pdp->xd_lk);
1427 
1428 	i_xvdi_rem_watch_oestate(dip);
1429 
1430 	if (pdp->xd_xsdev.frontend == 1)
1431 		i_xvdi_rem_watch_bepath(dip);
1432 	else
1433 		i_xvdi_rem_watch_hpstate(dip);
1434 
1435 	mutex_exit(&pdp->xd_lk);
1436 }
1437 
1438 static int
1439 i_xvdi_add_watch_bepath(dev_info_t *dip)
1440 {
1441 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1442 
1443 	ASSERT(pdp != NULL);
1444 	ASSERT(pdp->xd_xsdev.frontend == 1);
1445 
1446 	/*
1447 	 * Frontend devices need to watch for the backend path changing.
1448 	 */
1449 	if (pdp->xd_bepath_watch.node == NULL) {
1450 		size_t len;
1451 		char *path;
1452 
1453 		ASSERT(pdp->xd_xsdev.nodename != NULL);
1454 
1455 		len = strlen(pdp->xd_xsdev.nodename) + strlen("/backend") + 1;
1456 		path = kmem_alloc(len, KM_SLEEP);
1457 		(void) snprintf(path, len, "%s/backend",
1458 		    pdp->xd_xsdev.nodename);
1459 
1460 		pdp->xd_bepath_watch.node = path;
1461 		pdp->xd_bepath_watch.callback = i_xvdi_bepath_cb;
1462 		pdp->xd_bepath_watch.dev = (struct xenbus_device *)dip;
1463 		if (register_xenbus_watch(&pdp->xd_bepath_watch) != 0) {
1464 			kmem_free(path, len);
1465 			pdp->xd_bepath_watch.node = NULL;
1466 			return (DDI_FAILURE);
1467 		}
1468 	}
1469 
1470 	return (DDI_SUCCESS);
1471 }
1472 
1473 static void
1474 i_xvdi_rem_watch_bepath(dev_info_t *dip)
1475 {
1476 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1477 
1478 	ASSERT(pdp != NULL);
1479 	ASSERT(pdp->xd_xsdev.frontend == 1);
1480 	ASSERT(mutex_owned(&pdp->xd_lk));
1481 
1482 	if (pdp->xd_bepath_watch.node != NULL) {
1483 		mutex_exit(&pdp->xd_lk);
1484 		unregister_xenbus_watch(&pdp->xd_bepath_watch);
1485 		mutex_enter(&pdp->xd_lk);
1486 
1487 		kmem_free((void *)(pdp->xd_bepath_watch.node),
1488 		    strlen(pdp->xd_bepath_watch.node) + 1);
1489 		pdp->xd_bepath_watch.node = NULL;
1490 	}
1491 }
1492 
1493 int
1494 xvdi_switch_state(dev_info_t *dip, xenbus_transaction_t xbt,
1495     XenbusState newState)
1496 {
1497 	int rv;
1498 	struct xendev_ppd *pdp;
1499 
1500 	pdp = ddi_get_parent_data(dip);
1501 	ASSERT(pdp != NULL);
1502 
1503 	XVDI_DPRINTF(XVDI_DBG_STATE,
1504 	    "xvdi_switch_state: dip 0x%p moves to %d",
1505 	    (void *)dip, newState);
1506 
1507 	rv = xenbus_switch_state(&pdp->xd_xsdev, xbt, newState);
1508 	if (rv > 0)
1509 		cmn_err(CE_WARN, "xvdi_switch_state: change state failed");
1510 
1511 	return (rv);
1512 }
1513 
1514 /*
1515  * Notify hotplug script running in userland
1516  */
1517 int
1518 xvdi_post_event(dev_info_t *dip, xendev_hotplug_cmd_t hpc)
1519 {
1520 	struct xendev_ppd *pdp;
1521 	nvlist_t *attr_list = NULL;
1522 	i_xd_cfg_t *xdcp;
1523 	sysevent_id_t eid;
1524 	int err;
1525 	char devname[256]; /* XXPV dme: ? */
1526 
1527 	pdp = ddi_get_parent_data(dip);
1528 	ASSERT(pdp != NULL);
1529 
1530 	xdcp = i_xvdi_devclass2cfg(pdp->xd_devclass);
1531 	ASSERT(xdcp != NULL);
1532 
1533 	(void) snprintf(devname, sizeof (devname) - 1, "%s%d",
1534 	    ddi_driver_name(dip),  ddi_get_instance(dip));
1535 
1536 	err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_NOSLEEP);
1537 	if (err != DDI_SUCCESS)
1538 		goto failure;
1539 
1540 	err = nvlist_add_int32(attr_list, "domain", pdp->xd_domain);
1541 	if (err != DDI_SUCCESS)
1542 		goto failure;
1543 	err = nvlist_add_int32(attr_list, "vdev", pdp->xd_vdevnum);
1544 	if (err != DDI_SUCCESS)
1545 		goto failure;
1546 	err = nvlist_add_string(attr_list, "devclass", xdcp->xsdev);
1547 	if (err != DDI_SUCCESS)
1548 		goto failure;
1549 	err = nvlist_add_string(attr_list, "device", devname);
1550 	if (err != DDI_SUCCESS)
1551 		goto failure;
1552 	err = nvlist_add_string(attr_list, "fob",
1553 	    ((pdp->xd_xsdev.frontend == 1) ? "frontend" : "backend"));
1554 	if (err != DDI_SUCCESS)
1555 		goto failure;
1556 
1557 	switch (hpc) {
1558 	case XEN_HP_ADD:
1559 		err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev",
1560 		    "add", attr_list, &eid, DDI_NOSLEEP);
1561 		break;
1562 	case XEN_HP_REMOVE:
1563 		err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev",
1564 		    "remove", attr_list, &eid, DDI_NOSLEEP);
1565 		break;
1566 	default:
1567 		err = DDI_FAILURE;
1568 		goto failure;
1569 	}
1570 
1571 failure:
1572 	if (attr_list != NULL)
1573 		nvlist_free(attr_list);
1574 
1575 	return (err);
1576 }
1577 
1578 /* ARGSUSED */
1579 static void
1580 i_xvdi_probe_path_cb(struct xenbus_watch *w, const char **vec,
1581     unsigned int len)
1582 {
1583 	char *path;
1584 
1585 	if (xendev_dip == NULL)
1586 		xendev_dip = ddi_find_devinfo("xpvd", -1, 0);
1587 
1588 	path = i_ddi_strdup((char *)vec[XS_WATCH_PATH], KM_SLEEP);
1589 
1590 	(void) ddi_taskq_dispatch(DEVI(xendev_dip)->devi_taskq,
1591 	    i_xvdi_probe_path_handler, (void *)path, DDI_SLEEP);
1592 }
1593 
1594 static void
1595 i_xvdi_watch_device(char *path)
1596 {
1597 	struct xenbus_watch *w;
1598 
1599 	ASSERT(path != NULL);
1600 
1601 	w = kmem_zalloc(sizeof (*w), KM_SLEEP);
1602 	w->node = path;
1603 	w->callback = &i_xvdi_probe_path_cb;
1604 	w->dev = NULL;
1605 
1606 	if (register_xenbus_watch(w) != 0) {
1607 		cmn_err(CE_WARN, "i_xvdi_watch_device: "
1608 		    "cannot set watch on %s", path);
1609 		kmem_free(w, sizeof (*w));
1610 		return;
1611 	}
1612 }
1613 
1614 void
1615 xvdi_watch_devices(int newstate)
1616 {
1617 	int devclass;
1618 
1619 	/*
1620 	 * Watch for devices being created in the store.
1621 	 */
1622 	if (newstate == XENSTORE_DOWN)
1623 		return;
1624 	for (devclass = 0; devclass < NXDC; devclass++) {
1625 		if (xdci[devclass].xs_path_fe != NULL)
1626 			i_xvdi_watch_device(xdci[devclass].xs_path_fe);
1627 		if (xdci[devclass].xs_path_be != NULL)
1628 			i_xvdi_watch_device(xdci[devclass].xs_path_be);
1629 	}
1630 }
1631 
1632 /*
1633  * Iterate over the store looking for backend devices to create.
1634  */
1635 static void
1636 i_xvdi_enum_be(dev_info_t *parent, i_xd_cfg_t *xdcp)
1637 {
1638 	char **domains;
1639 	unsigned int ndomains;
1640 	int ldomains, i;
1641 
1642 	if ((domains = xenbus_directory(XBT_NULL, xdcp->xs_path_be, "",
1643 	    &ndomains)) == NULL)
1644 		return;
1645 
1646 	for (i = 0, ldomains = 0; i < ndomains; i++) {
1647 		ldomains += strlen(domains[i]) + 1 + sizeof (char *);
1648 
1649 		i_xvdi_enum_worker(parent, xdcp, domains[i]);
1650 	}
1651 	kmem_free(domains, ldomains);
1652 }
1653 
1654 /*
1655  * Iterate over the store looking for frontend devices to create.
1656  */
1657 static void
1658 i_xvdi_enum_fe(dev_info_t *parent, i_xd_cfg_t *xdcp)
1659 {
1660 	i_xvdi_enum_worker(parent, xdcp, NULL);
1661 }
1662 
1663 static void
1664 i_xvdi_enum_worker(dev_info_t *parent, i_xd_cfg_t *xdcp,
1665     char *domain)
1666 {
1667 	char *path, *domain_path, *ep;
1668 	char **devices;
1669 	unsigned int ndevices;
1670 	int ldevices, j, circ;
1671 	domid_t dom;
1672 	long tmplong;
1673 
1674 	if (domain == NULL) {
1675 		dom = DOMID_SELF;
1676 		path = xdcp->xs_path_fe;
1677 		domain_path = "";
1678 	} else {
1679 		(void) ddi_strtol(domain, &ep, 0, &tmplong);
1680 		dom = tmplong;
1681 		path = xdcp->xs_path_be;
1682 		domain_path = domain;
1683 	}
1684 
1685 	if ((devices = xenbus_directory(XBT_NULL, path, domain_path,
1686 	    &ndevices)) == NULL)
1687 		return;
1688 
1689 	for (j = 0, ldevices = 0; j < ndevices; j++) {
1690 		int vdev;
1691 
1692 		ldevices += strlen(devices[j]) + 1 + sizeof (char *);
1693 		(void) ddi_strtol(devices[j], &ep, 0, &tmplong);
1694 		vdev = tmplong;
1695 
1696 		ndi_devi_enter(parent, &circ);
1697 
1698 		if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL)
1699 			(void) xvdi_create_dev(parent, xdcp->devclass,
1700 			    dom, vdev);
1701 
1702 		ndi_devi_exit(parent, circ);
1703 	}
1704 	kmem_free(devices, ldevices);
1705 }
1706 
1707 /*
1708  * Leaf drivers should call this in their detach() routine during suspend.
1709  */
1710 void
1711 xvdi_suspend(dev_info_t *dip)
1712 {
1713 	i_xvdi_rem_watches(dip);
1714 }
1715 
1716 /*
1717  * Leaf drivers should call this in their attach() routine during resume.
1718  */
1719 int
1720 xvdi_resume(dev_info_t *dip)
1721 {
1722 	return (i_xvdi_add_watches(dip));
1723 }
1724 
1725 /*
1726  * Add event handler for the leaf driver
1727  * to handle event triggered by the change in xenstore
1728  */
1729 int
1730 xvdi_add_event_handler(dev_info_t *dip, char *name,
1731     void (*evthandler)(dev_info_t *, ddi_eventcookie_t, void *, void *))
1732 {
1733 	ddi_eventcookie_t ecv;
1734 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
1735 	ddi_callback_id_t *cbid;
1736 
1737 	ASSERT(pdp != NULL);
1738 
1739 	mutex_enter(&pdp->xd_lk);
1740 
1741 	if (strcmp(name, XS_OE_STATE) == 0) {
1742 		ASSERT(pdp->xd_xsdev.otherend != NULL);
1743 
1744 		cbid = &pdp->xd_oe_ehid;
1745 	} else if (strcmp(name, XS_HP_STATE) == 0) {
1746 		if (pdp->xd_xsdev.frontend == 1) {
1747 			mutex_exit(&pdp->xd_lk);
1748 			return (DDI_FAILURE);
1749 		}
1750 
1751 		ASSERT(pdp->xd_hp_watch.node != NULL);
1752 
1753 		cbid = &pdp->xd_hp_ehid;
1754 	} else {
1755 		/* Unsupported watch. */
1756 		mutex_exit(&pdp->xd_lk);
1757 		return (DDI_FAILURE);
1758 	}
1759 
1760 	/*
1761 	 * No event handler provided, take default action to handle
1762 	 * event.
1763 	 */
1764 	if (evthandler == NULL) {
1765 		mutex_exit(&pdp->xd_lk);
1766 		return (DDI_SUCCESS);
1767 	}
1768 
1769 	ASSERT(*cbid == NULL);
1770 
1771 	if (ddi_get_eventcookie(dip, name, &ecv) != DDI_SUCCESS) {
1772 		cmn_err(CE_WARN, "failed to find %s cookie for %s@%s",
1773 		    name, ddi_get_name(dip), ddi_get_name_addr(dip));
1774 		mutex_exit(&pdp->xd_lk);
1775 		return (DDI_FAILURE);
1776 	}
1777 	if (ddi_add_event_handler(dip, ecv, evthandler, NULL, cbid)
1778 	    != DDI_SUCCESS) {
1779 		cmn_err(CE_WARN, "failed to add %s event handler for %s@%s",
1780 		    name, ddi_get_name(dip), ddi_get_name_addr(dip));
1781 		*cbid = NULL;
1782 		mutex_exit(&pdp->xd_lk);
1783 		return (DDI_FAILURE);
1784 	}
1785 
1786 	mutex_exit(&pdp->xd_lk);
1787 
1788 	return (DDI_SUCCESS);
1789 }
1790 
1791 /*
1792  * Remove event handler for the leaf driver and unwatch xenstore
1793  * so, driver will not be notified when xenstore entry changed later
1794  */
1795 void
1796 xvdi_remove_event_handler(dev_info_t *dip, char *name)
1797 {
1798 	struct xendev_ppd *pdp;
1799 	boolean_t rem_oe = B_FALSE, rem_hp = B_FALSE;
1800 	ddi_callback_id_t oeid = NULL, hpid = NULL;
1801 
1802 	pdp = ddi_get_parent_data(dip);
1803 	ASSERT(pdp != NULL);
1804 
1805 	if (name == NULL) {
1806 		rem_oe = B_TRUE;
1807 		rem_hp = B_TRUE;
1808 	} else if (strcmp(name, XS_OE_STATE) == 0) {
1809 		rem_oe = B_TRUE;
1810 	} else if (strcmp(name, XS_HP_STATE) == 0) {
1811 		rem_hp = B_TRUE;
1812 	} else {
1813 		cmn_err(CE_WARN, "event %s not supported, cannot remove", name);
1814 		return;
1815 	}
1816 
1817 	mutex_enter(&pdp->xd_lk);
1818 
1819 	if (rem_oe && (pdp->xd_oe_ehid != NULL)) {
1820 		oeid = pdp->xd_oe_ehid;
1821 		pdp->xd_oe_ehid = NULL;
1822 	}
1823 
1824 	if (rem_hp && (pdp->xd_hp_ehid != NULL)) {
1825 		hpid = pdp->xd_hp_ehid;
1826 		pdp->xd_hp_ehid = NULL;
1827 	}
1828 
1829 	mutex_exit(&pdp->xd_lk);
1830 
1831 	if (oeid != NULL)
1832 		(void) ddi_remove_event_handler(oeid);
1833 	if (hpid != NULL)
1834 		(void) ddi_remove_event_handler(hpid);
1835 }
1836 
1837 
1838 /*
1839  * common ring interfaces
1840  */
1841 
1842 #define	FRONT_RING(_ringp)	(&(_ringp)->xr_sring.fr)
1843 #define	BACK_RING(_ringp)	(&(_ringp)->xr_sring.br)
1844 #define	GET_RING_SIZE(_ringp)	RING_SIZE(FRONT_RING(ringp))
1845 #define	GET_RING_ENTRY_FE(_ringp, _idx)		\
1846 	(FRONT_RING(_ringp)->sring->ring +	\
1847 	(_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1)))
1848 #define	GET_RING_ENTRY_BE(_ringp, _idx)		\
1849 	(BACK_RING(_ringp)->sring->ring +	\
1850 	(_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1)))
1851 
1852 unsigned int
1853 xvdi_ring_avail_slots(xendev_ring_t *ringp)
1854 {
1855 	comif_ring_fe_t *frp;
1856 	comif_ring_be_t *brp;
1857 
1858 	if (ringp->xr_frontend) {
1859 		frp = FRONT_RING(ringp);
1860 		return (GET_RING_SIZE(ringp) -
1861 		    (frp->req_prod_pvt - frp->rsp_cons));
1862 	} else {
1863 		brp = BACK_RING(ringp);
1864 		return (GET_RING_SIZE(ringp) -
1865 		    (brp->rsp_prod_pvt - brp->req_cons));
1866 	}
1867 }
1868 
1869 int
1870 xvdi_ring_has_unconsumed_requests(xendev_ring_t *ringp)
1871 {
1872 	comif_ring_be_t *brp;
1873 
1874 	ASSERT(!ringp->xr_frontend);
1875 	brp = BACK_RING(ringp);
1876 	return ((brp->req_cons !=
1877 	    ddi_get32(ringp->xr_acc_hdl, &brp->sring->req_prod)) &&
1878 	    ((brp->req_cons - brp->rsp_prod_pvt) != RING_SIZE(brp)));
1879 }
1880 
1881 int
1882 xvdi_ring_has_incomp_request(xendev_ring_t *ringp)
1883 {
1884 	comif_ring_fe_t *frp;
1885 
1886 	ASSERT(ringp->xr_frontend);
1887 	frp = FRONT_RING(ringp);
1888 	return (frp->req_prod_pvt !=
1889 	    ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod));
1890 }
1891 
1892 int
1893 xvdi_ring_has_unconsumed_responses(xendev_ring_t *ringp)
1894 {
1895 	comif_ring_fe_t *frp;
1896 
1897 	ASSERT(ringp->xr_frontend);
1898 	frp = FRONT_RING(ringp);
1899 	return (frp->rsp_cons !=
1900 	    ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod));
1901 }
1902 
1903 /* NOTE: req_event will be increased as needed */
1904 void *
1905 xvdi_ring_get_request(xendev_ring_t *ringp)
1906 {
1907 	comif_ring_fe_t *frp;
1908 	comif_ring_be_t *brp;
1909 
1910 	if (ringp->xr_frontend) {
1911 		/* for frontend ring */
1912 		frp = FRONT_RING(ringp);
1913 		if (!RING_FULL(frp))
1914 			return (GET_RING_ENTRY_FE(ringp, frp->req_prod_pvt++));
1915 		else
1916 			return (NULL);
1917 	} else {
1918 		/* for backend ring */
1919 		brp = BACK_RING(ringp);
1920 		/* RING_FINAL_CHECK_FOR_REQUESTS() */
1921 		if (xvdi_ring_has_unconsumed_requests(ringp))
1922 			return (GET_RING_ENTRY_BE(ringp, brp->req_cons++));
1923 		else {
1924 			ddi_put32(ringp->xr_acc_hdl, &brp->sring->req_event,
1925 			    brp->req_cons + 1);
1926 			membar_enter();
1927 			if (xvdi_ring_has_unconsumed_requests(ringp))
1928 				return (GET_RING_ENTRY_BE(ringp,
1929 				    brp->req_cons++));
1930 			else
1931 				return (NULL);
1932 		}
1933 	}
1934 }
1935 
1936 int
1937 xvdi_ring_push_request(xendev_ring_t *ringp)
1938 {
1939 	RING_IDX old, new, reqevt;
1940 	comif_ring_fe_t *frp;
1941 
1942 	/* only frontend should be able to push request */
1943 	ASSERT(ringp->xr_frontend);
1944 
1945 	/* RING_PUSH_REQUEST_AND_CHECK_NOTIFY() */
1946 	frp = FRONT_RING(ringp);
1947 	old = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_prod);
1948 	new = frp->req_prod_pvt;
1949 	ddi_put32(ringp->xr_acc_hdl, &frp->sring->req_prod, new);
1950 	membar_enter();
1951 	reqevt = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_event);
1952 	return ((RING_IDX)(new - reqevt) < (RING_IDX)(new - old));
1953 }
1954 
1955 /* NOTE: rsp_event will be increased as needed */
1956 void *
1957 xvdi_ring_get_response(xendev_ring_t *ringp)
1958 {
1959 	comif_ring_fe_t *frp;
1960 	comif_ring_be_t *brp;
1961 
1962 	if (!ringp->xr_frontend) {
1963 		/* for backend ring */
1964 		brp = BACK_RING(ringp);
1965 		return (GET_RING_ENTRY_BE(ringp, brp->rsp_prod_pvt++));
1966 	} else {
1967 		/* for frontend ring */
1968 		frp = FRONT_RING(ringp);
1969 		/* RING_FINAL_CHECK_FOR_RESPONSES() */
1970 		if (xvdi_ring_has_unconsumed_responses(ringp))
1971 			return (GET_RING_ENTRY_FE(ringp, frp->rsp_cons++));
1972 		else {
1973 			ddi_put32(ringp->xr_acc_hdl, &frp->sring->rsp_event,
1974 			    frp->rsp_cons + 1);
1975 			membar_enter();
1976 			if (xvdi_ring_has_unconsumed_responses(ringp))
1977 				return (GET_RING_ENTRY_FE(ringp,
1978 				    frp->rsp_cons++));
1979 			else
1980 				return (NULL);
1981 		}
1982 	}
1983 }
1984 
1985 int
1986 xvdi_ring_push_response(xendev_ring_t *ringp)
1987 {
1988 	RING_IDX old, new, rspevt;
1989 	comif_ring_be_t *brp;
1990 
1991 	/* only backend should be able to push response */
1992 	ASSERT(!ringp->xr_frontend);
1993 
1994 	/* RING_PUSH_RESPONSE_AND_CHECK_NOTIFY() */
1995 	brp = BACK_RING(ringp);
1996 	old = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_prod);
1997 	new = brp->rsp_prod_pvt;
1998 	ddi_put32(ringp->xr_acc_hdl, &brp->sring->rsp_prod, new);
1999 	membar_enter();
2000 	rspevt = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_event);
2001 	return ((RING_IDX)(new - rspevt) < (RING_IDX)(new - old));
2002 }
2003 
2004 static void
2005 xvdi_ring_init_sring(xendev_ring_t *ringp)
2006 {
2007 	ddi_acc_handle_t acchdl;
2008 	comif_sring_t *xsrp;
2009 	int i;
2010 
2011 	xsrp = (comif_sring_t *)ringp->xr_vaddr;
2012 	acchdl = ringp->xr_acc_hdl;
2013 
2014 	/* shared ring initialization */
2015 	ddi_put32(acchdl, &xsrp->req_prod, 0);
2016 	ddi_put32(acchdl, &xsrp->rsp_prod, 0);
2017 	ddi_put32(acchdl, &xsrp->req_event, 1);
2018 	ddi_put32(acchdl, &xsrp->rsp_event, 1);
2019 	for (i = 0; i < sizeof (xsrp->pad); i++)
2020 		ddi_put8(acchdl, xsrp->pad + i, 0);
2021 }
2022 
2023 static void
2024 xvdi_ring_init_front_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize)
2025 {
2026 	comif_ring_fe_t *xfrp;
2027 
2028 	xfrp = &ringp->xr_sring.fr;
2029 	xfrp->req_prod_pvt = 0;
2030 	xfrp->rsp_cons = 0;
2031 	xfrp->nr_ents = nentry;
2032 	xfrp->sring = (comif_sring_t *)ringp->xr_vaddr;
2033 
2034 	ringp->xr_frontend = 1;
2035 	ringp->xr_entry_size = entrysize;
2036 }
2037 
2038 #ifndef XPV_HVM_DRIVER
2039 static void
2040 xvdi_ring_init_back_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize)
2041 {
2042 	comif_ring_be_t *xbrp;
2043 
2044 	xbrp = &ringp->xr_sring.br;
2045 	xbrp->rsp_prod_pvt = 0;
2046 	xbrp->req_cons = 0;
2047 	xbrp->nr_ents = nentry;
2048 	xbrp->sring = (comif_sring_t *)ringp->xr_vaddr;
2049 
2050 	ringp->xr_frontend = 0;
2051 	ringp->xr_entry_size = entrysize;
2052 }
2053 #endif /* XPV_HVM_DRIVER */
2054 
2055 static void
2056 xendev_offline_device(void *arg)
2057 {
2058 	dev_info_t *dip = (dev_info_t *)arg;
2059 	char devname[MAXNAMELEN] = {0};
2060 
2061 	/*
2062 	 * This is currently the only chance to delete a devinfo node, which
2063 	 * is _not_ always successful.
2064 	 */
2065 	(void) ddi_deviname(dip, devname);
2066 	(void) devfs_clean(ddi_get_parent(dip), devname + 1, DV_CLEAN_FORCE);
2067 	(void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
2068 }
2069 
2070 static void
2071 i_xvdi_oestate_cb(struct xenbus_device *dev, XenbusState oestate)
2072 {
2073 	dev_info_t *dip = (dev_info_t *)dev->data;
2074 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
2075 
2076 	/*
2077 	 * Don't trigger two consecutive ndi_devi_offline on the same
2078 	 * dip.
2079 	 */
2080 	if ((oestate == XenbusStateClosed) &&
2081 	    (dev->otherend_state == XenbusStateClosed))
2082 		return;
2083 
2084 	dev->otherend_state = oestate;
2085 	(void) ddi_taskq_dispatch(pdp->xd_oe_taskq,
2086 	    i_xvdi_oestate_handler, (void *)dip, DDI_SLEEP);
2087 }
2088 
2089 /*ARGSUSED*/
2090 static void
2091 i_xvdi_hpstate_cb(struct xenbus_watch *w, const char **vec,
2092     unsigned int len)
2093 {
2094 	dev_info_t *dip = (dev_info_t *)w->dev;
2095 	struct xendev_ppd *pdp = ddi_get_parent_data(dip);
2096 
2097 	(void) ddi_taskq_dispatch(pdp->xd_hp_taskq,
2098 	    i_xvdi_hpstate_handler, (void *)dip, DDI_SLEEP);
2099 }
2100 
2101 static void
2102 i_xvdi_probe_path_handler(void *arg)
2103 {
2104 	dev_info_t *parent;
2105 	char *path = arg, *p = NULL;
2106 	int i, vdev, circ;
2107 	i_xd_cfg_t *xdcp;
2108 	boolean_t frontend;
2109 	domid_t dom;
2110 
2111 	for (i = 0, xdcp = &xdci[0]; i < NXDC; i++, xdcp++) {
2112 
2113 		if ((xdcp->xs_path_fe != NULL) &&
2114 		    (strncmp(path, xdcp->xs_path_fe, strlen(xdcp->xs_path_fe))
2115 		    == 0)) {
2116 
2117 			frontend = B_TRUE;
2118 			p = path + strlen(xdcp->xs_path_fe);
2119 			break;
2120 		}
2121 
2122 		if ((xdcp->xs_path_be != NULL) &&
2123 		    (strncmp(path, xdcp->xs_path_be, strlen(xdcp->xs_path_be))
2124 		    == 0)) {
2125 
2126 			frontend = B_FALSE;
2127 			p = path + strlen(xdcp->xs_path_be);
2128 			break;
2129 		}
2130 
2131 	}
2132 
2133 	if (p == NULL) {
2134 		cmn_err(CE_WARN, "i_xvdi_probe_path_handler: "
2135 		    "unexpected path prefix in %s", path);
2136 		goto done;
2137 	}
2138 
2139 	if (frontend) {
2140 		dom = DOMID_SELF;
2141 		if (sscanf(p, "/%d/", &vdev) != 1) {
2142 			XVDI_DPRINTF(XVDI_DBG_PROBE,
2143 			    "i_xvdi_probe_path_handler: "
2144 			    "cannot parse frontend path %s",
2145 			    path);
2146 			goto done;
2147 		}
2148 	} else {
2149 		if (sscanf(p, "/%d/%d/", &dom, &vdev) != 2) {
2150 			XVDI_DPRINTF(XVDI_DBG_PROBE,
2151 			    "i_xvdi_probe_path_handler: "
2152 			    "cannot parse backend path %s",
2153 			    path);
2154 			goto done;
2155 		}
2156 	}
2157 
2158 	/*
2159 	 * This is an oxymoron, so indicates a bogus configuration we
2160 	 * must check for.
2161 	 */
2162 	if (vdev == VDEV_NOXS) {
2163 		cmn_err(CE_WARN, "i_xvdi_probe_path_handler: "
2164 		    "invalid path %s", path);
2165 		goto done;
2166 	}
2167 
2168 	parent = xendev_dip;
2169 	ASSERT(parent != NULL);
2170 
2171 	ndi_devi_enter(parent, &circ);
2172 
2173 	if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) {
2174 		XVDI_DPRINTF(XVDI_DBG_PROBE,
2175 		    "i_xvdi_probe_path_handler: create for %s", path);
2176 		(void) xvdi_create_dev(parent, xdcp->devclass, dom, vdev);
2177 	} else {
2178 		XVDI_DPRINTF(XVDI_DBG_PROBE,
2179 		    "i_xvdi_probe_path_handler: %s already exists", path);
2180 	}
2181 
2182 	ndi_devi_exit(parent, circ);
2183 
2184 done:
2185 	kmem_free(path, strlen(path) + 1);
2186 }
2187