]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cam/cam_compat.c
Merge llvm-project main llvmorg-18-init-16003-gfc5f51cf5af4
[FreeBSD/FreeBSD.git] / sys / cam / cam_compat.c
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
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
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
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
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
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 }