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