Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/cam/cam_compat.c
39478 views
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
}
469
470