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