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
155typedef 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 */
162static int xdfs_iodone(struct buf *);
163static boolean_t xdfs_isopen_part(xdfs_state_t *, int);
164static boolean_t xdfs_isopen(xdfs_state_t *);
165static cmlb_tg_ops_t xdfs_lb_ops;
166
167/*
168 * Globals
169 */
170major_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 */
177volatile boolean_t	xdfs_pv_disable = B_FALSE;
178static void		*xdfs_ssp;
179static size_t		xdfs_ss_size;
180
181/*
182 * Private helper functions
183 */
184static boolean_t
185xdfs_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
198static void
199xdfs_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*/
210static int
211xdfs_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
265out:
266	xdfs_tgt_release(xsp);
267	return (rv);
268}
269
270static boolean_t
271xdfs_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
286static boolean_t
287xdfs_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
299static int
300xdfs_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
313static int
314xdfs_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
325static boolean_t
326xdfs_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
436static boolean_t
437xdfs_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 */
458void
459xdfs_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 */
468int
469xdfs_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*/
493static int
494xdfs_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*/
575static int
576xdfs_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
625int
626xdfs_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
685err:
686	bioerror(bp, ENXIO);
687	bp->b_resid = bp->b_bcount;
688	biodone(bp);
689	return (0);
690}
691
692static int
693xdfs_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*/
708static int
709xdfs_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*/
724static int
725xdfs_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*/
740static int
741xdfs_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*/
759static int
760xdfs_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
777static int
778xdfs_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
806static int
807xdfs_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
825static int
826xdfs_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*/
917static int
918xdfs_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
943static int
944xdfs_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
972static int
973xdfs_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
1050static int
1051xdfs_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 */
1075static int
1076xdfs_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
1092static int
1093xdfs_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
1113static int
1114xdfs_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
1139static int
1140xdfs_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
1153static int
1154xdfs_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 */
1167static 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 */
1176static 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
1197struct 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 */
1215static 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
1221static struct modlinkage modlinkage = {
1222	MODREV_1, (void *)&modldrv, NULL
1223};
1224
1225int
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
1268int
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
1276int
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}
1285