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); 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 356