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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <io/xdf_shell.h>
  27 #include <sys/dkio.h>
  28 #include <sys/scsi/scsi_types.h>
  29 
  30 /*
  31  * General Notes
  32  *
  33  * We don't support disks with bad block mappins.  We have this
  34  * limitation because the underlying xdf driver doesn't support
  35  * bad block remapping.  If there is a need to support this feature
  36  * it should be added directly to the xdf driver and we should just
  37  * pass requests strait on through and let it handle the remapping.
  38  * Also, it's probably worth pointing out that most modern disks do bad
  39  * block remapping internally in the hardware so there's actually less
  40  * of a chance of us ever discovering bad blocks.  Also, in most cases
  41  * this driver (and the xdf driver) will only be used with virtualized
  42  * devices, so one might wonder why a virtual device would ever actually
  43  * experience bad blocks.  To wrap this up, you might be wondering how
  44  * these bad block mappings get created and how they are managed.  Well,
  45  * there are two tools for managing bad block mappings, format(1M) and
  46  * addbadsec(1M).  Format(1M) can be used to do a surface scan of a disk
  47  * to attempt to find bad block and create mappings for them.  Format(1M)
  48  * and addbadsec(1M) can also be used to edit existing mappings that may
  49  * be saved on the disk.
  50  *
  51  * The underlying PV driver that this driver passes on requests to is the
  52  * xdf driver.  Since in most cases the xdf driver doesn't deal with
  53  * physical disks it has it's own algorithm for assigning a physical
  54  * geometry to a virtual disk (ie, cylinder count, head count, etc.)
  55  * The default values chosen by the xdf driver may not match those
  56  * assigned to a disk by a hardware disk emulator in an HVM environment.
  57  * This is a problem since these physical geometry attributes affect
  58  * things like the partition table, backup label location, etc.  So
  59  * to emulate disk devices correctly we need to know the physical geometry
  60  * that was assigned to a disk at the time of it's initalization.
  61  * Normally in an HVM environment this information will passed to
  62  * the BIOS and operating system from the hardware emulator that is
  63  * emulating the disk devices.  In the case of a solaris dom0+xvm
  64  * this would be qemu.  So to work around this issue, this driver will
  65  * query the emulated hardware to get the assigned physical geometry
  66  * and then pass this geometry onto the xdf driver so that it can use it.
  67  * But really, this information is essentially metadata about the disk
  68  * that should be kept with the disk image itself.  (Assuming or course
  69  * that a disk image is the actual backingstore for this emulated device.)
  70  * This metadata should also be made available to PV drivers via a common
  71  * mechanism, probably the xenstore.  The fact that this metadata isn't
  72  * available outside of HVM domains means that it's difficult to move
  73  * disks between HVM and PV domains, since a fully PV domain will have no
  74  * way of knowing what the correct geometry of the target device is.
  75  * (Short of reading the disk, looking for things like partition tables
  76  * and labels, and taking a best guess at what the geometry was when
  77  * the disk was initialized.  Unsuprisingly, qemu actually does this.)
  78  *
  79  * This driver has to map xdf shell device instances into their corresponding
  80  * xdf device instances.  We have to do this to ensure that when a user
  81  * accesses a emulated xdf shell device we map those accesses to the proper
  82  * paravirtualized device.  Basically what we need to know is how multiple
  83  * 'disk' entries in a domU configuration file get mapped to emulated
  84  * xdf shell devices and to xdf devices.  The 'disk' entry to xdf instance
  85  * mappings we know because those are done within the Solaris xvdi code
  86  * and the xpvd nexus driver.  But the config to emulated devices mappings
  87  * are handled entirely within the xen management tool chain and the
  88  * hardware emulator.  Since all the tools that establish these mappings
  89  * live in dom0, dom0 should really supply us with this information,
  90  * probably via the xenstore.  Unfortunatly it doesn't so, since there's
  91  * no good way to determine this mapping dynamically, this driver uses
  92  * a hard coded set of static mappings.  These mappings are hardware
  93  * emulator specific because each different hardware emulator could have
  94  * a different device tree with different xdf shell device paths.  This
  95  * means that if we want to continue to use this static mapping approach
  96  * to allow Solaris to run on different hardware emulators we'll have
  97  * to analyze each of those emulators to determine what paths they
  98  * use and hard code those paths into this driver.  yech.  This metadata
  99  * really needs to be supplied to us by dom0.
 100  *
 101  * This driver access underlying xdf nodes.  Unfortunatly, devices
 102  * must create minor nodes during attach, and for disk devices to create
 103  * minor nodes, they have to look at the label on the disk, so this means
 104  * that disk drivers must be able to access a disk contents during
 105  * attach.  That means that this disk driver must be able to access
 106  * underlying xdf nodes during attach.  Unfortunatly, due to device tree
 107  * locking restrictions, we cannot have an attach operation occuring on
 108  * this device and then attempt to access another device which may
 109  * cause another attach to occur in a different device tree branch
 110  * since this could result in deadlock.  Hence, this driver can only
 111  * access xdf device nodes that we know are attached, and it can't use
 112  * any ddi interfaces to access those nodes if those interfaces could
 113  * trigger an attach of the xdf device.  So this driver works around
 114  * these restrictions by talking directly to xdf devices via
 115  * xdf_hvm_hold().  This interface takes a pathname to an xdf device,
 116  * and if that device is already attached then it returns the a held dip
 117  * pointer for that device node.  This prevents us from getting into
 118  * deadlock situations, but now we need a mechanism to ensure that all
 119  * the xdf device nodes this driver might access are attached before
 120  * this driver tries to access them.  This is accomplished via the
 121  * hvmboot_rootconf() callback which is invoked just before root is
 122  * mounted.  hvmboot_rootconf() will attach xpvd and tell it to configure
 123  * all xdf device visible to the system.  All these xdf device nodes
 124  * will also be marked with the "ddi-no-autodetach" property so that
 125  * once they are configured, the will not be automatically unconfigured.
 126  * The only way that they could be unconfigured is if the administrator
 127  * explicitly attempts to unload required modules via rem_drv(1M)
 128  * or modunload(1M).
 129  */
 130 
 131 /*
 132  * 16 paritions + fdisk (see xdf.h)
 133  */
 134 #define XDFS_DEV2UNIT(dev)      XDF_INST((getminor((dev))))
 135 #define XDFS_DEV2PART(dev)      XDF_PART((getminor((dev))))
 136 
 137 #define OTYP_VALID(otyp)        ((otyp == OTYP_BLK) ||                  \
 138                                         (otyp == OTYP_CHR) ||           \
 139                                         (otyp == OTYP_LYR))
 140 
 141 #define XDFS_NODES              4
 142 
 143 #define XDFS_HVM_MODE(sp)       (XDFS_HVM_STATE(sp)->xdfs_hs_mode)
 144 #define XDFS_HVM_DIP(sp)        (XDFS_HVM_STATE(sp)->xdfs_hs_dip)
 145 #define XDFS_HVM_PATH(sp)       (XDFS_HVM_STATE(sp)->xdfs_hs_path)
 146 #define XDFS_HVM_STATE(sp)                                              \
 147                 ((xdfs_hvm_state_t *)(&((char *)(sp))[XDFS_HVM_STATE_OFFSET]))
 148 #define XDFS_HVM_STATE_OFFSET   (xdfs_ss_size - sizeof (xdfs_hvm_state_t))
 149 #define XDFS_HVM_SANE(sp)                                               \
 150                 ASSERT(XDFS_HVM_MODE(sp));                              \
 151                 ASSERT(XDFS_HVM_DIP(sp) != NULL);                       \
 152                 ASSERT(XDFS_HVM_PATH(sp) != NULL);
 153 
 154 
 155 typedef struct xdfs_hvm_state {
 156         boolean_t       xdfs_hs_mode;
 157         dev_info_t      *xdfs_hs_dip;
 158         char            *xdfs_hs_path;
 159 } xdfs_hvm_state_t;
 160 
 161 /* local function and structure prototypes */
 162 static int xdfs_iodone(struct buf *);
 163 static boolean_t xdfs_isopen_part(xdfs_state_t *, int);
 164 static boolean_t xdfs_isopen(xdfs_state_t *);
 165 static cmlb_tg_ops_t xdfs_lb_ops;
 166 
 167 /*
 168  * Globals
 169  */
 170 major_t                 xdfs_major;
 171 #define                 xdfs_hvm_dev_ops (xdfs_c_hvm_dev_ops)
 172 #define                 xdfs_hvm_cb_ops (xdfs_hvm_dev_ops->devo_cb_ops)
 173 
 174 /*
 175  * Private globals
 176  */
 177 volatile boolean_t      xdfs_pv_disable = B_FALSE;
 178 static void             *xdfs_ssp;
 179 static size_t           xdfs_ss_size;
 180 
 181 /*
 182  * Private helper functions
 183  */
 184 static boolean_t
 185 xdfs_tgt_hold(xdfs_state_t *xsp)
 186 {
 187         mutex_enter(&xsp->xdfss_mutex);
 188         ASSERT(xsp->xdfss_tgt_holds >= 0);
 189         if (!xsp->xdfss_tgt_attached) {
 190                 mutex_exit(&xsp->xdfss_mutex);
 191                 return (B_FALSE);
 192         }
 193         xsp->xdfss_tgt_holds++;
 194         mutex_exit(&xsp->xdfss_mutex);
 195         return (B_TRUE);
 196 }
 197 
 198 static void
 199 xdfs_tgt_release(xdfs_state_t *xsp)
 200 {
 201         mutex_enter(&xsp->xdfss_mutex);
 202         ASSERT(xsp->xdfss_tgt_attached);
 203         ASSERT(xsp->xdfss_tgt_holds > 0);
 204         if (--xsp->xdfss_tgt_holds == 0)
 205                 cv_broadcast(&xsp->xdfss_cv);
 206         mutex_exit(&xsp->xdfss_mutex);
 207 }
 208 
 209 /*ARGSUSED*/
 210 static int
 211 xdfs_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie)
 212 {
 213         int             instance = ddi_get_instance(dip);
 214         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 215         int             rv;
 216 
 217         if (xsp == NULL)
 218                 return (ENXIO);
 219 
 220         if (!xdfs_tgt_hold(xsp))
 221                 return (ENXIO);
 222 
 223         if (cmd == TG_GETVIRTGEOM) {
 224                 cmlb_geom_t     pgeom, *vgeomp;
 225                 diskaddr_t      capacity;
 226 
 227                 /*
 228                  * The native xdf driver doesn't support this ioctl.
 229                  * Intead of passing it on, emulate it here so that the
 230                  * results look the same as what we get for a real xdf
 231                  * shell device.
 232                  *
 233                  * Get the real size of the device
 234                  */
 235                 if ((rv = xdf_lb_getinfo(xsp->xdfss_tgt_dip,
 236                     TG_GETPHYGEOM, &pgeom, tg_cookie)) != 0)
 237                         goto out;
 238                 capacity = pgeom.g_capacity;
 239 
 240                 /*
 241                  * If the controller returned us something that doesn't
 242                  * really fit into an Int 13/function 8 geometry
 243                  * result, just fail the ioctl.  See PSARC 1998/313.
 244                  */
 245                 if (capacity >= (63 * 254 * 1024)) {
 246                         rv = EINVAL;
 247                         goto out;
 248                 }
 249 
 250                 vgeomp = (cmlb_geom_t *)arg;
 251                 vgeomp->g_capacity   = capacity;
 252                 vgeomp->g_nsect              = 63;
 253                 vgeomp->g_nhead              = 254;
 254                 vgeomp->g_ncyl               = capacity / (63 * 254);
 255                 vgeomp->g_acyl               = 0;
 256                 vgeomp->g_secsize    = 512;
 257                 vgeomp->g_intrlv     = 1;
 258                 vgeomp->g_rpm                = 3600;
 259                 rv = 0;
 260                 goto out;
 261         }
 262 
 263         rv = xdf_lb_getinfo(xsp->xdfss_tgt_dip, cmd, arg, tg_cookie);
 264 
 265 out:
 266         xdfs_tgt_release(xsp);
 267         return (rv);
 268 }
 269 
 270 static boolean_t
 271 xdfs_isopen_part(xdfs_state_t *xsp, int part)
 272 {
 273         int otyp;
 274 
 275         ASSERT(MUTEX_HELD(&xsp->xdfss_mutex));
 276         for (otyp = 0; (otyp < OTYPCNT); otyp++) {
 277                 if (xsp->xdfss_otyp_count[otyp][part] != 0) {
 278                         ASSERT(xsp->xdfss_tgt_attached);
 279                         ASSERT(xsp->xdfss_tgt_holds >= 0);
 280                         return (B_TRUE);
 281                 }
 282         }
 283         return (B_FALSE);
 284 }
 285 
 286 static boolean_t
 287 xdfs_isopen(xdfs_state_t *xsp)
 288 {
 289         int part;
 290 
 291         ASSERT(MUTEX_HELD(&xsp->xdfss_mutex));
 292         for (part = 0; part < XDF_PEXT; part++) {
 293                 if (xdfs_isopen_part(xsp, part))
 294                         return (B_TRUE);
 295         }
 296         return (B_FALSE);
 297 }
 298 
 299 static int
 300 xdfs_iodone(struct buf *bp)
 301 {
 302         struct buf      *bp_orig = bp->b_chain;
 303 
 304         /* Propegate back the io results */
 305         bp_orig->b_resid = bp->b_resid;
 306         bioerror(bp_orig, geterror(bp));
 307         biodone(bp_orig);
 308 
 309         freerbuf(bp);
 310         return (0);
 311 }
 312 
 313 static int
 314 xdfs_cmlb_attach(xdfs_state_t *xsp)
 315 {
 316         return (cmlb_attach(xsp->xdfss_dip, &xdfs_lb_ops,
 317             xsp->xdfss_tgt_is_cd ? DTYPE_RODIRECT : DTYPE_DIRECT,
 318             xdf_is_rm(xsp->xdfss_tgt_dip),
 319             B_TRUE,
 320             xdfs_c_cmlb_node_type(xsp),
 321             xdfs_c_cmlb_alter_behavior(xsp),
 322             xsp->xdfss_cmlbhandle, 0));
 323 }
 324 
 325 static boolean_t
 326 xdfs_tgt_probe(xdfs_state_t *xsp, dev_info_t *tgt_dip)
 327 {
 328         cmlb_geom_t             pgeom;
 329         int                     tgt_instance = ddi_get_instance(tgt_dip);
 330 
 331         ASSERT(MUTEX_HELD(&xsp->xdfss_mutex));
 332         ASSERT(!xdfs_isopen(xsp));
 333         ASSERT(!xsp->xdfss_tgt_attached);
 334 
 335         xsp->xdfss_tgt_dip = tgt_dip;
 336         xsp->xdfss_tgt_holds = 0;
 337         xsp->xdfss_tgt_dev = makedevice(ddi_driver_major(tgt_dip),
 338             XDF_MINOR(tgt_instance, 0));
 339         ASSERT((xsp->xdfss_tgt_dev & XDF_PMASK) == 0);
 340         xsp->xdfss_tgt_is_cd = xdf_is_cd(tgt_dip);
 341 
 342         /*
 343          * GROSS HACK ALERT!  GROSS HACK ALERT!
 344          *
 345          * Before we can initialize the cmlb layer, we have to tell the
 346          * underlying xdf device what it's physical geometry should be.
 347          * See the block comments at the top of this file for more info.
 348          */
 349         if (!xsp->xdfss_tgt_is_cd &&
 350             ((xdfs_c_getpgeom(xsp->xdfss_dip, &pgeom) != 0) ||
 351             (xdf_hvm_setpgeom(xsp->xdfss_tgt_dip, &pgeom) != 0)))
 352                 return (B_FALSE);
 353 
 354         /*
 355          * Force the xdf front end driver to connect to the backend.  From
 356          * the solaris device tree perspective, the xdf driver devinfo node
 357          * is already in the ATTACHED state.  (Otherwise xdf_hvm_hold()
 358          * would not have returned a dip.)  But this doesn't mean that the
 359          * xdf device has actually established a connection to it's back
 360          * end driver.  For us to be able to access the xdf device it needs
 361          * to be connected.
 362          */
 363         if (!xdf_hvm_connect(xsp->xdfss_tgt_dip)) {
 364                 cmn_err(CE_WARN, "pv driver failed to connect: %s",
 365                     xsp->xdfss_pv);
 366                 return (B_FALSE);
 367         }
 368 
 369         if (xsp->xdfss_tgt_is_cd && !xdf_media_req_supported(tgt_dip)) {
 370                 /*
 371                  * Unfortunatly, the dom0 backend driver doesn't support
 372                  * important media request operations like eject, so fail
 373                  * the probe (this should cause us to fall back to emulated
 374                  * hvm device access, which does support things like eject).
 375                  */
 376                 return (B_FALSE);
 377         }
 378 
 379         /* create kstat for iostat(1M) */
 380         if (xdf_kstat_create(xsp->xdfss_tgt_dip, (char *)xdfs_c_name,
 381             tgt_instance) != 0)
 382                 return (B_FALSE);
 383 
 384         /*
 385          * Now we need to mark ourselves as attached and drop xdfss_mutex.
 386          * We do this because the final steps in the attach process will
 387          * need to access the underlying disk to read the label and
 388          * possibly the devid.
 389          */
 390         xsp->xdfss_tgt_attached = B_TRUE;
 391         mutex_exit(&xsp->xdfss_mutex);
 392 
 393         if (!xsp->xdfss_tgt_is_cd && xdfs_c_bb_check(xsp)) {
 394                 cmn_err(CE_WARN, "pv disks with bad blocks are unsupported: %s",
 395                     xsp->xdfss_hvm);
 396                 mutex_enter(&xsp->xdfss_mutex);
 397                 xdf_kstat_delete(xsp->xdfss_tgt_dip);
 398                 xsp->xdfss_tgt_attached = B_FALSE;
 399                 return (B_FALSE);
 400         }
 401 
 402         /*
 403          * Initalize cmlb.  Note that for partition information cmlb
 404          * will access the underly xdf disk device directly via
 405          * xdfs_lb_rdwr() and xdfs_lb_getinfo().  There are no
 406          * layered driver handles associated with this access because
 407          * it is a direct disk access that doesn't go through
 408          * any of the device nodes exported by the xdf device (since
 409          * all exported device nodes only reflect the portion of
 410          * the device visible via the partition/slice that the node
 411          * is associated with.)  So while not observable via the LDI,
 412          * this direct disk access is ok since we're actually holding
 413          * the target device.
 414          */
 415         if (xdfs_cmlb_attach(xsp) != 0) {
 416                 mutex_enter(&xsp->xdfss_mutex);
 417                 xdf_kstat_delete(xsp->xdfss_tgt_dip);
 418                 xsp->xdfss_tgt_attached = B_FALSE;
 419                 return (B_FALSE);
 420         }
 421 
 422         /* setup devid string */
 423         xsp->xdfss_tgt_devid = NULL;
 424         if (!xsp->xdfss_tgt_is_cd)
 425                 xdfs_c_devid_setup(xsp);
 426 
 427         (void) cmlb_validate(xsp->xdfss_cmlbhandle, 0, 0);
 428 
 429         /* Have the system report any newly created device nodes */
 430         ddi_report_dev(xsp->xdfss_dip);
 431 
 432         mutex_enter(&xsp->xdfss_mutex);
 433         return (B_TRUE);
 434 }
 435 
 436 static boolean_t
 437 xdfs_tgt_detach(xdfs_state_t *xsp)
 438 {
 439         ASSERT(MUTEX_HELD(&xsp->xdfss_mutex));
 440         ASSERT(xsp->xdfss_tgt_attached);
 441         ASSERT(xsp->xdfss_tgt_holds >= 0);
 442 
 443         if ((xdfs_isopen(xsp)) || (xsp->xdfss_tgt_holds != 0))
 444                 return (B_FALSE);
 445 
 446         ddi_devid_unregister(xsp->xdfss_dip);
 447         if (xsp->xdfss_tgt_devid != NULL)
 448                 ddi_devid_free(xsp->xdfss_tgt_devid);
 449 
 450         xdf_kstat_delete(xsp->xdfss_tgt_dip);
 451         xsp->xdfss_tgt_attached = B_FALSE;
 452         return (B_TRUE);
 453 }
 454 
 455 /*
 456  * Xdf_shell interfaces that may be called from outside this file.
 457  */
 458 void
 459 xdfs_minphys(struct buf *bp)
 460 {
 461         xdfmin(bp);
 462 }
 463 
 464 /*
 465  * Cmlb ops vector, allows the cmlb module to directly access the entire
 466  * xdf disk device without going through any partitioning layers.
 467  */
 468 int
 469 xdfs_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr,
 470     diskaddr_t start, size_t count, void *tg_cookie)
 471 {
 472         int             instance = ddi_get_instance(dip);
 473         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 474         int             rv;
 475 
 476         if (xsp == NULL)
 477                 return (ENXIO);
 478 
 479         if (!xdfs_tgt_hold(xsp))
 480                 return (ENXIO);
 481 
 482         rv = xdf_lb_rdwr(xsp->xdfss_tgt_dip,
 483             cmd, bufaddr, start, count, tg_cookie);
 484 
 485         xdfs_tgt_release(xsp);
 486         return (rv);
 487 }
 488 
 489 /*
 490  * Driver PV and HVM cb_ops entry points
 491  */
 492 /*ARGSUSED*/
 493 static int
 494 xdfs_open(dev_t *dev_p, int flag, int otyp, cred_t *credp)
 495 {
 496         ldi_ident_t     li;
 497         dev_t           dev = *dev_p;
 498         int             instance = XDFS_DEV2UNIT(dev);
 499         int             part = XDFS_DEV2PART(dev);
 500         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 501         dev_t           tgt_devt = xsp->xdfss_tgt_dev | part;
 502         int             err = 0;
 503 
 504         if ((otyp < 0) || (otyp >= OTYPCNT))
 505                 return (EINVAL);
 506 
 507         if (XDFS_HVM_MODE(xsp)) {
 508                 if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL))
 509                         return (ENOTSUP);
 510                 return (xdfs_hvm_cb_ops->cb_open(dev_p, flag, otyp, credp));
 511         }
 512 
 513         /* allocate an ldi handle */
 514         VERIFY(ldi_ident_from_dev(*dev_p, &li) == 0);
 515 
 516         mutex_enter(&xsp->xdfss_mutex);
 517 
 518         /*
 519          * We translate all device opens (chr, blk, and lyr) into
 520          * block device opens.  Why?  Because for all the opens that
 521          * come through this driver, we only keep around one LDI handle.
 522          * So that handle can only be of one open type.  The reason
 523          * that we choose the block interface for this is that to use
 524          * the block interfaces for a device the system needs to allocate
 525          * buf_ts, which are associated with system memory which can act
 526          * as a cache for device data.  So normally when a block device
 527          * is closed the system will ensure that all these pages get
 528          * flushed out of memory.  But if we were to open the device
 529          * as a character device, then when we went to close the underlying
 530          * device (even if we had invoked the block interfaces) any data
 531          * remaining in memory wouldn't necessairly be flushed out
 532          * before the device was closed.
 533          */
 534         if (xsp->xdfss_tgt_lh[part] == NULL) {
 535                 ASSERT(!xdfs_isopen_part(xsp, part));
 536 
 537                 err = ldi_open_by_dev(&tgt_devt, OTYP_BLK, flag, credp,
 538                     &xsp->xdfss_tgt_lh[part], li);
 539 
 540                 if (err != 0) {
 541                         mutex_exit(&xsp->xdfss_mutex);
 542                         ldi_ident_release(li);
 543                         return (err);
 544                 }
 545 
 546                 /* Disk devices really shouldn't clone */
 547                 ASSERT(tgt_devt == (xsp->xdfss_tgt_dev | part));
 548         } else {
 549                 ldi_handle_t lh_tmp;
 550 
 551                 ASSERT(xdfs_isopen_part(xsp, part));
 552 
 553                 /* do ldi open/close to get flags and cred check */
 554                 err = ldi_open_by_dev(&tgt_devt, OTYP_BLK, flag, credp,
 555                     &lh_tmp, li);
 556                 if (err != 0) {
 557                         mutex_exit(&xsp->xdfss_mutex);
 558                         ldi_ident_release(li);
 559                         return (err);
 560                 }
 561 
 562                 /* Disk devices really shouldn't clone */
 563                 ASSERT(tgt_devt == (xsp->xdfss_tgt_dev | part));
 564                 (void) ldi_close(lh_tmp, flag, credp);
 565         }
 566         ldi_ident_release(li);
 567 
 568         xsp->xdfss_otyp_count[otyp][part]++;
 569 
 570         mutex_exit(&xsp->xdfss_mutex);
 571         return (0);
 572 }
 573 
 574 /*ARGSUSED*/
 575 static int
 576 xdfs_close(dev_t dev, int flag, int otyp, cred_t *credp)
 577 {
 578         int             instance = XDFS_DEV2UNIT(dev);
 579         int             part = XDFS_DEV2PART(dev);
 580         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 581         int             err = 0;
 582 
 583         ASSERT((otyp >= 0) && otyp < OTYPCNT);
 584 
 585         /* Sanity check the dev_t associated with this request. */
 586         ASSERT(getmajor(dev) == xdfs_major);
 587         if (getmajor(dev) != xdfs_major)
 588                 return (ENXIO);
 589 
 590         if (XDFS_HVM_MODE(xsp)) {
 591                 if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL))
 592                         return (ENOTSUP);
 593                 return (xdfs_hvm_cb_ops->cb_close(dev, flag, otyp, credp));
 594         }
 595 
 596         /*
 597          * Sanity check that that the device is actually open.  On debug
 598          * kernels we'll panic and on non-debug kernels we'll return failure.
 599          */
 600         mutex_enter(&xsp->xdfss_mutex);
 601         ASSERT(xdfs_isopen_part(xsp, part));
 602         if (!xdfs_isopen_part(xsp, part)) {
 603                 mutex_exit(&xsp->xdfss_mutex);
 604                 return (ENXIO);
 605         }
 606 
 607         ASSERT(xsp->xdfss_tgt_lh[part] != NULL);
 608         ASSERT(xsp->xdfss_otyp_count[otyp][part] > 0);
 609         if (otyp == OTYP_LYR) {
 610                 xsp->xdfss_otyp_count[otyp][part]--;
 611         } else {
 612                 xsp->xdfss_otyp_count[otyp][part] = 0;
 613         }
 614 
 615         if (!xdfs_isopen_part(xsp, part)) {
 616                 err = ldi_close(xsp->xdfss_tgt_lh[part], flag, credp);
 617                 xsp->xdfss_tgt_lh[part] = NULL;
 618         }
 619 
 620         mutex_exit(&xsp->xdfss_mutex);
 621 
 622         return (err);
 623 }
 624 
 625 int
 626 xdfs_strategy(struct buf *bp)
 627 {
 628         dev_t           dev = bp->b_edev;
 629         int             instance = XDFS_DEV2UNIT(dev);
 630         int             part = XDFS_DEV2PART(dev);
 631         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 632         dev_t           tgt_devt;
 633         struct buf      *bp_clone;
 634 
 635         /* Sanity check the dev_t associated with this request. */
 636         ASSERT(getmajor(dev) == xdfs_major);
 637         if (getmajor(dev) != xdfs_major)
 638                 goto err;
 639 
 640         if (XDFS_HVM_MODE(xsp)) {
 641                 if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL))
 642                         return (ENOTSUP);
 643                 return (xdfs_hvm_cb_ops->cb_strategy(bp));
 644         }
 645 
 646         /*
 647          * Sanity checks that the dev_t associated with the buf we were
 648          * passed corresponds to an open partition.  On debug kernels we'll
 649          * panic and on non-debug kernels we'll return failure.
 650          */
 651         mutex_enter(&xsp->xdfss_mutex);
 652         ASSERT(xdfs_isopen_part(xsp, part));
 653         if (!xdfs_isopen_part(xsp, part)) {
 654                 mutex_exit(&xsp->xdfss_mutex);
 655                 goto err;
 656         }
 657         mutex_exit(&xsp->xdfss_mutex);
 658 
 659         /* clone this buffer */
 660         tgt_devt = xsp->xdfss_tgt_dev | part;
 661         bp_clone = bioclone(bp, 0, bp->b_bcount, tgt_devt, bp->b_blkno,
 662             xdfs_iodone, NULL, KM_SLEEP);
 663         bp_clone->b_chain = bp;
 664 
 665         /*
 666          * If we're being invoked on behalf of the physio() call in
 667          * xdfs_dioctl_rwcmd() then b_private will be set to
 668          * XB_SLICE_NONE and we need to propegate this flag into the
 669          * cloned buffer so that the xdf driver will see it.
 670          */
 671         if (bp->b_private == (void *)XB_SLICE_NONE)
 672                 bp_clone->b_private = (void *)XB_SLICE_NONE;
 673 
 674         /*
 675          * Pass on the cloned buffer.  Note that we don't bother to check
 676          * for failure because the xdf strategy routine will have to
 677          * invoke biodone() if it wants to return an error, which means
 678          * that the xdfs_iodone() callback will get invoked and it
 679          * will propegate the error back up the stack and free the cloned
 680          * buffer.
 681          */
 682         ASSERT(xsp->xdfss_tgt_lh[part] != NULL);
 683         return (ldi_strategy(xsp->xdfss_tgt_lh[part], bp_clone));
 684 
 685 err:
 686         bioerror(bp, ENXIO);
 687         bp->b_resid = bp->b_bcount;
 688         biodone(bp);
 689         return (0);
 690 }
 691 
 692 static int
 693 xdfs_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk)
 694 {
 695         int             instance = XDFS_DEV2UNIT(dev);
 696         int             part = XDFS_DEV2PART(dev);
 697         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 698 
 699         if (!XDFS_HVM_MODE(xsp))
 700                 return (ldi_dump(xsp->xdfss_tgt_lh[part], addr, blkno, nblk));
 701 
 702         if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL))
 703                 return (ENOTSUP);
 704         return (xdfs_hvm_cb_ops->cb_dump(dev, addr, blkno, nblk));
 705 }
 706 
 707 /*ARGSUSED*/
 708 static int
 709 xdfs_read(dev_t dev, struct uio *uio, cred_t *credp)
 710 {
 711         int             instance = XDFS_DEV2UNIT(dev);
 712         int             part = XDFS_DEV2PART(dev);
 713         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 714 
 715         if (!XDFS_HVM_MODE(xsp))
 716                 return (ldi_read(xsp->xdfss_tgt_lh[part], uio, credp));
 717 
 718         if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL))
 719                 return (ENOTSUP);
 720         return (xdfs_hvm_cb_ops->cb_read(dev, uio, credp));
 721 }
 722 
 723 /*ARGSUSED*/
 724 static int
 725 xdfs_write(dev_t dev, struct uio *uio, cred_t *credp)
 726 {
 727         int             instance = XDFS_DEV2UNIT(dev);
 728         int             part = XDFS_DEV2PART(dev);
 729         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 730 
 731         if (!XDFS_HVM_MODE(xsp))
 732                 return (ldi_write(xsp->xdfss_tgt_lh[part], uio, credp));
 733 
 734         if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL))
 735                 return (ENOTSUP);
 736         return (xdfs_hvm_cb_ops->cb_write(dev, uio, credp));
 737 }
 738 
 739 /*ARGSUSED*/
 740 static int
 741 xdfs_aread(dev_t dev, struct aio_req *aio, cred_t *credp)
 742 {
 743         int             instance = XDFS_DEV2UNIT(dev);
 744         int             part = XDFS_DEV2PART(dev);
 745         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 746 
 747         if (!XDFS_HVM_MODE(xsp))
 748                 return (ldi_aread(xsp->xdfss_tgt_lh[part], aio, credp));
 749 
 750         if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL) ||
 751             (xdfs_hvm_cb_ops->cb_strategy == NULL) ||
 752             (xdfs_hvm_cb_ops->cb_strategy == nodev) ||
 753             (xdfs_hvm_cb_ops->cb_aread == NULL))
 754                 return (ENOTSUP);
 755         return (xdfs_hvm_cb_ops->cb_aread(dev, aio, credp));
 756 }
 757 
 758 /*ARGSUSED*/
 759 static int
 760 xdfs_awrite(dev_t dev, struct aio_req *aio, cred_t *credp)
 761 {
 762         int             instance = XDFS_DEV2UNIT(dev);
 763         int             part = XDFS_DEV2PART(dev);
 764         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 765 
 766         if (!XDFS_HVM_MODE(xsp))
 767                 return (ldi_awrite(xsp->xdfss_tgt_lh[part], aio, credp));
 768 
 769         if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL) ||
 770             (xdfs_hvm_cb_ops->cb_strategy == NULL) ||
 771             (xdfs_hvm_cb_ops->cb_strategy == nodev) ||
 772             (xdfs_hvm_cb_ops->cb_awrite == NULL))
 773                 return (ENOTSUP);
 774         return (xdfs_hvm_cb_ops->cb_awrite(dev, aio, credp));
 775 }
 776 
 777 static int
 778 xdfs_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp,
 779     int *rvalp)
 780 {
 781         int             instance = XDFS_DEV2UNIT(dev);
 782         int             part = XDFS_DEV2PART(dev);
 783         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 784         int             rv;
 785         boolean_t       done;
 786 
 787         if (XDFS_HVM_MODE(xsp)) {
 788                 if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL))
 789                         return (ENOTSUP);
 790                 return (xdfs_hvm_cb_ops->cb_ioctl(
 791                     dev, cmd, arg, flag, credp, rvalp));
 792         }
 793 
 794         rv = xdfs_c_ioctl(xsp, dev, part, cmd, arg, flag, credp, rvalp, &done);
 795         if (done)
 796                 return (rv);
 797         rv = ldi_ioctl(xsp->xdfss_tgt_lh[part], cmd, arg, flag, credp, rvalp);
 798         if (rv == 0) {
 799                 /* Force Geometry Validation */
 800                 (void) cmlb_invalidate(xsp->xdfss_cmlbhandle, 0);
 801                 (void) cmlb_validate(xsp->xdfss_cmlbhandle, 0, 0);
 802         }
 803         return (rv);
 804 }
 805 
 806 static int
 807 xdfs_hvm_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
 808     int flags, char *name, caddr_t valuep, int *lengthp)
 809 {
 810         int             instance = ddi_get_instance(dip);
 811         void            *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 812 
 813         ASSERT(XDFS_HVM_MODE(xsp));
 814 
 815         if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL) ||
 816             (xdfs_hvm_cb_ops->cb_prop_op == NULL) ||
 817             (xdfs_hvm_cb_ops->cb_prop_op == nodev) ||
 818             (xdfs_hvm_cb_ops->cb_prop_op == nulldev))
 819                 return (DDI_PROP_NOT_FOUND);
 820 
 821         return (xdfs_hvm_cb_ops->cb_prop_op(dev, dip, prop_op,
 822             flags, name, valuep, lengthp));
 823 }
 824 
 825 static int
 826 xdfs_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
 827     int flags, char *name, caddr_t valuep, int *lengthp)
 828 {
 829         int             instance = ddi_get_instance(dip);
 830         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 831         int             rv;
 832         dev_info_t      *tgt_dip;
 833         dev_t           tgt_devt;
 834 
 835         /*
 836          * Sanity check that if a dev_t or dip were specified that they
 837          * correspond to this device driver.  On debug kernels we'll
 838          * panic and on non-debug kernels we'll return failure.
 839          */
 840         ASSERT(ddi_driver_major(dip) == xdfs_major);
 841         ASSERT((dev == DDI_DEV_T_ANY) || (getmajor(dev) == xdfs_major));
 842         if ((ddi_driver_major(dip) != xdfs_major) ||
 843             ((dev != DDI_DEV_T_ANY) && (getmajor(dev) != xdfs_major)))
 844                 return (DDI_PROP_NOT_FOUND);
 845 
 846         /*
 847          * This property lookup might be associated with a device node
 848          * that is not yet attached, if so pass it onto ddi_prop_op().
 849          */
 850         if (xsp == NULL)
 851                 return (ddi_prop_op(dev, dip, prop_op, flags,
 852                     name, valuep, lengthp));
 853 
 854         /* If we're accessing the device in hvm mode, pass this request on */
 855         if (XDFS_HVM_MODE(xsp))
 856                 return (xdfs_hvm_prop_op(dev, dip, prop_op,
 857                     flags, name, valuep, lengthp));
 858 
 859         /*
 860          * Make sure we only lookup static properties.
 861          *
 862          * If there are static properties of the underlying xdf driver
 863          * that we want to mirror, then we'll have to explicity look them
 864          * up and define them during attach.  There are a few reasons
 865          * for this.  Most importantly, most static properties are typed
 866          * and all dynamic properties are untyped, ie, for dynamic
 867          * properties the caller must know the type of the property and
 868          * how to interpret the value of the property.  the prop_op drivedr
 869          * entry point is only designed for returning dynamic/untyped
 870          * properties, so if we were to attempt to lookup and pass back
 871          * static properties of the underlying device here then we would
 872          * be losing the type information for those properties.  Another
 873          * reason we don't want to pass on static property requests is that
 874          * static properties are enumerable in the device tree, where as
 875          * dynamic ones are not.
 876          */
 877         flags |= DDI_PROP_DYNAMIC;
 878 
 879         /*
 880          * We can't use the ldi here to access the underlying device because
 881          * the ldi actually opens the device, and that open might fail if the
 882          * device has already been opened with the FEXCL flag.  If we used
 883          * the ldi here, it would also be possible for some other caller to
 884          * try open the device with the FEXCL flag and get a failure back
 885          * because we have it open to do a property query.  Instad we'll
 886          * grab a hold on the target dip.
 887          */
 888         if (!xdfs_tgt_hold(xsp))
 889                 return (DDI_PROP_NOT_FOUND);
 890 
 891         /* figure out dip the dev_t we're going to pass on down */
 892         tgt_dip = xsp->xdfss_tgt_dip;
 893         if (dev == DDI_DEV_T_ANY) {
 894                 tgt_devt = DDI_DEV_T_ANY;
 895         } else {
 896                 tgt_devt = xsp->xdfss_tgt_dev | XDFS_DEV2PART(dev);
 897         }
 898 
 899         /*
 900          * Cdev_prop_op() is not a public interface, and normally the caller
 901          * is required to make sure that the target driver actually implements
 902          * this interface before trying to invoke it.  In this case we know
 903          * that we're always accessing the xdf driver and it does have this
 904          * interface defined, so we can skip the check.
 905          */
 906         rv = cdev_prop_op(tgt_devt, tgt_dip,
 907             prop_op, flags, name, valuep, lengthp);
 908 
 909         xdfs_tgt_release(xsp);
 910         return (rv);
 911 }
 912 
 913 /*
 914  * Driver PV and HVM dev_ops entry points
 915  */
 916 /*ARGSUSED*/
 917 static int
 918 xdfs_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 919     void **result)
 920 {
 921         dev_t           dev = (dev_t)arg;
 922         int             instance = XDFS_DEV2UNIT(dev);
 923         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
 924 
 925         switch (infocmd) {
 926                 case DDI_INFO_DEVT2DEVINFO:
 927                         if (xsp == NULL)
 928                                 return (DDI_FAILURE);
 929                         if (XDFS_HVM_MODE(xsp))
 930                                 *result = XDFS_HVM_DIP(xsp);
 931                         else
 932                                 *result = (void *)xsp->xdfss_dip;
 933                         break;
 934                 case DDI_INFO_DEVT2INSTANCE:
 935                         *result = (void *)(intptr_t)instance;
 936                         break;
 937                 default:
 938                         return (DDI_FAILURE);
 939         }
 940         return (DDI_SUCCESS);
 941 }
 942 
 943 static int
 944 xdfs_hvm_probe(dev_info_t *dip, char *path)
 945 {
 946         int             instance = ddi_get_instance(dip);
 947         int             rv = DDI_PROBE_SUCCESS;
 948         void            *xsp;
 949 
 950         ASSERT(path != NULL);
 951         cmn_err(CE_WARN, "PV access to device disabled: %s", path);
 952 
 953         (void) ddi_soft_state_zalloc(xdfs_ssp, instance);
 954         VERIFY((xsp = ddi_get_soft_state(xdfs_ssp, instance)) != NULL);
 955 
 956         if ((xdfs_hvm_dev_ops == NULL) ||
 957             (xdfs_hvm_dev_ops->devo_probe == NULL) ||
 958             ((rv = xdfs_hvm_dev_ops->devo_probe(dip)) == DDI_PROBE_FAILURE)) {
 959                 ddi_soft_state_free(xdfs_ssp, instance);
 960                 cmn_err(CE_WARN, "HVM probe of device failed: %s", path);
 961                 kmem_free(path, MAXPATHLEN);
 962                 return (DDI_PROBE_FAILURE);
 963         }
 964 
 965         XDFS_HVM_MODE(xsp) = B_TRUE;
 966         XDFS_HVM_DIP(xsp) = dip;
 967         XDFS_HVM_PATH(xsp) = path;
 968 
 969         return (rv);
 970 }
 971 
 972 static int
 973 xdfs_probe(dev_info_t *dip)
 974 {
 975         int             instance = ddi_get_instance(dip);
 976         xdfs_state_t    *xsp;
 977         dev_info_t      *tgt_dip;
 978         char            *path;
 979         int             i, pv_disable;
 980 
 981         /* if we've already probed the device then there's nothing todo */
 982         if (ddi_get_soft_state(xdfs_ssp, instance))
 983                 return (DDI_PROBE_PARTIAL);
 984 
 985         /* Figure out our pathname */
 986         path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 987         (void) ddi_pathname(dip, path);
 988 
 989         /* see if we should disable pv access mode */
 990         pv_disable = ddi_prop_get_int(DDI_DEV_T_ANY,
 991             dip, DDI_PROP_NOTPROM, "pv_disable", 0);
 992 
 993         if (xdfs_pv_disable || pv_disable)
 994                 return (xdfs_hvm_probe(dip, path));
 995 
 996         /*
 997          * This xdf shell device layers on top of an xdf device.  So the first
 998          * thing we need to do is determine which xdf device instance this
 999          * xdf shell instance should be layered on top of.
1000          */
1001         for (i = 0; xdfs_c_h2p_map[i].xdfs_h2p_hvm != NULL; i++) {
1002                 if (strcmp(xdfs_c_h2p_map[i].xdfs_h2p_hvm, path) == 0)
1003                         break;
1004         }
1005 
1006         if ((xdfs_c_h2p_map[i].xdfs_h2p_hvm == NULL) ||
1007             ((tgt_dip = xdf_hvm_hold(xdfs_c_h2p_map[i].xdfs_h2p_pv)) == NULL)) {
1008                 /*
1009                  * UhOh.  We either don't know what xdf instance this xdf
1010                  * shell device should be mapped to or the xdf node assocaited
1011                  * with this instance isnt' attached.  in either case fall
1012                  * back to hvm access.
1013                  */
1014                 return (xdfs_hvm_probe(dip, path));
1015         }
1016 
1017         /* allocate and initialize our state structure */
1018         (void) ddi_soft_state_zalloc(xdfs_ssp, instance);
1019         xsp = ddi_get_soft_state(xdfs_ssp, instance);
1020         mutex_init(&xsp->xdfss_mutex, NULL, MUTEX_DRIVER, NULL);
1021         cv_init(&xsp->xdfss_cv, NULL, CV_DEFAULT, NULL);
1022         mutex_enter(&xsp->xdfss_mutex);
1023 
1024         xsp->xdfss_dip = dip;
1025         xsp->xdfss_pv = xdfs_c_h2p_map[i].xdfs_h2p_pv;
1026         xsp->xdfss_hvm = xdfs_c_h2p_map[i].xdfs_h2p_hvm;
1027         xsp->xdfss_tgt_attached = B_FALSE;
1028         cmlb_alloc_handle((cmlb_handle_t *)&xsp->xdfss_cmlbhandle);
1029 
1030         if (!xdfs_tgt_probe(xsp, tgt_dip)) {
1031                 mutex_exit(&xsp->xdfss_mutex);
1032                 cmlb_free_handle(&xsp->xdfss_cmlbhandle);
1033                 ddi_soft_state_free(xdfs_ssp, instance);
1034                 ddi_release_devi(tgt_dip);
1035                 return (xdfs_hvm_probe(dip, path));
1036         }
1037         mutex_exit(&xsp->xdfss_mutex);
1038 
1039         /*
1040          * Add a zero-length attribute to tell the world we support
1041          * kernel ioctls (for layered drivers).
1042          */
1043         (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
1044             DDI_KERNEL_IOCTL, NULL, 0);
1045 
1046         kmem_free(path, MAXPATHLEN);
1047         return (DDI_PROBE_SUCCESS);
1048 }
1049 
1050 static int
1051 xdfs_hvm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1052 {
1053         int             instance = ddi_get_instance(dip);
1054         void            *xsp = ddi_get_soft_state(xdfs_ssp, instance);
1055         int             rv = DDI_FAILURE;
1056 
1057         XDFS_HVM_SANE(xsp);
1058 
1059         if ((xdfs_hvm_dev_ops == NULL) ||
1060             (xdfs_hvm_dev_ops->devo_attach == NULL) ||
1061             ((rv = xdfs_hvm_dev_ops->devo_attach(dip, cmd)) != DDI_SUCCESS)) {
1062                 cmn_err(CE_WARN, "HVM attach of device failed: %s",
1063                     XDFS_HVM_PATH(xsp));
1064                 kmem_free(XDFS_HVM_PATH(xsp), MAXPATHLEN);
1065                 ddi_soft_state_free(xdfs_ssp, instance);
1066                 return (rv);
1067         }
1068 
1069         return (DDI_SUCCESS);
1070 }
1071 
1072 /*
1073  * Autoconfiguration Routines
1074  */
1075 static int
1076 xdfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1077 {
1078         int             instance = ddi_get_instance(dip);
1079         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
1080 
1081         if (xsp == NULL)
1082                 return (DDI_FAILURE);
1083         if (XDFS_HVM_MODE(xsp))
1084                 return (xdfs_hvm_attach(dip, cmd));
1085         if (cmd != DDI_ATTACH)
1086                 return (DDI_FAILURE);
1087 
1088         xdfs_c_attach(xsp);
1089         return (DDI_SUCCESS);
1090 }
1091 
1092 static int
1093 xdfs_hvm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1094 {
1095         int             instance = ddi_get_instance(dip);
1096         void            *xsp = ddi_get_soft_state(xdfs_ssp, instance);
1097         int             rv;
1098 
1099         XDFS_HVM_SANE(xsp);
1100 
1101         if ((xdfs_hvm_dev_ops == NULL) ||
1102             (xdfs_hvm_dev_ops->devo_detach == NULL))
1103                 return (DDI_FAILURE);
1104 
1105         if ((rv = xdfs_hvm_dev_ops->devo_detach(dip, cmd)) != DDI_SUCCESS)
1106                 return (rv);
1107 
1108         kmem_free(XDFS_HVM_PATH(xsp), MAXPATHLEN);
1109         ddi_soft_state_free(xdfs_ssp, instance);
1110         return (DDI_SUCCESS);
1111 }
1112 
1113 static int
1114 xdfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1115 {
1116         int             instance = ddi_get_instance(dip);
1117         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
1118 
1119         if (XDFS_HVM_MODE(xsp))
1120                 return (xdfs_hvm_detach(dip, cmd));
1121         if (cmd != DDI_DETACH)
1122                 return (DDI_FAILURE);
1123 
1124         mutex_enter(&xsp->xdfss_mutex);
1125         if (!xdfs_tgt_detach(xsp)) {
1126                 mutex_exit(&xsp->xdfss_mutex);
1127                 return (DDI_FAILURE);
1128         }
1129         mutex_exit(&xsp->xdfss_mutex);
1130 
1131         cmlb_detach(xsp->xdfss_cmlbhandle, 0);
1132         cmlb_free_handle(&xsp->xdfss_cmlbhandle);
1133         ddi_release_devi(xsp->xdfss_tgt_dip);
1134         ddi_soft_state_free(xdfs_ssp, instance);
1135         ddi_prop_remove_all(dip);
1136         return (DDI_SUCCESS);
1137 }
1138 
1139 static int
1140 xdfs_hvm_power(dev_info_t *dip, int component, int level)
1141 {
1142         int             instance = ddi_get_instance(dip);
1143         void            *xsp = ddi_get_soft_state(xdfs_ssp, instance);
1144 
1145         XDFS_HVM_SANE(xsp);
1146 
1147         if ((xdfs_hvm_dev_ops == NULL) ||
1148             (xdfs_hvm_dev_ops->devo_power == NULL))
1149                 return (DDI_FAILURE);
1150         return (xdfs_hvm_dev_ops->devo_power(dip, component, level));
1151 }
1152 
1153 static int
1154 xdfs_power(dev_info_t *dip, int component, int level)
1155 {
1156         int             instance = ddi_get_instance(dip);
1157         xdfs_state_t    *xsp = ddi_get_soft_state(xdfs_ssp, instance);
1158 
1159         if (XDFS_HVM_MODE(xsp))
1160                 return (xdfs_hvm_power(dip, component, level));
1161         return (nodev());
1162 }
1163 
1164 /*
1165  * Cmlb ops vector
1166  */
1167 static cmlb_tg_ops_t xdfs_lb_ops = {
1168         TG_DK_OPS_VERSION_1,
1169         xdfs_lb_rdwr,
1170         xdfs_lb_getinfo
1171 };
1172 
1173 /*
1174  * Device driver ops vector
1175  */
1176 static struct cb_ops xdfs_cb_ops = {
1177         xdfs_open,              /* open */
1178         xdfs_close,             /* close */
1179         xdfs_strategy,          /* strategy */
1180         nodev,                  /* print */
1181         xdfs_dump,              /* dump */
1182         xdfs_read,              /* read */
1183         xdfs_write,             /* write */
1184         xdfs_ioctl,             /* ioctl */
1185         nodev,                  /* devmap */
1186         nodev,                  /* mmap */
1187         nodev,                  /* segmap */
1188         nochpoll,               /* poll */
1189         xdfs_prop_op,           /* cb_prop_op */
1190         0,                      /* streamtab  */
1191         D_64BIT | D_MP | D_NEW, /* Driver comaptibility flag */
1192         CB_REV,                 /* cb_rev */
1193         xdfs_aread,             /* async read */
1194         xdfs_awrite             /* async write */
1195 };
1196 
1197 struct dev_ops xdfs_ops = {
1198         DEVO_REV,               /* devo_rev, */
1199         0,                      /* refcnt  */
1200         xdfs_getinfo,           /* info */
1201         nulldev,                /* identify */
1202         xdfs_probe,             /* probe */
1203         xdfs_attach,            /* attach */
1204         xdfs_detach,            /* detach */
1205         nodev,                  /* reset */
1206         &xdfs_cb_ops,               /* driver operations */
1207         NULL,                   /* bus operations */
1208         xdfs_power,             /* power */
1209         ddi_quiesce_not_supported, /* devo_quiesce */
1210 };
1211 
1212 /*
1213  * Module linkage information for the kernel.
1214  */
1215 static struct modldrv modldrv = {
1216         &mod_driverops,             /* Type of module.  This one is a driver. */
1217         NULL,                   /* Module description.  Set by _init() */
1218         &xdfs_ops,          /* Driver ops. */
1219 };
1220 
1221 static struct modlinkage modlinkage = {
1222         MODREV_1, { (void *)&modldrv, NULL }
1223 };
1224 
1225 int
1226 _init(void)
1227 {
1228         int rval;
1229 
1230         xdfs_major = ddi_name_to_major((char *)xdfs_c_name);
1231         if (xdfs_major == (major_t)-1)
1232                 return (EINVAL);
1233 
1234         /*
1235          * Determine the size of our soft state structure.  The base
1236          * size of the structure is the larger of the hvm clients state
1237          * structure, or our shell state structure.  Then we'll align
1238          * the end of the structure to a pointer boundry and append
1239          * a xdfs_hvm_state_t structure.  This way the xdfs_hvm_state_t
1240          * structure is always present and we can use it to determine the
1241          * current device access mode (hvm or shell).
1242          */
1243         xdfs_ss_size = MAX(xdfs_c_hvm_ss_size, sizeof (xdfs_state_t));
1244         xdfs_ss_size = P2ROUNDUP(xdfs_ss_size, sizeof (uintptr_t));
1245         xdfs_ss_size += sizeof (xdfs_hvm_state_t);
1246 
1247         /*
1248          * In general ide usually supports 4 disk devices, this same
1249          * limitation also applies to software emulating ide devices.
1250          * so by default we pre-allocate 4 xdf shell soft state structures.
1251          */
1252         if ((rval = ddi_soft_state_init(&xdfs_ssp,
1253             xdfs_ss_size, XDFS_NODES)) != 0)
1254                 return (rval);
1255         *xdfs_c_hvm_ss = xdfs_ssp;
1256 
1257         /* Install our module */
1258         if (modldrv.drv_linkinfo == NULL)
1259                 modldrv.drv_linkinfo = (char *)xdfs_c_linkinfo;
1260         if ((rval = mod_install(&modlinkage)) != 0) {
1261                 ddi_soft_state_fini(&xdfs_ssp);
1262                 return (rval);
1263         }
1264 
1265         return (0);
1266 }
1267 
1268 int
1269 _info(struct modinfo *modinfop)
1270 {
1271         if (modldrv.drv_linkinfo == NULL)
1272                 modldrv.drv_linkinfo = (char *)xdfs_c_linkinfo;
1273         return (mod_info(&modlinkage, modinfop));
1274 }
1275 
1276 int
1277 _fini(void)
1278 {
1279         int     rval;
1280         if ((rval = mod_remove(&modlinkage)) != 0)
1281                 return (rval);
1282         ddi_soft_state_fini(&xdfs_ssp);
1283         return (0);
1284 }