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