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