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