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 } 423