1 /*- 2 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 3 * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer, 11 * without modification, immediately at the beginning of the file. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/types.h> 35 #include <sys/bio.h> 36 #include <sys/malloc.h> 37 #include <sys/fcntl.h> 38 #include <sys/conf.h> 39 #include <sys/errno.h> 40 #include <sys/devicestat.h> 41 #include <sys/proc.h> 42 43 #include <cam/cam.h> 44 #include <cam/cam_ccb.h> 45 #include <cam/cam_periph.h> 46 #include <cam/cam_queue.h> 47 #include <cam/cam_xpt_periph.h> 48 #include <cam/cam_debug.h> 49 #include <cam/cam_sim.h> 50 51 #include <cam/scsi/scsi_all.h> 52 #include <cam/scsi/scsi_pass.h> 53 54 typedef enum { 55 PASS_FLAG_OPEN = 0x01, 56 PASS_FLAG_LOCKED = 0x02, 57 PASS_FLAG_INVALID = 0x04 58 } pass_flags; 59 60 typedef enum { 61 PASS_STATE_NORMAL 62 } pass_state; 63 64 typedef enum { 65 PASS_CCB_BUFFER_IO, 66 PASS_CCB_WAITING 67 } pass_ccb_types; 68 69 #define ccb_type ppriv_field0 70 #define ccb_bp ppriv_ptr1 71 72 struct pass_softc { 73 pass_state state; 74 pass_flags flags; 75 u_int8_t pd_type; 76 union ccb saved_ccb; 77 struct devstat *device_stats; 78 struct cdev *dev; 79 }; 80 81 82 static d_open_t passopen; 83 static d_close_t passclose; 84 static d_ioctl_t passioctl; 85 86 static periph_init_t passinit; 87 static periph_ctor_t passregister; 88 static periph_oninv_t passoninvalidate; 89 static periph_dtor_t passcleanup; 90 static periph_start_t passstart; 91 static void passasync(void *callback_arg, u_int32_t code, 92 struct cam_path *path, void *arg); 93 static void passdone(struct cam_periph *periph, 94 union ccb *done_ccb); 95 static int passerror(union ccb *ccb, u_int32_t cam_flags, 96 u_int32_t sense_flags); 97 static int passsendccb(struct cam_periph *periph, union ccb *ccb, 98 union ccb *inccb); 99 100 static struct periph_driver passdriver = 101 { 102 passinit, "pass", 103 TAILQ_HEAD_INITIALIZER(passdriver.units), /* generation */ 0 104 }; 105 106 PERIPHDRIVER_DECLARE(pass, passdriver); 107 108 static struct cdevsw pass_cdevsw = { 109 .d_version = D_VERSION, 110 .d_flags = 0, 111 .d_open = passopen, 112 .d_close = passclose, 113 .d_ioctl = passioctl, 114 .d_name = "pass", 115 }; 116 117 static void 118 passinit(void) 119 { 120 cam_status status; 121 122 /* 123 * Install a global async callback. This callback will 124 * receive async callbacks like "new device found". 125 */ 126 status = xpt_register_async(AC_FOUND_DEVICE, passasync, NULL, NULL); 127 128 if (status != CAM_REQ_CMP) { 129 printf("pass: Failed to attach master async callback " 130 "due to status 0x%x!\n", status); 131 } 132 133 } 134 135 static void 136 passoninvalidate(struct cam_periph *periph) 137 { 138 struct pass_softc *softc; 139 140 softc = (struct pass_softc *)periph->softc; 141 142 /* 143 * De-register any async callbacks. 144 */ 145 xpt_register_async(0, passasync, periph, periph->path); 146 147 softc->flags |= PASS_FLAG_INVALID; 148 149 /* 150 * XXX Return all queued I/O with ENXIO. 151 * XXX Handle any transactions queued to the card 152 * with XPT_ABORT_CCB. 153 */ 154 155 if (bootverbose) { 156 xpt_print(periph->path, "lost device\n"); 157 } 158 159 } 160 161 static void 162 passcleanup(struct cam_periph *periph) 163 { 164 struct pass_softc *softc; 165 166 softc = (struct pass_softc *)periph->softc; 167 168 if (bootverbose) 169 xpt_print(periph->path, "removing device entry\n"); 170 devstat_remove_entry(softc->device_stats); 171 cam_periph_unlock(periph); 172 /* 173 * passcleanup() is indirectly a d_close method via passclose, 174 * so using destroy_dev(9) directly can result in deadlock. 175 */ 176 destroy_dev_sched(softc->dev); 177 cam_periph_lock(periph); 178 free(softc, M_DEVBUF); 179 } 180 181 static void 182 passasync(void *callback_arg, u_int32_t code, 183 struct cam_path *path, void *arg) 184 { 185 struct cam_periph *periph; 186 187 periph = (struct cam_periph *)callback_arg; 188 189 switch (code) { 190 case AC_FOUND_DEVICE: 191 { 192 struct ccb_getdev *cgd; 193 cam_status status; 194 195 cgd = (struct ccb_getdev *)arg; 196 if (cgd == NULL) 197 break; 198 199 /* 200 * Allocate a peripheral instance for 201 * this device and start the probe 202 * process. 203 */ 204 status = cam_periph_alloc(passregister, passoninvalidate, 205 passcleanup, passstart, "pass", 206 CAM_PERIPH_BIO, cgd->ccb_h.path, 207 passasync, AC_FOUND_DEVICE, cgd); 208 209 if (status != CAM_REQ_CMP 210 && status != CAM_REQ_INPROG) { 211 const struct cam_status_entry *entry; 212 213 entry = cam_fetch_status_entry(status); 214 215 printf("passasync: Unable to attach new device " 216 "due to status %#x: %s\n", status, entry ? 217 entry->status_text : "Unknown"); 218 } 219 220 break; 221 } 222 default: 223 cam_periph_async(periph, code, path, arg); 224 break; 225 } 226 } 227 228 static cam_status 229 passregister(struct cam_periph *periph, void *arg) 230 { 231 struct pass_softc *softc; 232 struct ccb_getdev *cgd; 233 struct ccb_pathinq cpi; 234 int no_tags; 235 236 cgd = (struct ccb_getdev *)arg; 237 if (periph == NULL) { 238 printf("passregister: periph was NULL!!\n"); 239 return(CAM_REQ_CMP_ERR); 240 } 241 242 if (cgd == NULL) { 243 printf("passregister: no getdev CCB, can't register device\n"); 244 return(CAM_REQ_CMP_ERR); 245 } 246 247 softc = (struct pass_softc *)malloc(sizeof(*softc), 248 M_DEVBUF, M_NOWAIT); 249 250 if (softc == NULL) { 251 printf("passregister: Unable to probe new device. " 252 "Unable to allocate softc\n"); 253 return(CAM_REQ_CMP_ERR); 254 } 255 256 bzero(softc, sizeof(*softc)); 257 softc->state = PASS_STATE_NORMAL; 258 if (cgd->protocol == PROTO_SCSI || cgd->protocol == PROTO_ATAPI) 259 softc->pd_type = SID_TYPE(&cgd->inq_data); 260 else if (cgd->protocol == PROTO_SATAPM) 261 softc->pd_type = T_ENCLOSURE; 262 else 263 softc->pd_type = T_DIRECT; 264 265 periph->softc = softc; 266 267 bzero(&cpi, sizeof(cpi)); 268 xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 269 cpi.ccb_h.func_code = XPT_PATH_INQ; 270 xpt_action((union ccb *)&cpi); 271 272 /* 273 * We pass in 0 for a blocksize, since we don't 274 * know what the blocksize of this device is, if 275 * it even has a blocksize. 276 */ 277 mtx_unlock(periph->sim->mtx); 278 no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; 279 softc->device_stats = devstat_new_entry("pass", 280 periph->unit_number, 0, 281 DEVSTAT_NO_BLOCKSIZE 282 | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0), 283 softc->pd_type | 284 XPORT_DEVSTAT_TYPE(cpi.transport) | 285 DEVSTAT_TYPE_PASS, 286 DEVSTAT_PRIORITY_PASS); 287 288 /* Register the device */ 289 softc->dev = make_dev(&pass_cdevsw, periph->unit_number, 290 UID_ROOT, GID_OPERATOR, 0600, "%s%d", 291 periph->periph_name, periph->unit_number); 292 mtx_lock(periph->sim->mtx); 293 softc->dev->si_drv1 = periph; 294 295 /* 296 * Add an async callback so that we get 297 * notified if this device goes away. 298 */ 299 xpt_register_async(AC_LOST_DEVICE, passasync, periph, periph->path); 300 301 if (bootverbose) 302 xpt_announce_periph(periph, NULL); 303 304 return(CAM_REQ_CMP); 305 } 306 307 static int 308 passopen(struct cdev *dev, int flags, int fmt, struct thread *td) 309 { 310 struct cam_periph *periph; 311 struct pass_softc *softc; 312 int error; 313 314 periph = (struct cam_periph *)dev->si_drv1; 315 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 316 return (ENXIO); 317 318 cam_periph_lock(periph); 319 320 softc = (struct pass_softc *)periph->softc; 321 322 if (softc->flags & PASS_FLAG_INVALID) { 323 cam_periph_unlock(periph); 324 cam_periph_release(periph); 325 return(ENXIO); 326 } 327 328 /* 329 * Don't allow access when we're running at a high securelevel. 330 */ 331 error = securelevel_gt(td->td_ucred, 1); 332 if (error) { 333 cam_periph_unlock(periph); 334 cam_periph_release(periph); 335 return(error); 336 } 337 338 /* 339 * Only allow read-write access. 340 */ 341 if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) { 342 cam_periph_unlock(periph); 343 cam_periph_release(periph); 344 return(EPERM); 345 } 346 347 /* 348 * We don't allow nonblocking access. 349 */ 350 if ((flags & O_NONBLOCK) != 0) { 351 xpt_print(periph->path, "can't do nonblocking access\n"); 352 cam_periph_unlock(periph); 353 cam_periph_release(periph); 354 return(EINVAL); 355 } 356 357 if ((softc->flags & PASS_FLAG_OPEN) == 0) { 358 softc->flags |= PASS_FLAG_OPEN; 359 cam_periph_unlock(periph); 360 } else { 361 /* Device closes aren't symmertical, so fix up the refcount */ 362 cam_periph_unlock(periph); 363 cam_periph_release(periph); 364 } 365 366 return (error); 367 } 368 369 static int 370 passclose(struct cdev *dev, int flag, int fmt, struct thread *td) 371 { 372 struct cam_periph *periph; 373 struct pass_softc *softc; 374 375 periph = (struct cam_periph *)dev->si_drv1; 376 if (periph == NULL) 377 return (ENXIO); 378 379 cam_periph_lock(periph); 380 381 softc = (struct pass_softc *)periph->softc; 382 softc->flags &= ~PASS_FLAG_OPEN; 383 384 cam_periph_unlock(periph); 385 cam_periph_release(periph); 386 387 return (0); 388 } 389 390 static void 391 passstart(struct cam_periph *periph, union ccb *start_ccb) 392 { 393 struct pass_softc *softc; 394 395 softc = (struct pass_softc *)periph->softc; 396 397 switch (softc->state) { 398 case PASS_STATE_NORMAL: 399 start_ccb->ccb_h.ccb_type = PASS_CCB_WAITING; 400 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 401 periph_links.sle); 402 periph->immediate_priority = CAM_PRIORITY_NONE; 403 wakeup(&periph->ccb_list); 404 break; 405 } 406 } 407 408 static void 409 passdone(struct cam_periph *periph, union ccb *done_ccb) 410 { 411 struct pass_softc *softc; 412 struct ccb_scsiio *csio; 413 414 softc = (struct pass_softc *)periph->softc; 415 csio = &done_ccb->csio; 416 switch (csio->ccb_h.ccb_type) { 417 case PASS_CCB_WAITING: 418 /* Caller will release the CCB */ 419 wakeup(&done_ccb->ccb_h.cbfcnp); 420 return; 421 } 422 xpt_release_ccb(done_ccb); 423 } 424 425 static int 426 passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 427 { 428 struct cam_periph *periph; 429 struct pass_softc *softc; 430 int error; 431 432 periph = (struct cam_periph *)dev->si_drv1; 433 if (periph == NULL) 434 return(ENXIO); 435 436 cam_periph_lock(periph); 437 softc = (struct pass_softc *)periph->softc; 438 439 error = 0; 440 441 switch (cmd) { 442 443 case CAMIOCOMMAND: 444 { 445 union ccb *inccb; 446 union ccb *ccb; 447 int ccb_malloced; 448 449 inccb = (union ccb *)addr; 450 451 /* 452 * Some CCB types, like scan bus and scan lun can only go 453 * through the transport layer device. 454 */ 455 if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) { 456 xpt_print(periph->path, "CCB function code %#x is " 457 "restricted to the XPT device\n", 458 inccb->ccb_h.func_code); 459 error = ENODEV; 460 break; 461 } 462 463 /* 464 * Non-immediate CCBs need a CCB from the per-device pool 465 * of CCBs, which is scheduled by the transport layer. 466 * Immediate CCBs and user-supplied CCBs should just be 467 * malloced. 468 */ 469 if ((inccb->ccb_h.func_code & XPT_FC_QUEUED) 470 && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) { 471 ccb = cam_periph_getccb(periph, 472 inccb->ccb_h.pinfo.priority); 473 ccb_malloced = 0; 474 } else { 475 ccb = xpt_alloc_ccb_nowait(); 476 477 if (ccb != NULL) 478 xpt_setup_ccb(&ccb->ccb_h, periph->path, 479 inccb->ccb_h.pinfo.priority); 480 ccb_malloced = 1; 481 } 482 483 if (ccb == NULL) { 484 xpt_print(periph->path, "unable to allocate CCB\n"); 485 error = ENOMEM; 486 break; 487 } 488 489 error = passsendccb(periph, ccb, inccb); 490 491 if (ccb_malloced) 492 xpt_free_ccb(ccb); 493 else 494 xpt_release_ccb(ccb); 495 496 break; 497 } 498 default: 499 error = cam_periph_ioctl(periph, cmd, addr, passerror); 500 break; 501 } 502 503 cam_periph_unlock(periph); 504 return(error); 505 } 506 507 /* 508 * Generally, "ccb" should be the CCB supplied by the kernel. "inccb" 509 * should be the CCB that is copied in from the user. 510 */ 511 static int 512 passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) 513 { 514 struct pass_softc *softc; 515 struct cam_periph_map_info mapinfo; 516 int error, need_unmap; 517 518 softc = (struct pass_softc *)periph->softc; 519 520 need_unmap = 0; 521 522 /* 523 * There are some fields in the CCB header that need to be 524 * preserved, the rest we get from the user. 525 */ 526 xpt_merge_ccb(ccb, inccb); 527 528 /* 529 * There's no way for the user to have a completion 530 * function, so we put our own completion function in here. 531 */ 532 ccb->ccb_h.cbfcnp = passdone; 533 534 /* 535 * We only attempt to map the user memory into kernel space 536 * if they haven't passed in a physical memory pointer, 537 * and if there is actually an I/O operation to perform. 538 * cam_periph_mapmem() supports SCSI, ATA, SMP, ADVINFO and device 539 * match CCBs. For the SCSI, ATA and ADVINFO CCBs, we only pass the 540 * CCB in if there's actually data to map. cam_periph_mapmem() will 541 * do the right thing, even if there isn't data to map, but since CCBs 542 * without data are a reasonably common occurance (e.g. test unit 543 * ready), it will save a few cycles if we check for it here. 544 */ 545 if (((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) 546 && (((ccb->ccb_h.func_code == XPT_SCSI_IO || 547 ccb->ccb_h.func_code == XPT_ATA_IO) 548 && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)) 549 || (ccb->ccb_h.func_code == XPT_DEV_MATCH) 550 || (ccb->ccb_h.func_code == XPT_SMP_IO) 551 || ((ccb->ccb_h.func_code == XPT_GDEV_ADVINFO) 552 && (ccb->cgdai.bufsiz > 0)))) { 553 554 bzero(&mapinfo, sizeof(mapinfo)); 555 556 /* 557 * cam_periph_mapmem calls into proc and vm functions that can 558 * sleep as well as trigger I/O, so we can't hold the lock. 559 * Dropping it here is reasonably safe. 560 */ 561 cam_periph_unlock(periph); 562 error = cam_periph_mapmem(ccb, &mapinfo); 563 cam_periph_lock(periph); 564 565 /* 566 * cam_periph_mapmem returned an error, we can't continue. 567 * Return the error to the user. 568 */ 569 if (error) 570 return(error); 571 572 /* 573 * We successfully mapped the memory in, so we need to 574 * unmap it when the transaction is done. 575 */ 576 need_unmap = 1; 577 } 578 579 /* 580 * If the user wants us to perform any error recovery, then honor 581 * that request. Otherwise, it's up to the user to perform any 582 * error recovery. 583 */ 584 cam_periph_runccb(ccb, 585 (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? passerror : NULL, 586 /* cam_flags */ CAM_RETRY_SELTO, /* sense_flags */SF_RETRY_UA, 587 softc->device_stats); 588 589 if (need_unmap != 0) 590 cam_periph_unmapmem(ccb, &mapinfo); 591 592 ccb->ccb_h.cbfcnp = NULL; 593 ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv; 594 bcopy(ccb, inccb, sizeof(union ccb)); 595 596 return(0); 597 } 598 599 static int 600 passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 601 { 602 struct cam_periph *periph; 603 struct pass_softc *softc; 604 605 periph = xpt_path_periph(ccb->ccb_h.path); 606 softc = (struct pass_softc *)periph->softc; 607 608 return(cam_periph_error(ccb, cam_flags, sense_flags, 609 &softc->saved_ccb)); 610 } 611