FreeBSD/Linux Kernel Cross Reference
sys/cam/cam_compat.c
1 /*-
2 * CAM ioctl compatibility shims
3 *
4 * Copyright (c) 2013 Scott Long
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification, immediately at the beginning of the file.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD: releng/11.2/sys/cam/cam_compat.c 307264 2016-10-14 06:56:06Z mav $");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/types.h>
36 #include <sys/kernel.h>
37 #include <sys/conf.h>
38 #include <sys/fcntl.h>
39
40 #include <sys/lock.h>
41 #include <sys/mutex.h>
42 #include <sys/sysctl.h>
43 #include <sys/kthread.h>
44
45 #include <cam/cam.h>
46 #include <cam/cam_ccb.h>
47 #include <cam/cam_xpt.h>
48 #include <cam/cam_compat.h>
49 #include <cam/cam_periph.h>
50
51 #include <cam/scsi/scsi_pass.h>
52
53 #include "opt_cam.h"
54
55 static int cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr,
56 int flag, struct thread *td, d_ioctl_t *cbfnp);
57 static int cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr,
58 int flag, struct thread *td, d_ioctl_t *cbfnp);
59 static int cam_compat_translate_dev_match_0x18(union ccb *ccb);
60
61 int
62 cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
63 struct thread *td, d_ioctl_t *cbfnp)
64 {
65 int error;
66
67 switch (cmd) {
68 case CAMIOCOMMAND_0x16:
69 {
70 struct ccb_hdr_0x17 *hdr17;
71
72 hdr17 = (struct ccb_hdr_0x17 *)addr;
73 if (hdr17->flags & CAM_SG_LIST_PHYS_0x16) {
74 hdr17->flags &= ~CAM_SG_LIST_PHYS_0x16;
75 hdr17->flags |= CAM_DATA_SG_PADDR;
76 }
77 if (hdr17->flags & CAM_DATA_PHYS_0x16) {
78 hdr17->flags &= ~CAM_DATA_PHYS_0x16;
79 hdr17->flags |= CAM_DATA_PADDR;
80 }
81 if (hdr17->flags & CAM_SCATTER_VALID_0x16) {
82 hdr17->flags &= CAM_SCATTER_VALID_0x16;
83 hdr17->flags |= CAM_DATA_SG;
84 }
85 cmd = CAMIOCOMMAND;
86 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
87 break;
88 }
89 case CAMGETPASSTHRU_0x16:
90 cmd = CAMGETPASSTHRU;
91 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
92 break;
93 case CAMIOCOMMAND_0x17:
94 cmd = CAMIOCOMMAND;
95 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
96 break;
97 case CAMGETPASSTHRU_0x17:
98 cmd = CAMGETPASSTHRU;
99 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
100 break;
101 case CAMIOCOMMAND_0x18:
102 cmd = CAMIOCOMMAND;
103 error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp);
104 break;
105 case CAMGETPASSTHRU_0x18:
106 cmd = CAMGETPASSTHRU;
107 error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp);
108 break;
109 default:
110 error = ENOTTY;
111 }
112
113 return (error);
114 }
115
116 static int
117 cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
118 struct thread *td, d_ioctl_t *cbfnp)
119 {
120 union ccb *ccb;
121 struct ccb_hdr *hdr;
122 struct ccb_hdr_0x17 *hdr17;
123 uint8_t *ccbb, *ccbb17;
124 u_int error;
125
126 hdr17 = (struct ccb_hdr_0x17 *)addr;
127 ccb = xpt_alloc_ccb();
128 hdr = &ccb->ccb_h;
129
130 hdr->pinfo = hdr17->pinfo;
131 hdr->xpt_links = hdr17->xpt_links;
132 hdr->sim_links = hdr17->sim_links;
133 hdr->periph_links = hdr17->periph_links;
134 hdr->retry_count = hdr17->retry_count;
135 hdr->cbfcnp = hdr17->cbfcnp;
136 hdr->func_code = hdr17->func_code;
137 hdr->status = hdr17->status;
138 hdr->path = hdr17->path;
139 hdr->path_id = hdr17->path_id;
140 hdr->target_id = hdr17->target_id;
141 hdr->target_lun = hdr17->target_lun;
142 hdr->flags = hdr17->flags;
143 hdr->xflags = 0;
144 hdr->periph_priv = hdr17->periph_priv;
145 hdr->sim_priv = hdr17->sim_priv;
146 hdr->timeout = hdr17->timeout;
147 hdr->softtimeout.tv_sec = 0;
148 hdr->softtimeout.tv_usec = 0;
149
150 ccbb = (uint8_t *)&hdr[1];
151 ccbb17 = (uint8_t *)&hdr17[1];
152 if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) {
153 struct ccb_trans_settings *cts;
154 struct ccb_trans_settings_0x17 *cts17;
155
156 cts = &ccb->cts;
157 cts17 = (struct ccb_trans_settings_0x17 *)hdr17;
158 cts->type = cts17->type;
159 cts->protocol = cts17->protocol;
160 cts->protocol_version = cts17->protocol_version;
161 cts->transport = cts17->transport;
162 cts->transport_version = cts17->transport_version;
163 bcopy(&cts17->proto_specific, &cts->proto_specific,
164 sizeof(cts17->proto_specific));
165 bcopy(&cts17->xport_specific, &cts->xport_specific,
166 sizeof(cts17->xport_specific));
167 } else {
168 bcopy(ccbb17, ccbb, CAM_0X17_DATA_LEN);
169 }
170
171 error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td);
172
173 hdr17->pinfo = hdr->pinfo;
174 hdr17->xpt_links = hdr->xpt_links;
175 hdr17->sim_links = hdr->sim_links;
176 hdr17->periph_links = hdr->periph_links;
177 hdr17->retry_count = hdr->retry_count;
178 hdr17->cbfcnp = hdr->cbfcnp;
179 hdr17->func_code = hdr->func_code;
180 hdr17->status = hdr->status;
181 hdr17->path = hdr->path;
182 hdr17->path_id = hdr->path_id;
183 hdr17->target_id = hdr->target_id;
184 hdr17->target_lun = hdr->target_lun;
185 hdr17->flags = hdr->flags;
186 hdr17->periph_priv = hdr->periph_priv;
187 hdr17->sim_priv = hdr->sim_priv;
188 hdr17->timeout = hdr->timeout;
189
190 if (ccb->ccb_h.func_code == XPT_PATH_INQ) {
191 struct ccb_pathinq *cpi;
192 struct ccb_pathinq_0x17 *cpi17;
193
194 /* The PATH_INQ only needs special handling on the way out */
195 cpi = &ccb->cpi;
196 cpi17 = (struct ccb_pathinq_0x17 *)hdr17;
197 cpi17->version_num = cpi->version_num;
198 cpi17->hba_inquiry = cpi->hba_inquiry;
199 cpi17->target_sprt = (u_int8_t)cpi->target_sprt;
200 cpi17->hba_misc = (u_int8_t)cpi->hba_misc;
201 cpi17->hba_eng_cnt = cpi->hba_eng_cnt;
202 bcopy(&cpi->vuhba_flags[0], &cpi17->vuhba_flags[0], VUHBALEN);
203 cpi17->max_target = cpi->max_target;
204 cpi17->max_lun = cpi->max_lun;
205 cpi17->async_flags = cpi->async_flags;
206 cpi17->hpath_id = cpi->hpath_id;
207 cpi17->initiator_id = cpi->initiator_id;
208 bcopy(&cpi->sim_vid[0], &cpi17->sim_vid[0], SIM_IDLEN);
209 bcopy(&cpi->hba_vid[0], &cpi17->hba_vid[0], HBA_IDLEN);
210 bcopy(&cpi->dev_name[0], &cpi17->dev_name[0], DEV_IDLEN);
211 cpi17->unit_number = cpi->unit_number;
212 cpi17->bus_id = cpi->bus_id;
213 cpi17->base_transfer_speed = cpi->base_transfer_speed;
214 cpi17->protocol = cpi->protocol;
215 cpi17->protocol_version = cpi->protocol_version;
216 cpi17->transport = cpi->transport;
217 cpi17->transport_version = cpi->transport_version;
218 bcopy(&cpi->xport_specific, &cpi17->xport_specific,
219 PATHINQ_SETTINGS_SIZE);
220 cpi17->maxio = cpi->maxio;
221 cpi17->hba_vendor = cpi->hba_vendor;
222 cpi17->hba_device = cpi->hba_device;
223 cpi17->hba_subvendor = cpi->hba_subvendor;
224 cpi17->hba_subdevice = cpi->hba_subdevice;
225 } else if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) {
226 struct ccb_trans_settings *cts;
227 struct ccb_trans_settings_0x17 *cts17;
228
229 cts = &ccb->cts;
230 cts17 = (struct ccb_trans_settings_0x17 *)hdr17;
231 cts17->type = cts->type;
232 cts17->protocol = cts->protocol;
233 cts17->protocol_version = cts->protocol_version;
234 cts17->transport = cts->transport;
235 cts17->transport_version = cts->transport_version;
236 bcopy(&cts->proto_specific, &cts17->proto_specific,
237 sizeof(cts17->proto_specific));
238 bcopy(&cts->xport_specific, &cts17->xport_specific,
239 sizeof(cts17->xport_specific));
240 } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
241 /* Copy the rest of the header over */
242 bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
243
244 cam_compat_translate_dev_match_0x18(ccb);
245 } else {
246 bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
247 }
248
249 xpt_free_ccb(ccb);
250
251 return (error);
252 }
253
254 static int
255 cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
256 struct thread *td, d_ioctl_t *cbfnp)
257 {
258 union ccb *ccb;
259 struct ccb_hdr *hdr;
260 struct ccb_hdr_0x18 *hdr18;
261 uint8_t *ccbb, *ccbb18;
262 u_int error;
263
264 hdr18 = (struct ccb_hdr_0x18 *)addr;
265 ccb = xpt_alloc_ccb();
266 hdr = &ccb->ccb_h;
267
268 hdr->pinfo = hdr18->pinfo;
269 hdr->xpt_links = hdr18->xpt_links;
270 hdr->sim_links = hdr18->sim_links;
271 hdr->periph_links = hdr18->periph_links;
272 hdr->retry_count = hdr18->retry_count;
273 hdr->cbfcnp = hdr18->cbfcnp;
274 hdr->func_code = hdr18->func_code;
275 hdr->status = hdr18->status;
276 hdr->path = hdr18->path;
277 hdr->path_id = hdr18->path_id;
278 hdr->target_id = hdr18->target_id;
279 hdr->target_lun = hdr18->target_lun;
280 if (hdr18->xflags & CAM_EXTLUN_VALID_0x18)
281 hdr->target_lun = hdr18->ext_lun;
282 hdr->flags = hdr18->flags;
283 hdr->xflags = hdr18->xflags;
284 hdr->periph_priv = hdr18->periph_priv;
285 hdr->sim_priv = hdr18->sim_priv;
286 hdr->timeout = hdr18->timeout;
287 hdr->softtimeout.tv_sec = 0;
288 hdr->softtimeout.tv_usec = 0;
289
290 ccbb = (uint8_t *)&hdr[1];
291 ccbb18 = (uint8_t *)&hdr18[1];
292 if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) {
293 struct ccb_trans_settings *cts;
294 struct ccb_trans_settings_0x18 *cts18;
295
296 cts = &ccb->cts;
297 cts18 = (struct ccb_trans_settings_0x18 *)hdr18;
298 cts->type = cts18->type;
299 cts->protocol = cts18->protocol;
300 cts->protocol_version = cts18->protocol_version;
301 cts->transport = cts18->transport;
302 cts->transport_version = cts18->transport_version;
303 bcopy(&cts18->proto_specific, &cts->proto_specific,
304 sizeof(cts18->proto_specific));
305 bcopy(&cts18->xport_specific, &cts->xport_specific,
306 sizeof(cts18->xport_specific));
307 } else {
308 bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN);
309 }
310
311 error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td);
312
313 hdr18->pinfo = hdr->pinfo;
314 hdr18->xpt_links = hdr->xpt_links;
315 hdr18->sim_links = hdr->sim_links;
316 hdr18->periph_links = hdr->periph_links;
317 hdr18->retry_count = hdr->retry_count;
318 hdr18->cbfcnp = hdr->cbfcnp;
319 hdr18->func_code = hdr->func_code;
320 hdr18->status = hdr->status;
321 hdr18->path = hdr->path;
322 hdr18->path_id = hdr->path_id;
323 hdr18->target_id = hdr->target_id;
324 hdr18->target_lun = hdr->target_lun;
325 hdr18->ext_lun = hdr->target_lun;
326 hdr18->flags = hdr->flags;
327 hdr18->xflags = hdr->xflags | CAM_EXTLUN_VALID_0x18;
328 hdr18->periph_priv = hdr->periph_priv;
329 hdr18->sim_priv = hdr->sim_priv;
330 hdr18->timeout = hdr->timeout;
331
332 if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) {
333 struct ccb_trans_settings *cts;
334 struct ccb_trans_settings_0x18 *cts18;
335
336 cts = &ccb->cts;
337 cts18 = (struct ccb_trans_settings_0x18 *)hdr18;
338 cts18->type = cts->type;
339 cts18->protocol = cts->protocol;
340 cts18->protocol_version = cts->protocol_version;
341 cts18->transport = cts->transport;
342 cts18->transport_version = cts->transport_version;
343 bcopy(&cts->proto_specific, &cts18->proto_specific,
344 sizeof(cts18->proto_specific));
345 bcopy(&cts->xport_specific, &cts18->xport_specific,
346 sizeof(cts18->xport_specific));
347 } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
348 bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
349 cam_compat_translate_dev_match_0x18(ccb);
350 } else {
351 bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
352 }
353
354 xpt_free_ccb(ccb);
355
356 return (error);
357 }
358
359 static int
360 cam_compat_translate_dev_match_0x18(union ccb *ccb)
361 {
362 struct dev_match_result *dm;
363 struct dev_match_result_0x18 *dm18;
364 struct cam_periph_map_info mapinfo;
365 int i;
366
367 /* Remap the CCB into kernel address space */
368 bzero(&mapinfo, sizeof(mapinfo));
369 cam_periph_mapmem(ccb, &mapinfo, MAXPHYS);
370
371 dm = ccb->cdm.matches;
372 /* Translate in-place: old fields are smaller */
373 dm18 = (struct dev_match_result_0x18 *)(dm);
374
375 for (i = 0; i < ccb->cdm.num_matches; i++) {
376 dm18[i].type = dm[i].type;
377 switch (dm[i].type) {
378 case DEV_MATCH_PERIPH:
379 memcpy(&dm18[i].result.periph_result.periph_name,
380 &dm[i].result.periph_result.periph_name,
381 DEV_IDLEN);
382 dm18[i].result.periph_result.unit_number =
383 dm[i].result.periph_result.unit_number;
384 dm18[i].result.periph_result.path_id =
385 dm[i].result.periph_result.path_id;
386 dm18[i].result.periph_result.target_id =
387 dm[i].result.periph_result.target_id;
388 dm18[i].result.periph_result.target_lun =
389 dm[i].result.periph_result.target_lun;
390 break;
391 case DEV_MATCH_DEVICE:
392 dm18[i].result.device_result.path_id =
393 dm[i].result.device_result.path_id;
394 dm18[i].result.device_result.target_id =
395 dm[i].result.device_result.target_id;
396 dm18[i].result.device_result.target_lun =
397 dm[i].result.device_result.target_lun;
398 dm18[i].result.device_result.protocol =
399 dm[i].result.device_result.protocol;
400 memcpy(&dm18[i].result.device_result.inq_data,
401 &dm[i].result.device_result.inq_data,
402 sizeof(struct scsi_inquiry_data));
403 memcpy(&dm18[i].result.device_result.ident_data,
404 &dm[i].result.device_result.ident_data,
405 sizeof(struct ata_params));
406 dm18[i].result.device_result.flags =
407 dm[i].result.device_result.flags;
408 break;
409 case DEV_MATCH_BUS:
410 memcpy(&dm18[i].result.bus_result,
411 &dm[i].result.bus_result,
412 sizeof(struct bus_match_result));
413 break;
414 }
415 }
416
417 cam_periph_unmapmem(ccb, &mapinfo);
418
419 return (0);
420 }
421
Cache object: a716dc4c4eae63932f872cf22735eeb9
|