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>
 
 
 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),
 
 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
 
 | 
 
 
   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  * Copyright 2018 Nexenta Systems, Inc.
  30  */
  31 
  32 /*
  33  * Xen virtual device driver interfaces
  34  */
  35 
  36 /*
  37  * todo:
  38  * + name space clean up:
  39  *      xvdi_* - public xen interfaces, for use by all leaf drivers
  40  *      xd_* - public xen data structures
  41  *      i_xvdi_* - implementation private functions
  42  *      xendev_* - xendev driver interfaces, both internal and in cb_ops/bus_ops
  43  * + add mdb dcmds to dump ring status
  44  * + implement xvdi_xxx to wrap xenbus_xxx read/write function
  45  * + convert (xendev_ring_t *) into xvdi_ring_handle_t
  46  */
  47 #include <sys/conf.h>
  48 #include <sys/param.h>
  49 #include <sys/kmem.h>
 
 
 236         for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++)
 237                 if (xdcp->devclass == devclass)
 238                         return (xdcp);
 239 
 240         return (NULL);
 241 }
 242 
 243 int
 244 xvdi_init_dev(dev_info_t *dip)
 245 {
 246         xendev_devclass_t devcls;
 247         int vdevnum;
 248         domid_t domid;
 249         struct xendev_ppd *pdp;
 250         i_xd_cfg_t *xdcp;
 251         boolean_t backend;
 252         char xsnamebuf[TYPICALMAXPATHLEN];
 253         char *xsname;
 254         void *prop_str;
 255         unsigned int prop_len;
 256         char unitaddr[16];
 257 
 258         devcls = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 259             DDI_PROP_DONTPASS, "devclass", XEN_INVAL);
 260         vdevnum = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 261             DDI_PROP_DONTPASS, "vdev", VDEV_NOXS);
 262         domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 263             DDI_PROP_DONTPASS, "domain", DOMID_SELF);
 264 
 265         backend = (domid != DOMID_SELF);
 266         xdcp = i_xvdi_devclass2cfg(devcls);
 267         if (xdcp->device_type != NULL)
 268                 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
 269                     "device_type", xdcp->device_type);
 270 
 271         pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP);
 272         pdp->xd_domain = domid;
 273         pdp->xd_vdevnum = vdevnum;
 274         pdp->xd_devclass = devcls;
 275         pdp->xd_evtchn = INVALID_EVTCHN;
 276         list_create(&pdp->xd_xb_watches, sizeof (xd_xb_watches_t),
 
 317         pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP);
 318         pdp->xd_xsdev.devicetype = xdcp->xsdev;
 319         pdp->xd_xsdev.frontend = (backend ? 0 : 1);
 320         pdp->xd_xsdev.data = dip;
 321         pdp->xd_xsdev.otherend_id = (backend ? domid : -1);
 322         if (i_xvdi_add_watches(dip) != DDI_SUCCESS) {
 323                 cmn_err(CE_WARN, "xvdi_init_dev: "
 324                     "cannot add watches for %s", xsname);
 325                 xvdi_uninit_dev(dip);
 326                 return (DDI_FAILURE);
 327         }
 328 
 329         if (backend)
 330                 return (DDI_SUCCESS);
 331 
 332         /*
 333          * The unit-address for frontend devices is the name of the
 334          * of the xenstore node containing the device configuration
 335          * and is contained in the 'vdev' property.
 336          * VIF devices are named using an incrementing integer.
 337          * VBD devices are either named using the 32-bit dev_t value
 338          * for linux 'hd' and 'xvd' devices, or a simple integer value
 339          * in the range 0..767.  768 is the base value of the linux
 340          * dev_t namespace, the dev_t value for 'hda'.
 341          */
 342         (void) snprintf(unitaddr, sizeof (unitaddr), "%d", vdevnum);
 343         (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "unit-address",
 344             unitaddr);
 345 
 346         switch (devcls) {
 347         case XEN_VNET:
 348                 if (xenbus_read(XBT_NULL, xsname, "mac", (void *)&prop_str,
 349                     &prop_len) != 0)
 350                         break;
 351                 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "mac",
 352                     prop_str);
 353                 kmem_free(prop_str, prop_len);
 354                 break;
 355         case XEN_VBLK:
 356                 /*
 357                  * cache a copy of the otherend name
 
 |