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
28#include <sys/scsi/targets/sddef.h>
29
30/*
31 * We're emulating (and possibly layering on top of) sd devices, so xdf
32 * disk unit mappings must match up with sd disk unit mappings'.
33 */
34#if !defined(XDF_PSHIFT)
35#error "can't find definition for xdf unit mappings - XDF_PSHIFT"
36#endif /* XDF_PSHIFT */
37
38#if !defined(SDUNIT_SHIFT)
39#error "can't find definition for cmdk unit mappings - SDUNIT_SHIFT"
40#endif /* SDUNIT_SHIFT */
41
42#if ((XDF_PSHIFT - SDUNIT_SHIFT) != 0)
43#error "sd and xdf unit mappings don't match."
44#endif /* ((XDF_PSHIFT - SDUNIT_SHIFT) != 0) */
45
46extern const struct dev_ops	sd_ops;
47extern void			*sd_state;
48
49/*
50 * Globals required by xdf_shell.c
51 */
52const char		*xdfs_c_name = "sd";
53const char		*xdfs_c_linkinfo = "PV SCSI Disk Driver";
54void			**xdfs_c_hvm_ss = &sd_state;
55const size_t		xdfs_c_hvm_ss_size = sizeof (struct sd_lun);
56const struct dev_ops	*xdfs_c_hvm_dev_ops = &sd_ops;
57
58const xdfs_h2p_map_t xdfs_c_h2p_map[] = {
59	{ "/pci@0,0/pci-ide@1,1/ide@0/sd@0,0", "/xpvd/xdf@768" },
60	{ "/pci@0,0/pci-ide@1,1/ide@0/sd@1,0", "/xpvd/xdf@832" },
61	{ "/pci@0,0/pci-ide@1,1/ide@1/sd@0,0", "/xpvd/xdf@5632" },
62	{ "/pci@0,0/pci-ide@1,1/ide@1/sd@1,0", "/xpvd/xdf@5696" },
63	{ NULL, 0 }
64};
65
66/*ARGSUSED*/
67int
68xdfs_c_ioctl(xdfs_state_t *xsp, dev_t dev, int part,
69    int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp, boolean_t *done)
70{
71	dev_info_t	*dip = xsp->xdfss_dip;
72	int		instance = ddi_get_instance(dip);
73	int		rv;
74
75	*done = B_TRUE;
76	switch (cmd) {
77	case DKIOCINFO: {
78		struct dk_cinfo	info;
79
80		/* Pass on the ioctl request, save the response */
81		if ((rv = ldi_ioctl(xsp->xdfss_tgt_lh[part],
82		    cmd, (intptr_t)&info, FKIOCTL, credp, rvalp)) != 0)
83			return (rv);
84
85		/* Update controller info */
86		info.dki_cnum = ddi_get_instance(ddi_get_parent(dip));
87		(void) strlcpy(info.dki_cname,
88		    ddi_get_name(ddi_get_parent(dip)), sizeof (info.dki_cname));
89
90		/* Update unit info. */
91		if (info.dki_ctype == DKC_VBD) {
92			/*
93			 * Normally a real scsi device would report the
94			 * controller type as DKC_SCSI_CCS.  But we don't
95			 * emulate a real scsi controller.  (Which becomes
96			 * apparent if anyone tries to issue us a uscsi(7i)
97			 * command.) So instead of reporting DKC_SCSI_CCS,
98			 * we report DKC_UNKNOWN.
99			 */
100			info.dki_ctype = DKC_UNKNOWN;
101		}
102		info.dki_unit = instance;
103		(void) strlcpy(info.dki_dname,
104		    ddi_driver_name(dip), sizeof (info.dki_dname));
105		info.dki_addr = 1;
106
107		if (ddi_copyout(&info, (void *)arg, sizeof (info), flag))
108			return (EFAULT);
109
110		return (0);
111	}
112	default:
113		*done = B_FALSE;
114		return (0);
115	} /* switch (cmd) */
116	/*NOTREACHED*/
117}
118
119/*ARGSUSED*/
120void
121xdfs_c_devid_setup(xdfs_state_t *xsp)
122{
123	/*
124	 * Currently we only support cdrom devices, which don't have
125	 * devids associated with them.
126	 */
127	ASSERT("cdrom devices don't have a devid");
128}
129
130/*ARGSUSED*/
131int
132xdfs_c_getpgeom(dev_info_t *dip, cmlb_geom_t *pgeom)
133{
134	/*
135	 * Currently we only support cdrom devices, which don't have
136	 * a physical geometry, so this routine should never get
137	 * invoked.
138	 */
139	ASSERT("cdrom devices don't have any physical geometry");
140	return (-1);
141}
142
143/*ARGSUSED*/
144boolean_t
145xdfs_c_bb_check(xdfs_state_t *xsp)
146{
147	/*
148	 * Currently we only support cdrom devices, which don't have
149	 * bad blocks, so this routine should never get invoked.
150	 */
151	ASSERT("cdrom devices don't support bad block mappings");
152	return (B_TRUE);
153}
154
155char *
156xdfs_c_cmlb_node_type(xdfs_state_t *xsp)
157{
158	return (xsp->xdfss_tgt_is_cd ? DDI_NT_CD_CHAN : DDI_NT_BLOCK_CHAN);
159}
160
161/*ARGSUSED*/
162int
163xdfs_c_cmlb_alter_behavior(xdfs_state_t *xsp)
164{
165	return (0);
166}
167
168void
169xdfs_c_attach(xdfs_state_t *xsp)
170{
171	dev_info_t	*dip = xsp->xdfss_dip;
172	int		dtype = DTYPE_DIRECT;
173
174	if (xsp->xdfss_tgt_is_cd) {
175		dtype = DTYPE_RODIRECT;
176		(void) ddi_prop_create(DDI_DEV_T_NONE, dip,
177		    DDI_PROP_CANSLEEP, "removable-media", NULL, 0);
178	}
179
180	/*
181	 * We use ndi_* instead of ddi_* because it will result in
182	 * INQUIRY_DEVICE_TYPE being a hardware property instead
183	 * or a driver property
184	 */
185	(void) ndi_prop_update_int(DDI_DEV_T_NONE, dip,
186	    INQUIRY_DEVICE_TYPE, dtype);
187}
188