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
xdfs_c_ioctl(xdfs_state_t * xsp,dev_t dev,int part,int cmd,intptr_t arg,int flag,cred_t * credp,int * rvalp,boolean_t * done)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
xdfs_c_devid_setup(xdfs_state_t * xsp)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
xdfs_c_getpgeom(dev_info_t * dip,cmlb_geom_t * pgeom)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
xdfs_c_bb_check(xdfs_state_t * xsp)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 *
xdfs_c_cmlb_node_type(xdfs_state_t * xsp)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
xdfs_c_cmlb_alter_behavior(xdfs_state_t * xsp)163 xdfs_c_cmlb_alter_behavior(xdfs_state_t *xsp)
164 {
165 return (0);
166 }
167
168 void
xdfs_c_attach(xdfs_state_t * xsp)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