1 /*-
2 * CAM ioctl compatibility shims
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
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/param.h>
33 #include <sys/systm.h>
34 #include <sys/types.h>
35 #include <sys/kernel.h>
36 #include <sys/conf.h>
37 #include <sys/fcntl.h>
38
39 #include <sys/lock.h>
40 #include <sys/mutex.h>
41 #include <sys/sysctl.h>
42 #include <sys/kthread.h>
43
44 #include <cam/cam.h>
45 #include <cam/cam_ccb.h>
46 #include <cam/cam_xpt.h>
47 #include <cam/cam_compat.h>
48 #include <cam/cam_periph.h>
49
50 #include <cam/scsi/scsi_pass.h>
51
52 static int cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr,
53 int flag, struct thread *td, d_ioctl_t *cbfnp);
54 static int cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr,
55 int flag, struct thread *td, d_ioctl_t *cbfnp);
56 static int cam_compat_handle_0x19(struct cdev *dev, u_long cmd, caddr_t addr,
57 int flag, struct thread *td, d_ioctl_t *cbfnp);
58 static int cam_compat_translate_dev_match_0x18(union ccb *ccb);
59
60 int
cam_compat_ioctl(struct cdev * dev,u_long cmd,caddr_t addr,int flag,struct thread * td,d_ioctl_t * cbfnp)61 cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
62 struct thread *td, d_ioctl_t *cbfnp)
63 {
64 int error;
65
66 switch (cmd) {
67 case CAMIOCOMMAND_0x16:
68 {
69 struct ccb_hdr_0x17 *hdr17;
70
71 hdr17 = (struct ccb_hdr_0x17 *)addr;
72 if (hdr17->flags & CAM_SG_LIST_PHYS_0x16) {
73 hdr17->flags &= ~CAM_SG_LIST_PHYS_0x16;
74 hdr17->flags |= CAM_DATA_SG_PADDR;
75 }
76 if (hdr17->flags & CAM_DATA_PHYS_0x16) {
77 hdr17->flags &= ~CAM_DATA_PHYS_0x16;
78 hdr17->flags |= CAM_DATA_PADDR;
79 }
80 if (hdr17->flags & CAM_SCATTER_VALID_0x16) {
81 hdr17->flags &= CAM_SCATTER_VALID_0x16;
82 hdr17->flags |= CAM_DATA_SG;
83 }
84 cmd = CAMIOCOMMAND;
85 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
86 break;
87 }
88 case CAMGETPASSTHRU_0x16:
89 cmd = CAMGETPASSTHRU;
90 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
91 break;
92 case CAMIOCOMMAND_0x17:
93 cmd = CAMIOCOMMAND;
94 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
95 break;
96 case CAMGETPASSTHRU_0x17:
97 cmd = CAMGETPASSTHRU;
98 error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
99 break;
100 case CAMIOCOMMAND_0x18:
101 cmd = CAMIOCOMMAND;
102 error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp);
103 break;
104 case CAMGETPASSTHRU_0x18:
105 cmd = CAMGETPASSTHRU;
106 error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp);
107 break;
108 case CAMIOCOMMAND_0x19:
109 cmd = CAMIOCOMMAND;
110 error = cam_compat_handle_0x19(dev, cmd, addr, flag, td, cbfnp);
111 break;
112 case CAMGETPASSTHRU_0x19:
113 cmd = CAMGETPASSTHRU;
114 error = cam_compat_handle_0x19(dev, cmd, addr, flag, td, cbfnp);
115 break;
116 case CAMIOQUEUE_0x19:
117 cmd = CAMIOQUEUE;
118 error = cam_compat_handle_0x19(dev, cmd, addr, flag, td, cbfnp);
119 break;
120 case CAMIOGET_0x19:
121 cmd = CAMIOGET;
122 error = cam_compat_handle_0x19(dev, cmd, addr, flag, td, cbfnp);
123 break;
124 default:
125 error = ENOTTY;
126 }
127
128 return (error);
129 }
130
131 static int
cam_compat_handle_0x17(struct cdev * dev,u_long cmd,caddr_t addr,int flag,struct thread * td,d_ioctl_t * cbfnp)132 cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
133 struct thread *td, d_ioctl_t *cbfnp)
134 {
135 union ccb *ccb;
136 struct ccb_hdr *hdr;
137 struct ccb_hdr_0x17 *hdr17;
138 uint8_t *ccbb, *ccbb17;
139 u_int error;
140
141 hdr17 = (struct ccb_hdr_0x17 *)addr;
142 ccb = xpt_alloc_ccb();
143 hdr = &ccb->ccb_h;
144
145 hdr->pinfo = hdr17->pinfo;
146 hdr->xpt_links = hdr17->xpt_links;
147 hdr->sim_links = hdr17->sim_links;
148 hdr->periph_links = hdr17->periph_links;
149 hdr->retry_count = hdr17->retry_count;
150 hdr->cbfcnp = hdr17->cbfcnp;
151 hdr->func_code = hdr17->func_code;
152 hdr->status = hdr17->status;
153 hdr->path = hdr17->path;
154 hdr->path_id = hdr17->path_id;
155 hdr->target_id = hdr17->target_id;
156 hdr->target_lun = hdr17->target_lun;
157 hdr->flags = hdr17->flags;
158 hdr->xflags = 0;
159 hdr->periph_priv = hdr17->periph_priv;
160 hdr->sim_priv = hdr17->sim_priv;
161 hdr->timeout = hdr17->timeout;
162 hdr->softtimeout.tv_sec = 0;
163 hdr->softtimeout.tv_usec = 0;
164
165 ccbb = (uint8_t *)&hdr[1];
166 ccbb17 = (uint8_t *)&hdr17[1];
167 if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) {
168 struct ccb_trans_settings *cts;
169 struct ccb_trans_settings_0x17 *cts17;
170
171 cts = &ccb->cts;
172 cts17 = (struct ccb_trans_settings_0x17 *)hdr17;
173 cts->type = cts17->type;
174 cts->protocol = cts17->protocol;
175 cts->protocol_version = cts17->protocol_version;
176 cts->transport = cts17->transport;
177 cts->transport_version = cts17->transport_version;
178 bcopy(&cts17->proto_specific, &cts->proto_specific,
179 sizeof(cts17->proto_specific));
180 bcopy(&cts17->xport_specific, &cts->xport_specific,
181 sizeof(cts17->xport_specific));
182 } else {
183 bcopy(ccbb17, ccbb, CAM_0X17_DATA_LEN);
184 }
185
186 error = cam_compat_handle_0x19(dev, cmd, (caddr_t)ccb, flag, td, cbfnp);
187
188 hdr17->pinfo = hdr->pinfo;
189 hdr17->xpt_links = hdr->xpt_links;
190 hdr17->sim_links = hdr->sim_links;
191 hdr17->periph_links = hdr->periph_links;
192 hdr17->retry_count = hdr->retry_count;
193 hdr17->cbfcnp = hdr->cbfcnp;
194 hdr17->func_code = hdr->func_code;
195 hdr17->status = hdr->status;
196 hdr17->path = hdr->path;
197 hdr17->path_id = hdr->path_id;
198 hdr17->target_id = hdr->target_id;
199 hdr17->target_lun = hdr->target_lun;
200 hdr17->flags = hdr->flags;
201 hdr17->periph_priv = hdr->periph_priv;
202 hdr17->sim_priv = hdr->sim_priv;
203 hdr17->timeout = hdr->timeout;
204
205 if (ccb->ccb_h.func_code == XPT_PATH_INQ) {
206 struct ccb_pathinq *cpi;
207 struct ccb_pathinq_0x17 *cpi17;
208
209 /* The PATH_INQ only needs special handling on the way out */
210 cpi = &ccb->cpi;
211 cpi17 = (struct ccb_pathinq_0x17 *)hdr17;
212 cpi17->version_num = cpi->version_num;
213 cpi17->hba_inquiry = cpi->hba_inquiry;
214 cpi17->target_sprt = (uint8_t)cpi->target_sprt;
215 cpi17->hba_misc = (uint8_t)cpi->hba_misc;
216 cpi17->hba_eng_cnt = cpi->hba_eng_cnt;
217 bcopy(&cpi->vuhba_flags[0], &cpi17->vuhba_flags[0], VUHBALEN);
218 cpi17->max_target = cpi->max_target;
219 cpi17->max_lun = cpi->max_lun;
220 cpi17->async_flags = cpi->async_flags;
221 cpi17->hpath_id = cpi->hpath_id;
222 cpi17->initiator_id = cpi->initiator_id;
223 bcopy(&cpi->sim_vid[0], &cpi17->sim_vid[0], SIM_IDLEN);
224 bcopy(&cpi->hba_vid[0], &cpi17->hba_vid[0], HBA_IDLEN);
225 bcopy(&cpi->dev_name[0], &cpi17->dev_name[0], DEV_IDLEN);
226 cpi17->unit_number = cpi->unit_number;
227 cpi17->bus_id = cpi->bus_id;
228 cpi17->base_transfer_speed = cpi->base_transfer_speed;
229 cpi17->protocol = cpi->protocol;
230 cpi17->protocol_version = cpi->protocol_version;
231 cpi17->transport = cpi->transport;
232 cpi17->transport_version = cpi->transport_version;
233 bcopy(&cpi->xport_specific, &cpi17->xport_specific,
234 PATHINQ_SETTINGS_SIZE);
235 cpi17->maxio = cpi->maxio;
236 cpi17->hba_vendor = cpi->hba_vendor;
237 cpi17->hba_device = cpi->hba_device;
238 cpi17->hba_subvendor = cpi->hba_subvendor;
239 cpi17->hba_subdevice = cpi->hba_subdevice;
240 } else if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) {
241 struct ccb_trans_settings *cts;
242 struct ccb_trans_settings_0x17 *cts17;
243
244 cts = &ccb->cts;
245 cts17 = (struct ccb_trans_settings_0x17 *)hdr17;
246 cts17->type = cts->type;
247 cts17->protocol = cts->protocol;
248 cts17->protocol_version = cts->protocol_version;
249 cts17->transport = cts->transport;
250 cts17->transport_version = cts->transport_version;
251 bcopy(&cts->proto_specific, &cts17->proto_specific,
252 sizeof(cts17->proto_specific));
253 bcopy(&cts->xport_specific, &cts17->xport_specific,
254 sizeof(cts17->xport_specific));
255 } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
256 /* Copy the rest of the header over */
257 bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
258
259 cam_compat_translate_dev_match_0x18(ccb);
260 } else {
261 bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
262 }
263
264 xpt_free_ccb(ccb);
265
266 return (error);
267 }
268
269 static int
cam_compat_handle_0x18(struct cdev * dev,u_long cmd,caddr_t addr,int flag,struct thread * td,d_ioctl_t * cbfnp)270 cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
271 struct thread *td, d_ioctl_t *cbfnp)
272 {
273 union ccb *ccb;
274 struct ccb_hdr *hdr;
275 struct ccb_hdr_0x18 *hdr18;
276 uint8_t *ccbb, *ccbb18;
277 u_int error;
278
279 hdr18 = (struct ccb_hdr_0x18 *)addr;
280 ccb = xpt_alloc_ccb();
281 hdr = &ccb->ccb_h;
282
283 hdr->pinfo = hdr18->pinfo;
284 hdr->xpt_links = hdr18->xpt_links;
285 hdr->sim_links = hdr18->sim_links;
286 hdr->periph_links = hdr18->periph_links;
287 hdr->retry_count = hdr18->retry_count;
288 hdr->cbfcnp = hdr18->cbfcnp;
289 hdr->func_code = hdr18->func_code;
290 hdr->status = hdr18->status;
291 hdr->path = hdr18->path;
292 hdr->path_id = hdr18->path_id;
293 hdr->target_id = hdr18->target_id;
294 hdr->target_lun = hdr18->target_lun;
295 if (hdr18->xflags & CAM_EXTLUN_VALID_0x18)
296 hdr->target_lun = hdr18->ext_lun;
297 hdr->flags = hdr18->flags;
298 hdr->xflags = hdr18->xflags;
299 hdr->periph_priv = hdr18->periph_priv;
300 hdr->sim_priv = hdr18->sim_priv;
301 hdr->timeout = hdr18->timeout;
302 hdr->softtimeout.tv_sec = 0;
303 hdr->softtimeout.tv_usec = 0;
304
305 ccbb = (uint8_t *)&hdr[1];
306 ccbb18 = (uint8_t *)&hdr18[1];
307 if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) {
308 struct ccb_trans_settings *cts;
309 struct ccb_trans_settings_0x18 *cts18;
310
311 cts = &ccb->cts;
312 cts18 = (struct ccb_trans_settings_0x18 *)hdr18;
313 cts->type = cts18->type;
314 cts->protocol = cts18->protocol;
315 cts->protocol_version = cts18->protocol_version;
316 cts->transport = cts18->transport;
317 cts->transport_version = cts18->transport_version;
318 bcopy(&cts18->proto_specific, &cts->proto_specific,
319 sizeof(cts18->proto_specific));
320 bcopy(&cts18->xport_specific, &cts->xport_specific,
321 sizeof(cts18->xport_specific));
322 } else {
323 bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN);
324 }
325
326 error = cam_compat_handle_0x19(dev, cmd, (caddr_t)ccb, flag, td, cbfnp);
327
328 hdr18->pinfo = hdr->pinfo;
329 hdr18->xpt_links = hdr->xpt_links;
330 hdr18->sim_links = hdr->sim_links;
331 hdr18->periph_links = hdr->periph_links;
332 hdr18->retry_count = hdr->retry_count;
333 hdr18->cbfcnp = hdr->cbfcnp;
334 hdr18->func_code = hdr->func_code;
335 hdr18->status = hdr->status;
336 hdr18->path = hdr->path;
337 hdr18->path_id = hdr->path_id;
338 hdr18->target_id = hdr->target_id;
339 hdr18->target_lun = hdr->target_lun;
340 hdr18->ext_lun = hdr->target_lun;
341 hdr18->flags = hdr->flags;
342 hdr18->xflags = hdr->xflags | CAM_EXTLUN_VALID_0x18;
343 hdr18->periph_priv = hdr->periph_priv;
344 hdr18->sim_priv = hdr->sim_priv;
345 hdr18->timeout = hdr->timeout;
346
347 if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) {
348 struct ccb_trans_settings *cts;
349 struct ccb_trans_settings_0x18 *cts18;
350
351 cts = &ccb->cts;
352 cts18 = (struct ccb_trans_settings_0x18 *)hdr18;
353 cts18->type = cts->type;
354 cts18->protocol = cts->protocol;
355 cts18->protocol_version = cts->protocol_version;
356 cts18->transport = cts->transport;
357 cts18->transport_version = cts->transport_version;
358 bcopy(&cts->proto_specific, &cts18->proto_specific,
359 sizeof(cts18->proto_specific));
360 bcopy(&cts->xport_specific, &cts18->xport_specific,
361 sizeof(cts18->xport_specific));
362 } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
363 bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
364 cam_compat_translate_dev_match_0x18(ccb);
365 } else {
366 bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
367 }
368
369 xpt_free_ccb(ccb);
370
371 return (error);
372 }
373
374 static int
cam_compat_translate_dev_match_0x18(union ccb * ccb)375 cam_compat_translate_dev_match_0x18(union ccb *ccb)
376 {
377 struct dev_match_result *dm;
378 struct dev_match_result_0x18 *dm18;
379 struct cam_periph_map_info mapinfo;
380 int error, i;
381
382 /* Remap the CCB into kernel address space */
383 bzero(&mapinfo, sizeof(mapinfo));
384 error = cam_periph_mapmem(ccb, &mapinfo, maxphys);
385 if (error != 0)
386 return (error);
387
388 dm = ccb->cdm.matches;
389 /* Translate in-place: old fields are smaller */
390 dm18 = (struct dev_match_result_0x18 *)(dm);
391
392 for (i = 0; i < ccb->cdm.num_matches; i++) {
393 dm18[i].type = dm[i].type;
394 switch (dm[i].type) {
395 case DEV_MATCH_PERIPH:
396 memcpy(&dm18[i].result.periph_result.periph_name,
397 &dm[i].result.periph_result.periph_name,
398 DEV_IDLEN);
399 dm18[i].result.periph_result.unit_number =
400 dm[i].result.periph_result.unit_number;
401 dm18[i].result.periph_result.path_id =
402 dm[i].result.periph_result.path_id;
403 dm18[i].result.periph_result.target_id =
404 dm[i].result.periph_result.target_id;
405 dm18[i].result.periph_result.target_lun =
406 dm[i].result.periph_result.target_lun;
407 break;
408 case DEV_MATCH_DEVICE:
409 dm18[i].result.device_result.path_id =
410 dm[i].result.device_result.path_id;
411 dm18[i].result.device_result.target_id =
412 dm[i].result.device_result.target_id;
413 dm18[i].result.device_result.target_lun =
414 dm[i].result.device_result.target_lun;
415 dm18[i].result.device_result.protocol =
416 dm[i].result.device_result.protocol;
417 memcpy(&dm18[i].result.device_result.inq_data,
418 &dm[i].result.device_result.inq_data,
419 sizeof(struct scsi_inquiry_data));
420 memcpy(&dm18[i].result.device_result.ident_data,
421 &dm[i].result.device_result.ident_data,
422 sizeof(struct ata_params));
423 dm18[i].result.device_result.flags =
424 dm[i].result.device_result.flags;
425 break;
426 case DEV_MATCH_BUS:
427 memcpy(&dm18[i].result.bus_result,
428 &dm[i].result.bus_result,
429 sizeof(struct bus_match_result));
430 break;
431 }
432 }
433
434 return (cam_periph_unmapmem(ccb, &mapinfo));
435 }
436
437 static int
cam_compat_handle_0x19(struct cdev * dev,u_long cmd,caddr_t addr,int flag,struct thread * td,d_ioctl_t * cbfnp)438 cam_compat_handle_0x19(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
439 struct thread *td, d_ioctl_t *cbfnp)
440 {
441 struct cam_periph_map_info mapinfo;
442 union ccb *ccb = (union ccb *)addr;
443 int error;
444
445 if (cmd == CAMIOCOMMAND && ccb->ccb_h.func_code == XPT_DEV_MATCH) {
446 bzero(&mapinfo, sizeof(mapinfo));
447 error = cam_periph_mapmem(ccb, &mapinfo, maxphys);
448 if (error != 0)
449 return (error);
450 for (int i = 0; i < ccb->cdm.num_patterns; i++) {
451 struct dev_match_pattern *p = &ccb->cdm.patterns[i];
452
453 if (p->type == DEV_MATCH_BUS &&
454 p->pattern.bus_pattern.flags == 0x00f)
455 p->pattern.bus_pattern.flags = BUS_MATCH_ANY;
456 if (p->type == DEV_MATCH_DEVICE &&
457 p->pattern.device_pattern.flags == 0x00f)
458 p->pattern.device_pattern.flags = DEV_MATCH_ANY;
459 if (p->type == DEV_MATCH_PERIPH &&
460 p->pattern.periph_pattern.flags == 0x01f)
461 p->pattern.periph_pattern.flags = PERIPH_MATCH_ANY;
462 }
463 error = cam_periph_unmapmem(ccb, &mapinfo);
464 if (error != 0)
465 return (error);
466 }
467 return ((cbfnp)(dev, cmd, addr, flag, td));
468 }
469