]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cam/cam_compat.c
Merge OpenSSL 1.0.2h.
[FreeBSD/FreeBSD.git] / 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$");
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         bcopy(ccbb17, ccbb, CAM_0X17_DATA_LEN);
153
154         error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td);
155
156         hdr17->pinfo = hdr->pinfo;
157         hdr17->xpt_links = hdr->xpt_links;
158         hdr17->sim_links = hdr->sim_links;
159         hdr17->periph_links = hdr->periph_links;
160         hdr17->retry_count = hdr->retry_count;
161         hdr17->cbfcnp = hdr->cbfcnp;
162         hdr17->func_code = hdr->func_code;
163         hdr17->status = hdr->status;
164         hdr17->path = hdr->path;
165         hdr17->path_id = hdr->path_id;
166         hdr17->target_id = hdr->target_id;
167         hdr17->target_lun = hdr->target_lun;
168         hdr17->flags = hdr->flags;
169         hdr17->periph_priv = hdr->periph_priv;
170         hdr17->sim_priv = hdr->sim_priv;
171         hdr17->timeout = hdr->timeout;
172
173         if (ccb->ccb_h.func_code == XPT_PATH_INQ) {
174                 struct ccb_pathinq      *cpi;
175                 struct ccb_pathinq_0x17 *cpi17;
176
177                 /* The PATH_INQ only needs special handling on the way out */
178                 cpi = &ccb->cpi;
179                 cpi17 = (struct ccb_pathinq_0x17 *)hdr17;
180                 cpi17->version_num = cpi->version_num;
181                 cpi17->hba_inquiry = cpi->hba_inquiry;
182                 cpi17->target_sprt = (u_int8_t)cpi->target_sprt;
183                 cpi17->hba_misc = (u_int8_t)cpi->hba_misc;
184                 cpi17->hba_eng_cnt = cpi->hba_eng_cnt;
185                 bcopy(&cpi->vuhba_flags[0], &cpi17->vuhba_flags[0], VUHBALEN);
186                 cpi17->max_target = cpi->max_target;
187                 cpi17->max_lun = cpi->max_lun;
188                 cpi17->async_flags = cpi->async_flags;
189                 cpi17->hpath_id = cpi->hpath_id;
190                 cpi17->initiator_id = cpi->initiator_id;
191                 bcopy(&cpi->sim_vid[0], &cpi17->sim_vid[0], SIM_IDLEN);
192                 bcopy(&cpi->hba_vid[0], &cpi17->hba_vid[0], HBA_IDLEN);
193                 bcopy(&cpi->dev_name[0], &cpi17->dev_name[0], DEV_IDLEN);
194                 cpi17->unit_number = cpi->unit_number;
195                 cpi17->bus_id = cpi->bus_id;
196                 cpi17->base_transfer_speed = cpi->base_transfer_speed;
197                 cpi17->protocol = cpi->protocol;
198                 cpi17->protocol_version = cpi->protocol_version;
199                 cpi17->transport = cpi->transport;
200                 cpi17->transport_version = cpi->transport_version;
201                 bcopy(&cpi->xport_specific, &cpi17->xport_specific,
202                     PATHINQ_SETTINGS_SIZE);
203                 cpi17->maxio = cpi->maxio;
204                 cpi17->hba_vendor = cpi->hba_vendor;
205                 cpi17->hba_device = cpi->hba_device;
206                 cpi17->hba_subvendor = cpi->hba_subvendor;
207                 cpi17->hba_subdevice = cpi->hba_subdevice;
208         } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
209                 /* Copy the rest of the header over */
210                 bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
211
212                 cam_compat_translate_dev_match_0x18(ccb);
213         } else {
214                 bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
215         }
216
217         xpt_free_ccb(ccb);
218
219         return (error);
220 }
221
222 static int
223 cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
224     struct thread *td, d_ioctl_t *cbfnp)
225 {
226         union ccb               *ccb;
227         struct ccb_hdr          *hdr;
228         struct ccb_hdr_0x18     *hdr18;
229         uint8_t                 *ccbb, *ccbb18;
230         u_int                   error;
231
232         hdr18 = (struct ccb_hdr_0x18 *)addr;
233         ccb = xpt_alloc_ccb();
234         hdr = &ccb->ccb_h;
235
236         hdr->pinfo = hdr18->pinfo;
237         hdr->xpt_links = hdr18->xpt_links;
238         hdr->sim_links = hdr18->sim_links;
239         hdr->periph_links = hdr18->periph_links;
240         hdr->retry_count = hdr18->retry_count;
241         hdr->cbfcnp = hdr18->cbfcnp;
242         hdr->func_code = hdr18->func_code;
243         hdr->status = hdr18->status;
244         hdr->path = hdr18->path;
245         hdr->path_id = hdr18->path_id;
246         hdr->target_id = hdr18->target_id;
247         hdr->target_lun = hdr18->target_lun;
248         if (hdr18->xflags & CAM_EXTLUN_VALID_0x18)
249                 hdr->target_lun = hdr18->ext_lun;
250         hdr->flags = hdr18->flags;
251         hdr->xflags = hdr18->xflags;
252         hdr->periph_priv = hdr18->periph_priv;
253         hdr->sim_priv = hdr18->sim_priv;
254         hdr->timeout = hdr18->timeout;
255         hdr->softtimeout.tv_sec = 0;
256         hdr->softtimeout.tv_usec = 0;
257
258         ccbb = (uint8_t *)&hdr[1];
259         ccbb18 = (uint8_t *)&hdr18[1];
260         bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN);
261
262         error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td);
263
264         hdr18->pinfo = hdr->pinfo;
265         hdr18->xpt_links = hdr->xpt_links;
266         hdr18->sim_links = hdr->sim_links;
267         hdr18->periph_links = hdr->periph_links;
268         hdr18->retry_count = hdr->retry_count;
269         hdr18->cbfcnp = hdr->cbfcnp;
270         hdr18->func_code = hdr->func_code;
271         hdr18->status = hdr->status;
272         hdr18->path = hdr->path;
273         hdr18->path_id = hdr->path_id;
274         hdr18->target_id = hdr->target_id;
275         hdr18->target_lun = hdr->target_lun;
276         hdr18->ext_lun = hdr->target_lun;
277         hdr18->flags = hdr->flags;
278         hdr18->xflags = hdr->xflags | CAM_EXTLUN_VALID_0x18;
279         hdr18->periph_priv = hdr->periph_priv;
280         hdr18->sim_priv = hdr->sim_priv;
281         hdr18->timeout = hdr->timeout;
282
283         bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
284
285         if (ccb->ccb_h.func_code == XPT_DEV_MATCH)
286                 cam_compat_translate_dev_match_0x18(ccb);
287
288         xpt_free_ccb(ccb);
289
290         return (error);
291 }
292
293 static int
294 cam_compat_translate_dev_match_0x18(union ccb *ccb)
295 {
296         struct dev_match_result         *dm;
297         struct dev_match_result_0x18    *dm18;
298         struct cam_periph_map_info      mapinfo;
299         int i;
300
301         /* Remap the CCB into kernel address space */
302         bzero(&mapinfo, sizeof(mapinfo));
303         cam_periph_mapmem(ccb, &mapinfo, MAXPHYS);
304
305         dm = ccb->cdm.matches;
306         /* Translate in-place: old fields are smaller */
307         dm18 = (struct dev_match_result_0x18 *)(dm);
308         
309         for (i = 0; i < ccb->cdm.num_matches; i++) {
310                 dm18[i].type = dm[i].type;
311                 switch (dm[i].type) {
312                 case DEV_MATCH_PERIPH:
313                         memcpy(&dm18[i].result.periph_result.periph_name, 
314                             &dm[i].result.periph_result.periph_name,
315                             DEV_IDLEN);
316                         dm18[i].result.periph_result.unit_number =
317                            dm[i].result.periph_result.unit_number;
318                         dm18[i].result.periph_result.path_id =
319                            dm[i].result.periph_result.path_id;
320                         dm18[i].result.periph_result.target_id =
321                            dm[i].result.periph_result.target_id;
322                         dm18[i].result.periph_result.target_lun =
323                            dm[i].result.periph_result.target_lun;
324                         break;
325                 case DEV_MATCH_DEVICE:
326                         dm18[i].result.device_result.path_id =
327                            dm[i].result.device_result.path_id;
328                         dm18[i].result.device_result.target_id =
329                            dm[i].result.device_result.target_id;
330                         dm18[i].result.device_result.target_lun =
331                            dm[i].result.device_result.target_lun;
332                         dm18[i].result.device_result.protocol =
333                            dm[i].result.device_result.protocol;
334                         memcpy(&dm18[i].result.device_result.inq_data, 
335                             &dm[i].result.device_result.inq_data,
336                             sizeof(struct scsi_inquiry_data));
337                         memcpy(&dm18[i].result.device_result.ident_data,
338                             &dm[i].result.device_result.ident_data,
339                             sizeof(struct ata_params));
340                         dm18[i].result.device_result.flags =
341                            dm[i].result.device_result.flags;
342                         break;
343                 case DEV_MATCH_BUS:
344                         memcpy(&dm18[i].result.bus_result, 
345                             &dm[i].result.bus_result,
346                             sizeof(struct bus_match_result));
347                         break;
348                 }
349         }
350
351         cam_periph_unmapmem(ccb, &mapinfo);
352
353         return (0);
354 }
355