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