]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cam/cam_compat.c
login(1): when exporting variables check the result of setenv(3)
[FreeBSD/FreeBSD.git] / 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$");
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 }