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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <io/xdf_shell.h>
28 #include <sys/scsi/scsi_types.h>
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.
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.)
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.
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)
132 * 16 paritions + fdisk (see xdf.h)
134 #define XDFS_DEV2UNIT(dev) XDF_INST((getminor((dev))))
135 #define XDFS_DEV2PART(dev) XDF_PART((getminor((dev))))
137 #define OTYP_VALID(otyp) ((otyp == OTYP_BLK) || \
138 (otyp == OTYP_CHR) || \
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);
155 typedef struct xdfs_hvm_state
{
156 boolean_t xdfs_hs_mode
;
157 dev_info_t
*xdfs_hs_dip
;
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
;
171 #define xdfs_hvm_dev_ops (xdfs_c_hvm_dev_ops)
172 #define xdfs_hvm_cb_ops (xdfs_hvm_dev_ops->devo_cb_ops)
177 volatile boolean_t xdfs_pv_disable
= B_FALSE
;
178 static void *xdfs_ssp
;
179 static size_t xdfs_ss_size
;
182 * Private helper functions
185 xdfs_tgt_hold(xdfs_state_t
*xsp
)
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
);
193 xsp
->xdfss_tgt_holds
++;
194 mutex_exit(&xsp
->xdfss_mutex
);
199 xdfs_tgt_release(xdfs_state_t
*xsp
)
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
);
211 xdfs_lb_getinfo(dev_info_t
*dip
, int cmd
, void *arg
, void *tg_cookie
)
213 int instance
= ddi_get_instance(dip
);
214 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
220 if (!xdfs_tgt_hold(xsp
))
223 if (cmd
== TG_GETVIRTGEOM
) {
224 cmlb_geom_t pgeom
, *vgeomp
;
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
233 * Get the real size of the device
235 if ((rv
= xdf_lb_getinfo(xsp
->xdfss_tgt_dip
,
236 TG_GETPHYGEOM
, &pgeom
, tg_cookie
)) != 0)
238 capacity
= pgeom
.g_capacity
;
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.
245 if (capacity
>= (63 * 254 * 1024)) {
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);
256 vgeomp
->g_secsize
= 512;
257 vgeomp
->g_intrlv
= 1;
258 vgeomp
->g_rpm
= 3600;
263 rv
= xdf_lb_getinfo(xsp
->xdfss_tgt_dip
, cmd
, arg
, tg_cookie
);
266 xdfs_tgt_release(xsp
);
271 xdfs_isopen_part(xdfs_state_t
*xsp
, int part
)
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);
287 xdfs_isopen(xdfs_state_t
*xsp
)
291 ASSERT(MUTEX_HELD(&xsp
->xdfss_mutex
));
292 for (part
= 0; part
< XDF_PEXT
; part
++) {
293 if (xdfs_isopen_part(xsp
, part
))
300 xdfs_iodone(struct buf
*bp
)
302 struct buf
*bp_orig
= bp
->b_chain
;
304 /* Propegate back the io results */
305 bp_orig
->b_resid
= bp
->b_resid
;
306 bioerror(bp_orig
, geterror(bp
));
314 xdfs_cmlb_attach(xdfs_state_t
*xsp
)
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
),
320 xdfs_c_cmlb_node_type(xsp
),
321 xdfs_c_cmlb_alter_behavior(xsp
),
322 xsp
->xdfss_cmlbhandle
, 0));
326 xdfs_tgt_probe(xdfs_state_t
*xsp
, dev_info_t
*tgt_dip
)
329 int tgt_instance
= ddi_get_instance(tgt_dip
);
331 ASSERT(MUTEX_HELD(&xsp
->xdfss_mutex
));
332 ASSERT(!xdfs_isopen(xsp
));
333 ASSERT(!xsp
->xdfss_tgt_attached
);
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
);
343 * GROSS HACK ALERT! GROSS HACK ALERT!
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.
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)))
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
363 if (!xdf_hvm_connect(xsp
->xdfss_tgt_dip
)) {
364 cmn_err(CE_WARN
, "pv driver failed to connect: %s",
369 if (xsp
->xdfss_tgt_is_cd
&& !xdf_media_req_supported(tgt_dip
)) {
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).
379 /* create kstat for iostat(1M) */
380 if (xdf_kstat_create(xsp
->xdfss_tgt_dip
, (char *)xdfs_c_name
,
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.
390 xsp
->xdfss_tgt_attached
= B_TRUE
;
391 mutex_exit(&xsp
->xdfss_mutex
);
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",
396 mutex_enter(&xsp
->xdfss_mutex
);
397 xdf_kstat_delete(xsp
->xdfss_tgt_dip
);
398 xsp
->xdfss_tgt_attached
= B_FALSE
;
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
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
;
422 /* setup devid string */
423 xsp
->xdfss_tgt_devid
= NULL
;
424 if (!xsp
->xdfss_tgt_is_cd
)
425 xdfs_c_devid_setup(xsp
);
427 (void) cmlb_validate(xsp
->xdfss_cmlbhandle
, 0, 0);
429 /* Have the system report any newly created device nodes */
430 ddi_report_dev(xsp
->xdfss_dip
);
432 mutex_enter(&xsp
->xdfss_mutex
);
437 xdfs_tgt_detach(xdfs_state_t
*xsp
)
439 ASSERT(MUTEX_HELD(&xsp
->xdfss_mutex
));
440 ASSERT(xsp
->xdfss_tgt_attached
);
441 ASSERT(xsp
->xdfss_tgt_holds
>= 0);
443 if ((xdfs_isopen(xsp
)) || (xsp
->xdfss_tgt_holds
!= 0))
446 ddi_devid_unregister(xsp
->xdfss_dip
);
447 if (xsp
->xdfss_tgt_devid
!= NULL
)
448 ddi_devid_free(xsp
->xdfss_tgt_devid
);
450 xdf_kstat_delete(xsp
->xdfss_tgt_dip
);
451 xsp
->xdfss_tgt_attached
= B_FALSE
;
456 * Xdf_shell interfaces that may be called from outside this file.
459 xdfs_minphys(struct buf
*bp
)
465 * Cmlb ops vector, allows the cmlb module to directly access the entire
466 * xdf disk device without going through any partitioning layers.
469 xdfs_lb_rdwr(dev_info_t
*dip
, uchar_t cmd
, void *bufaddr
,
470 diskaddr_t start
, size_t count
, void *tg_cookie
)
472 int instance
= ddi_get_instance(dip
);
473 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
479 if (!xdfs_tgt_hold(xsp
))
482 rv
= xdf_lb_rdwr(xsp
->xdfss_tgt_dip
,
483 cmd
, bufaddr
, start
, count
, tg_cookie
);
485 xdfs_tgt_release(xsp
);
490 * Driver PV and HVM cb_ops entry points
494 xdfs_open(dev_t
*dev_p
, int flag
, int otyp
, cred_t
*credp
)
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
;
504 if ((otyp
< 0) || (otyp
>= OTYPCNT
))
507 if (XDFS_HVM_MODE(xsp
)) {
508 if ((xdfs_hvm_dev_ops
== NULL
) || (xdfs_hvm_cb_ops
== NULL
))
510 return (xdfs_hvm_cb_ops
->cb_open(dev_p
, flag
, otyp
, credp
));
513 /* allocate an ldi handle */
514 VERIFY(ldi_ident_from_dev(*dev_p
, &li
) == 0);
516 mutex_enter(&xsp
->xdfss_mutex
);
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.
534 if (xsp
->xdfss_tgt_lh
[part
] == NULL
) {
535 ASSERT(!xdfs_isopen_part(xsp
, part
));
537 err
= ldi_open_by_dev(&tgt_devt
, OTYP_BLK
, flag
, credp
,
538 &xsp
->xdfss_tgt_lh
[part
], li
);
541 mutex_exit(&xsp
->xdfss_mutex
);
542 ldi_ident_release(li
);
546 /* Disk devices really shouldn't clone */
547 ASSERT(tgt_devt
== (xsp
->xdfss_tgt_dev
| part
));
551 ASSERT(xdfs_isopen_part(xsp
, part
));
553 /* do ldi open/close to get flags and cred check */
554 err
= ldi_open_by_dev(&tgt_devt
, OTYP_BLK
, flag
, credp
,
557 mutex_exit(&xsp
->xdfss_mutex
);
558 ldi_ident_release(li
);
562 /* Disk devices really shouldn't clone */
563 ASSERT(tgt_devt
== (xsp
->xdfss_tgt_dev
| part
));
564 (void) ldi_close(lh_tmp
, flag
, credp
);
566 ldi_ident_release(li
);
568 xsp
->xdfss_otyp_count
[otyp
][part
]++;
570 mutex_exit(&xsp
->xdfss_mutex
);
576 xdfs_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
578 int instance
= XDFS_DEV2UNIT(dev
);
579 int part
= XDFS_DEV2PART(dev
);
580 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
583 ASSERT((otyp
>= 0) && otyp
< OTYPCNT
);
585 /* Sanity check the dev_t associated with this request. */
586 ASSERT(getmajor(dev
) == xdfs_major
);
587 if (getmajor(dev
) != xdfs_major
)
590 if (XDFS_HVM_MODE(xsp
)) {
591 if ((xdfs_hvm_dev_ops
== NULL
) || (xdfs_hvm_cb_ops
== NULL
))
593 return (xdfs_hvm_cb_ops
->cb_close(dev
, flag
, otyp
, credp
));
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.
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
);
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
]--;
612 xsp
->xdfss_otyp_count
[otyp
][part
] = 0;
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
;
620 mutex_exit(&xsp
->xdfss_mutex
);
626 xdfs_strategy(struct buf
*bp
)
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
);
633 struct buf
*bp_clone
;
635 /* Sanity check the dev_t associated with this request. */
636 ASSERT(getmajor(dev
) == xdfs_major
);
637 if (getmajor(dev
) != xdfs_major
)
640 if (XDFS_HVM_MODE(xsp
)) {
641 if ((xdfs_hvm_dev_ops
== NULL
) || (xdfs_hvm_cb_ops
== NULL
))
643 return (xdfs_hvm_cb_ops
->cb_strategy(bp
));
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.
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
);
657 mutex_exit(&xsp
->xdfss_mutex
);
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
;
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.
671 if (bp
->b_private
== (void *)XB_SLICE_NONE
)
672 bp_clone
->b_private
= (void *)XB_SLICE_NONE
;
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
682 ASSERT(xsp
->xdfss_tgt_lh
[part
] != NULL
);
683 return (ldi_strategy(xsp
->xdfss_tgt_lh
[part
], bp_clone
));
687 bp
->b_resid
= bp
->b_bcount
;
693 xdfs_dump(dev_t dev
, caddr_t addr
, daddr_t blkno
, int nblk
)
695 int instance
= XDFS_DEV2UNIT(dev
);
696 int part
= XDFS_DEV2PART(dev
);
697 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
699 if (!XDFS_HVM_MODE(xsp
))
700 return (ldi_dump(xsp
->xdfss_tgt_lh
[part
], addr
, blkno
, nblk
));
702 if ((xdfs_hvm_dev_ops
== NULL
) || (xdfs_hvm_cb_ops
== NULL
))
704 return (xdfs_hvm_cb_ops
->cb_dump(dev
, addr
, blkno
, nblk
));
709 xdfs_read(dev_t dev
, struct uio
*uio
, cred_t
*credp
)
711 int instance
= XDFS_DEV2UNIT(dev
);
712 int part
= XDFS_DEV2PART(dev
);
713 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
715 if (!XDFS_HVM_MODE(xsp
))
716 return (ldi_read(xsp
->xdfss_tgt_lh
[part
], uio
, credp
));
718 if ((xdfs_hvm_dev_ops
== NULL
) || (xdfs_hvm_cb_ops
== NULL
))
720 return (xdfs_hvm_cb_ops
->cb_read(dev
, uio
, credp
));
725 xdfs_write(dev_t dev
, struct uio
*uio
, cred_t
*credp
)
727 int instance
= XDFS_DEV2UNIT(dev
);
728 int part
= XDFS_DEV2PART(dev
);
729 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
731 if (!XDFS_HVM_MODE(xsp
))
732 return (ldi_write(xsp
->xdfss_tgt_lh
[part
], uio
, credp
));
734 if ((xdfs_hvm_dev_ops
== NULL
) || (xdfs_hvm_cb_ops
== NULL
))
736 return (xdfs_hvm_cb_ops
->cb_write(dev
, uio
, credp
));
741 xdfs_aread(dev_t dev
, struct aio_req
*aio
, cred_t
*credp
)
743 int instance
= XDFS_DEV2UNIT(dev
);
744 int part
= XDFS_DEV2PART(dev
);
745 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
747 if (!XDFS_HVM_MODE(xsp
))
748 return (ldi_aread(xsp
->xdfss_tgt_lh
[part
], aio
, credp
));
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
))
755 return (xdfs_hvm_cb_ops
->cb_aread(dev
, aio
, credp
));
760 xdfs_awrite(dev_t dev
, struct aio_req
*aio
, cred_t
*credp
)
762 int instance
= XDFS_DEV2UNIT(dev
);
763 int part
= XDFS_DEV2PART(dev
);
764 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
766 if (!XDFS_HVM_MODE(xsp
))
767 return (ldi_awrite(xsp
->xdfss_tgt_lh
[part
], aio
, credp
));
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
))
774 return (xdfs_hvm_cb_ops
->cb_awrite(dev
, aio
, credp
));
778 xdfs_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int flag
, cred_t
*credp
,
781 int instance
= XDFS_DEV2UNIT(dev
);
782 int part
= XDFS_DEV2PART(dev
);
783 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
787 if (XDFS_HVM_MODE(xsp
)) {
788 if ((xdfs_hvm_dev_ops
== NULL
) || (xdfs_hvm_cb_ops
== NULL
))
790 return (xdfs_hvm_cb_ops
->cb_ioctl(
791 dev
, cmd
, arg
, flag
, credp
, rvalp
));
794 rv
= xdfs_c_ioctl(xsp
, dev
, part
, cmd
, arg
, flag
, credp
, rvalp
, &done
);
797 rv
= ldi_ioctl(xsp
->xdfss_tgt_lh
[part
], cmd
, arg
, flag
, credp
, rvalp
);
799 /* Force Geometry Validation */
800 (void) cmlb_invalidate(xsp
->xdfss_cmlbhandle
, 0);
801 (void) cmlb_validate(xsp
->xdfss_cmlbhandle
, 0, 0);
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
)
810 int instance
= ddi_get_instance(dip
);
811 void *xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
813 ASSERT(XDFS_HVM_MODE(xsp
));
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
);
821 return (xdfs_hvm_cb_ops
->cb_prop_op(dev
, dip
, prop_op
,
822 flags
, name
, valuep
, lengthp
));
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
)
829 int instance
= ddi_get_instance(dip
);
830 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
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.
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
);
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().
851 return (ddi_prop_op(dev
, dip
, prop_op
, flags
,
852 name
, valuep
, lengthp
));
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
));
860 * Make sure we only lookup static properties.
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.
877 flags
|= DDI_PROP_DYNAMIC
;
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.
888 if (!xdfs_tgt_hold(xsp
))
889 return (DDI_PROP_NOT_FOUND
);
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
;
896 tgt_devt
= xsp
->xdfss_tgt_dev
| XDFS_DEV2PART(dev
);
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.
906 rv
= cdev_prop_op(tgt_devt
, tgt_dip
,
907 prop_op
, flags
, name
, valuep
, lengthp
);
909 xdfs_tgt_release(xsp
);
914 * Driver PV and HVM dev_ops entry points
918 xdfs_getinfo(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
,
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
);
926 case DDI_INFO_DEVT2DEVINFO
:
928 return (DDI_FAILURE
);
929 if (XDFS_HVM_MODE(xsp
))
930 *result
= XDFS_HVM_DIP(xsp
);
932 *result
= (void *)xsp
->xdfss_dip
;
934 case DDI_INFO_DEVT2INSTANCE
:
935 *result
= (void *)(intptr_t)instance
;
938 return (DDI_FAILURE
);
940 return (DDI_SUCCESS
);
944 xdfs_hvm_probe(dev_info_t
*dip
, char *path
)
946 int instance
= ddi_get_instance(dip
);
947 int rv
= DDI_PROBE_SUCCESS
;
950 ASSERT(path
!= NULL
);
951 cmn_err(CE_WARN
, "PV access to device disabled: %s", path
);
953 (void) ddi_soft_state_zalloc(xdfs_ssp
, instance
);
954 VERIFY((xsp
= ddi_get_soft_state(xdfs_ssp
, instance
)) != NULL
);
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
);
965 XDFS_HVM_MODE(xsp
) = B_TRUE
;
966 XDFS_HVM_DIP(xsp
) = dip
;
967 XDFS_HVM_PATH(xsp
) = path
;
973 xdfs_probe(dev_info_t
*dip
)
975 int instance
= ddi_get_instance(dip
);
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
);
985 /* Figure out our pathname */
986 path
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
987 (void) ddi_pathname(dip
, path
);
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);
993 if (xdfs_pv_disable
|| pv_disable
)
994 return (xdfs_hvm_probe(dip
, path
));
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.
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)
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
)) {
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.
1014 return (xdfs_hvm_probe(dip
, path
));
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
);
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
);
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
));
1037 mutex_exit(&xsp
->xdfss_mutex
);
1040 * Add a zero-length attribute to tell the world we support
1041 * kernel ioctls (for layered drivers).
1043 (void) ddi_prop_create(DDI_DEV_T_NONE
, dip
, DDI_PROP_CANSLEEP
,
1044 DDI_KERNEL_IOCTL
, NULL
, 0);
1046 kmem_free(path
, MAXPATHLEN
);
1047 return (DDI_PROBE_SUCCESS
);
1051 xdfs_hvm_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
1053 int instance
= ddi_get_instance(dip
);
1054 void *xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
1055 int rv
= DDI_FAILURE
;
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
);
1069 return (DDI_SUCCESS
);
1073 * Autoconfiguration Routines
1076 xdfs_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
1078 int instance
= ddi_get_instance(dip
);
1079 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
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
);
1089 return (DDI_SUCCESS
);
1093 xdfs_hvm_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
1095 int instance
= ddi_get_instance(dip
);
1096 void *xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
1101 if ((xdfs_hvm_dev_ops
== NULL
) ||
1102 (xdfs_hvm_dev_ops
->devo_detach
== NULL
))
1103 return (DDI_FAILURE
);
1105 if ((rv
= xdfs_hvm_dev_ops
->devo_detach(dip
, cmd
)) != DDI_SUCCESS
)
1108 kmem_free(XDFS_HVM_PATH(xsp
), MAXPATHLEN
);
1109 ddi_soft_state_free(xdfs_ssp
, instance
);
1110 return (DDI_SUCCESS
);
1114 xdfs_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
1116 int instance
= ddi_get_instance(dip
);
1117 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
1119 if (XDFS_HVM_MODE(xsp
))
1120 return (xdfs_hvm_detach(dip
, cmd
));
1121 if (cmd
!= DDI_DETACH
)
1122 return (DDI_FAILURE
);
1124 mutex_enter(&xsp
->xdfss_mutex
);
1125 if (!xdfs_tgt_detach(xsp
)) {
1126 mutex_exit(&xsp
->xdfss_mutex
);
1127 return (DDI_FAILURE
);
1129 mutex_exit(&xsp
->xdfss_mutex
);
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
);
1140 xdfs_hvm_power(dev_info_t
*dip
, int component
, int level
)
1142 int instance
= ddi_get_instance(dip
);
1143 void *xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
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
));
1154 xdfs_power(dev_info_t
*dip
, int component
, int level
)
1156 int instance
= ddi_get_instance(dip
);
1157 xdfs_state_t
*xsp
= ddi_get_soft_state(xdfs_ssp
, instance
);
1159 if (XDFS_HVM_MODE(xsp
))
1160 return (xdfs_hvm_power(dip
, component
, level
));
1167 static cmlb_tg_ops_t xdfs_lb_ops
= {
1168 TG_DK_OPS_VERSION_1
,
1174 * Device driver ops vector
1176 static struct cb_ops xdfs_cb_ops
= {
1177 xdfs_open
, /* open */
1178 xdfs_close
, /* close */
1179 xdfs_strategy
, /* strategy */
1181 xdfs_dump
, /* dump */
1182 xdfs_read
, /* read */
1183 xdfs_write
, /* write */
1184 xdfs_ioctl
, /* ioctl */
1188 nochpoll
, /* poll */
1189 xdfs_prop_op
, /* cb_prop_op */
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 */
1197 struct dev_ops xdfs_ops
= {
1198 DEVO_REV
, /* devo_rev, */
1200 xdfs_getinfo
, /* info */
1201 nulldev
, /* identify */
1202 xdfs_probe
, /* probe */
1203 xdfs_attach
, /* attach */
1204 xdfs_detach
, /* detach */
1206 &xdfs_cb_ops
, /* driver operations */
1207 NULL
, /* bus operations */
1208 xdfs_power
, /* power */
1209 ddi_quiesce_not_supported
, /* devo_quiesce */
1213 * Module linkage information for the kernel.
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. */
1221 static struct modlinkage modlinkage
= {
1222 MODREV_1
, (void *)&modldrv
, NULL
1230 xdfs_major
= ddi_name_to_major((char *)xdfs_c_name
);
1231 if (xdfs_major
== (major_t
)-1)
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).
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
);
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.
1252 if ((rval
= ddi_soft_state_init(&xdfs_ssp
,
1253 xdfs_ss_size
, XDFS_NODES
)) != 0)
1255 *xdfs_c_hvm_ss
= xdfs_ssp
;
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
);
1269 _info(struct modinfo
*modinfop
)
1271 if (modldrv
.drv_linkinfo
== NULL
)
1272 modldrv
.drv_linkinfo
= (char *)xdfs_c_linkinfo
;
1273 return (mod_info(&modlinkage
, modinfop
));
1280 if ((rval
= mod_remove(&modlinkage
)) != 0)
1282 ddi_soft_state_fini(&xdfs_ssp
);