xref: /titanic_41/usr/src/uts/i86pc/i86hvm/io/pv_sd.c (revision fc0105de770cee6a3fd91de949b9927fba6e894b)
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 
46 extern const struct dev_ops	sd_ops;
47 extern void			*sd_state;
48 
49 /*
50  * Globals required by xdf_shell.c
51  */
52 const char		*xdfs_c_name = "sd";
53 const char		*xdfs_c_linkinfo = "PV SCSI Disk Driver";
54 void			**xdfs_c_hvm_ss = &sd_state;
55 const size_t		xdfs_c_hvm_ss_size = sizeof (struct sd_lun);
56 const struct dev_ops	*xdfs_c_hvm_dev_ops = &sd_ops;
57 
58 const 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*/
67 int
68 xdfs_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*/
120 void
121 xdfs_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*/
131 int
132 xdfs_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*/
144 boolean_t
145 xdfs_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 
155 char *
156 xdfs_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*/
162 int
163 xdfs_c_cmlb_alter_behavior(xdfs_state_t *xsp)
164 {
165 	return (0);
166 }
167 
168 void
169 xdfs_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