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 #include <sys/taskqueue.h> 43 44 #include <cam/cam.h> 45 #include <cam/cam_ccb.h> 46 #include <cam/cam_periph.h> 47 #include <cam/cam_queue.h> 48 #include <cam/cam_xpt_periph.h> 49 #include <cam/cam_debug.h> 50 #include <cam/cam_sim.h> 51 #include <cam/cam_compat.h> 52 53 #include <cam/scsi/scsi_all.h> 54 #include <cam/scsi/scsi_pass.h> 55 56 typedef enum { 57 PASS_FLAG_OPEN = 0x01, 58 PASS_FLAG_LOCKED = 0x02, 59 PASS_FLAG_INVALID = 0x04, 60 PASS_FLAG_INITIAL_PHYSPATH = 0x08 61 } pass_flags; 62 63 typedef enum { 64 PASS_STATE_NORMAL 65 } pass_state; 66 67 typedef enum { 68 PASS_CCB_BUFFER_IO 69 } pass_ccb_types; 70 71 #define ccb_type ppriv_field0 72 #define ccb_bp ppriv_ptr1 73 74 struct pass_softc { 75 pass_state state; 76 pass_flags flags; 77 u_int8_t pd_type; 78 union ccb saved_ccb; 79 int open_count; 80 struct devstat *device_stats; 81 struct cdev *dev; 82 struct cdev *alias_dev; 83 struct task add_physpath_task; 84 }; 85 86 87 static d_open_t passopen; 88 static d_close_t passclose; 89 static d_ioctl_t passioctl; 90 static d_ioctl_t passdoioctl; 91 92 static periph_init_t passinit; 93 static periph_ctor_t passregister; 94 static periph_oninv_t passoninvalidate; 95 static periph_dtor_t passcleanup; 96 static void pass_add_physpath(void *context, int pending); 97 static void passasync(void *callback_arg, u_int32_t code, 98 struct cam_path *path, void *arg); 99 static int passerror(union ccb *ccb, u_int32_t cam_flags, 100 u_int32_t sense_flags); 101 static int passsendccb(struct cam_periph *periph, union ccb *ccb, 102 union ccb *inccb); 103 104 static struct periph_driver passdriver = 105 { 106 passinit, "pass", 107 TAILQ_HEAD_INITIALIZER(passdriver.units), /* generation */ 0 108 }; 109 110 PERIPHDRIVER_DECLARE(pass, passdriver); 111 112 static struct cdevsw pass_cdevsw = { 113 .d_version = D_VERSION, 114 .d_flags = D_TRACKCLOSE, 115 .d_open = passopen, 116 .d_close = passclose, 117 .d_ioctl = passioctl, 118 .d_name = "pass", 119 }; 120 121 static void 122 passinit(void) 123 { 124 cam_status status; 125 126 /* 127 * Install a global async callback. This callback will 128 * receive async callbacks like "new device found". 129 */ 130 status = xpt_register_async(AC_FOUND_DEVICE, passasync, NULL, NULL); 131 132 if (status != CAM_REQ_CMP) { 133 printf("pass: Failed to attach master async callback " 134 "due to status 0x%x!\n", status); 135 } 136 137 } 138 139 static void 140 passdevgonecb(void *arg) 141 { 142 struct cam_periph *periph; 143 struct mtx *mtx; 144 struct pass_softc *softc; 145 int i; 146 147 periph = (struct cam_periph *)arg; 148 mtx = cam_periph_mtx(periph); 149 mtx_lock(mtx); 150 151 softc = (struct pass_softc *)periph->softc; 152 KASSERT(softc->open_count >= 0, ("Negative open count %d", 153 softc->open_count)); 154 155 /* 156 * When we get this callback, we will get no more close calls from 157 * devfs. So if we have any dangling opens, we need to release the 158 * reference held for that particular context. 159 */ 160 for (i = 0; i < softc->open_count; i++) 161 cam_periph_release_locked(periph); 162 163 softc->open_count = 0; 164 165 /* 166 * Release the reference held for the device node, it is gone now. 167 */ 168 cam_periph_release_locked(periph); 169 170 /* 171 * We reference the lock directly here, instead of using 172 * cam_periph_unlock(). The reason is that the final call to 173 * cam_periph_release_locked() above could result in the periph 174 * getting freed. If that is the case, dereferencing the periph 175 * with a cam_periph_unlock() call would cause a page fault. 176 */ 177 mtx_unlock(mtx); 178 } 179 180 static void 181 passoninvalidate(struct cam_periph *periph) 182 { 183 struct pass_softc *softc; 184 185 softc = (struct pass_softc *)periph->softc; 186 187 /* 188 * De-register any async callbacks. 189 */ 190 xpt_register_async(0, passasync, periph, periph->path); 191 192 softc->flags |= PASS_FLAG_INVALID; 193 194 /* 195 * Tell devfs this device has gone away, and ask for a callback 196 * when it has cleaned up its state. 197 */ 198 destroy_dev_sched_cb(softc->dev, passdevgonecb, periph); 199 200 /* 201 * XXX Return all queued I/O with ENXIO. 202 * XXX Handle any transactions queued to the card 203 * with XPT_ABORT_CCB. 204 */ 205 } 206 207 static void 208 passcleanup(struct cam_periph *periph) 209 { 210 struct pass_softc *softc; 211 212 softc = (struct pass_softc *)periph->softc; 213 214 devstat_remove_entry(softc->device_stats); 215 216 cam_periph_unlock(periph); 217 taskqueue_drain(taskqueue_thread, &softc->add_physpath_task); 218 219 cam_periph_lock(periph); 220 221 free(softc, M_DEVBUF); 222 } 223 224 static void 225 pass_add_physpath(void *context, int pending) 226 { 227 struct cam_periph *periph; 228 struct pass_softc *softc; 229 char *physpath; 230 231 /* 232 * If we have one, create a devfs alias for our 233 * physical path. 234 */ 235 periph = context; 236 softc = periph->softc; 237 physpath = malloc(MAXPATHLEN, M_DEVBUF, M_WAITOK); 238 cam_periph_lock(periph); 239 if (periph->flags & CAM_PERIPH_INVALID) { 240 cam_periph_unlock(periph); 241 goto out; 242 } 243 if (xpt_getattr(physpath, MAXPATHLEN, 244 "GEOM::physpath", periph->path) == 0 245 && strlen(physpath) != 0) { 246 247 cam_periph_unlock(periph); 248 make_dev_physpath_alias(MAKEDEV_WAITOK, &softc->alias_dev, 249 softc->dev, softc->alias_dev, physpath); 250 cam_periph_lock(periph); 251 } 252 253 /* 254 * Now that we've made our alias, we no longer have to have a 255 * reference to the device. 256 */ 257 if ((softc->flags & PASS_FLAG_INITIAL_PHYSPATH) == 0) { 258 softc->flags |= PASS_FLAG_INITIAL_PHYSPATH; 259 cam_periph_unlock(periph); 260 dev_rel(softc->dev); 261 } 262 else 263 cam_periph_unlock(periph); 264 265 out: 266 free(physpath, M_DEVBUF); 267 } 268 269 static void 270 passasync(void *callback_arg, u_int32_t code, 271 struct cam_path *path, void *arg) 272 { 273 struct cam_periph *periph; 274 275 periph = (struct cam_periph *)callback_arg; 276 277 switch (code) { 278 case AC_FOUND_DEVICE: 279 { 280 struct ccb_getdev *cgd; 281 cam_status status; 282 283 cgd = (struct ccb_getdev *)arg; 284 if (cgd == NULL) 285 break; 286 287 /* 288 * Allocate a peripheral instance for 289 * this device and start the probe 290 * process. 291 */ 292 status = cam_periph_alloc(passregister, passoninvalidate, 293 passcleanup, NULL, "pass", 294 CAM_PERIPH_BIO, path, 295 passasync, AC_FOUND_DEVICE, cgd); 296 297 if (status != CAM_REQ_CMP 298 && status != CAM_REQ_INPROG) { 299 const struct cam_status_entry *entry; 300 301 entry = cam_fetch_status_entry(status); 302 303 printf("passasync: Unable to attach new device " 304 "due to status %#x: %s\n", status, entry ? 305 entry->status_text : "Unknown"); 306 } 307 308 break; 309 } 310 case AC_ADVINFO_CHANGED: 311 { 312 uintptr_t buftype; 313 314 buftype = (uintptr_t)arg; 315 if (buftype == CDAI_TYPE_PHYS_PATH) { 316 struct pass_softc *softc; 317 318 softc = (struct pass_softc *)periph->softc; 319 taskqueue_enqueue(taskqueue_thread, 320 &softc->add_physpath_task); 321 } 322 break; 323 } 324 default: 325 cam_periph_async(periph, code, path, arg); 326 break; 327 } 328 } 329 330 static cam_status 331 passregister(struct cam_periph *periph, void *arg) 332 { 333 struct pass_softc *softc; 334 struct ccb_getdev *cgd; 335 struct ccb_pathinq cpi; 336 int no_tags; 337 338 cgd = (struct ccb_getdev *)arg; 339 if (cgd == NULL) { 340 printf("%s: no getdev CCB, can't register device\n", __func__); 341 return(CAM_REQ_CMP_ERR); 342 } 343 344 softc = (struct pass_softc *)malloc(sizeof(*softc), 345 M_DEVBUF, M_NOWAIT); 346 347 if (softc == NULL) { 348 printf("%s: Unable to probe new device. " 349 "Unable to allocate softc\n", __func__); 350 return(CAM_REQ_CMP_ERR); 351 } 352 353 bzero(softc, sizeof(*softc)); 354 softc->state = PASS_STATE_NORMAL; 355 if (cgd->protocol == PROTO_SCSI || cgd->protocol == PROTO_ATAPI) 356 softc->pd_type = SID_TYPE(&cgd->inq_data); 357 else if (cgd->protocol == PROTO_SATAPM) 358 softc->pd_type = T_ENCLOSURE; 359 else 360 softc->pd_type = T_DIRECT; 361 362 periph->softc = softc; 363 364 bzero(&cpi, sizeof(cpi)); 365 xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 366 cpi.ccb_h.func_code = XPT_PATH_INQ; 367 xpt_action((union ccb *)&cpi); 368 369 /* 370 * We pass in 0 for a blocksize, since we don't 371 * know what the blocksize of this device is, if 372 * it even has a blocksize. 373 */ 374 cam_periph_unlock(periph); 375 no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; 376 softc->device_stats = devstat_new_entry("pass", 377 periph->unit_number, 0, 378 DEVSTAT_NO_BLOCKSIZE 379 | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0), 380 softc->pd_type | 381 XPORT_DEVSTAT_TYPE(cpi.transport) | 382 DEVSTAT_TYPE_PASS, 383 DEVSTAT_PRIORITY_PASS); 384 385 /* 386 * Acquire a reference to the periph before we create the devfs 387 * instance for it. We'll release this reference once the devfs 388 * instance has been freed. 389 */ 390 if (cam_periph_acquire(periph) != CAM_REQ_CMP) { 391 xpt_print(periph->path, "%s: lost periph during " 392 "registration!\n", __func__); 393 cam_periph_lock(periph); 394 return (CAM_REQ_CMP_ERR); 395 } 396 397 /* Register the device */ 398 softc->dev = make_dev(&pass_cdevsw, periph->unit_number, 399 UID_ROOT, GID_OPERATOR, 0600, "%s%d", 400 periph->periph_name, periph->unit_number); 401 402 /* 403 * Now that we have made the devfs instance, hold a reference to it 404 * until the task queue has run to setup the physical path alias. 405 * That way devfs won't get rid of the device before we add our 406 * alias. 407 */ 408 dev_ref(softc->dev); 409 410 cam_periph_lock(periph); 411 softc->dev->si_drv1 = periph; 412 413 TASK_INIT(&softc->add_physpath_task, /*priority*/0, 414 pass_add_physpath, periph); 415 416 /* 417 * See if physical path information is already available. 418 */ 419 taskqueue_enqueue(taskqueue_thread, &softc->add_physpath_task); 420 421 /* 422 * Add an async callback so that we get notified if 423 * this device goes away or its physical path 424 * (stored in the advanced info data of the EDT) has 425 * changed. 426 */ 427 xpt_register_async(AC_LOST_DEVICE | AC_ADVINFO_CHANGED, 428 passasync, periph, periph->path); 429 430 if (bootverbose) 431 xpt_announce_periph(periph, NULL); 432 433 return(CAM_REQ_CMP); 434 } 435 436 static int 437 passopen(struct cdev *dev, int flags, int fmt, struct thread *td) 438 { 439 struct cam_periph *periph; 440 struct pass_softc *softc; 441 int error; 442 443 periph = (struct cam_periph *)dev->si_drv1; 444 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 445 return (ENXIO); 446 447 cam_periph_lock(periph); 448 449 softc = (struct pass_softc *)periph->softc; 450 451 if (softc->flags & PASS_FLAG_INVALID) { 452 cam_periph_release_locked(periph); 453 cam_periph_unlock(periph); 454 return(ENXIO); 455 } 456 457 /* 458 * Don't allow access when we're running at a high securelevel. 459 */ 460 error = securelevel_gt(td->td_ucred, 1); 461 if (error) { 462 cam_periph_release_locked(periph); 463 cam_periph_unlock(periph); 464 return(error); 465 } 466 467 /* 468 * Only allow read-write access. 469 */ 470 if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) { 471 cam_periph_release_locked(periph); 472 cam_periph_unlock(periph); 473 return(EPERM); 474 } 475 476 /* 477 * We don't allow nonblocking access. 478 */ 479 if ((flags & O_NONBLOCK) != 0) { 480 xpt_print(periph->path, "can't do nonblocking access\n"); 481 cam_periph_release_locked(periph); 482 cam_periph_unlock(periph); 483 return(EINVAL); 484 } 485 486 softc->open_count++; 487 488 cam_periph_unlock(periph); 489 490 return (error); 491 } 492 493 static int 494 passclose(struct cdev *dev, int flag, int fmt, struct thread *td) 495 { 496 struct cam_periph *periph; 497 struct pass_softc *softc; 498 struct mtx *mtx; 499 500 periph = (struct cam_periph *)dev->si_drv1; 501 if (periph == NULL) 502 return (ENXIO); 503 mtx = cam_periph_mtx(periph); 504 mtx_lock(mtx); 505 506 softc = periph->softc; 507 softc->open_count--; 508 509 cam_periph_release_locked(periph); 510 511 /* 512 * We reference the lock directly here, instead of using 513 * cam_periph_unlock(). The reason is that the call to 514 * cam_periph_release_locked() above could result in the periph 515 * getting freed. If that is the case, dereferencing the periph 516 * with a cam_periph_unlock() call would cause a page fault. 517 * 518 * cam_periph_release() avoids this problem using the same method, 519 * but we're manually acquiring and dropping the lock here to 520 * protect the open count and avoid another lock acquisition and 521 * release. 522 */ 523 mtx_unlock(mtx); 524 525 return (0); 526 } 527 528 static int 529 passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 530 { 531 int error; 532 533 if ((error = passdoioctl(dev, cmd, addr, flag, td)) == ENOTTY) { 534 error = cam_compat_ioctl(dev, cmd, addr, flag, td, passdoioctl); 535 } 536 return (error); 537 } 538 539 static int 540 passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 541 { 542 struct cam_periph *periph; 543 int error; 544 uint32_t priority; 545 546 periph = (struct cam_periph *)dev->si_drv1; 547 if (periph == NULL) 548 return(ENXIO); 549 550 cam_periph_lock(periph); 551 552 error = 0; 553 554 switch (cmd) { 555 556 case CAMIOCOMMAND: 557 { 558 union ccb *inccb; 559 union ccb *ccb; 560 int ccb_malloced; 561 562 inccb = (union ccb *)addr; 563 564 /* 565 * Some CCB types, like scan bus and scan lun can only go 566 * through the transport layer device. 567 */ 568 if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) { 569 xpt_print(periph->path, "CCB function code %#x is " 570 "restricted to the XPT device\n", 571 inccb->ccb_h.func_code); 572 error = ENODEV; 573 break; 574 } 575 576 /* Compatibility for RL/priority-unaware code. */ 577 priority = inccb->ccb_h.pinfo.priority; 578 if (priority <= CAM_PRIORITY_OOB) 579 priority += CAM_PRIORITY_OOB + 1; 580 581 /* 582 * Non-immediate CCBs need a CCB from the per-device pool 583 * of CCBs, which is scheduled by the transport layer. 584 * Immediate CCBs and user-supplied CCBs should just be 585 * malloced. 586 */ 587 if ((inccb->ccb_h.func_code & XPT_FC_QUEUED) 588 && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) { 589 ccb = cam_periph_getccb(periph, priority); 590 ccb_malloced = 0; 591 } else { 592 ccb = xpt_alloc_ccb_nowait(); 593 594 if (ccb != NULL) 595 xpt_setup_ccb(&ccb->ccb_h, periph->path, 596 priority); 597 ccb_malloced = 1; 598 } 599 600 if (ccb == NULL) { 601 xpt_print(periph->path, "unable to allocate CCB\n"); 602 error = ENOMEM; 603 break; 604 } 605 606 error = passsendccb(periph, ccb, inccb); 607 608 if (ccb_malloced) 609 xpt_free_ccb(ccb); 610 else 611 xpt_release_ccb(ccb); 612 613 break; 614 } 615 default: 616 error = cam_periph_ioctl(periph, cmd, addr, passerror); 617 break; 618 } 619 620 cam_periph_unlock(periph); 621 return(error); 622 } 623 624 /* 625 * Generally, "ccb" should be the CCB supplied by the kernel. "inccb" 626 * should be the CCB that is copied in from the user. 627 */ 628 static int 629 passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) 630 { 631 struct pass_softc *softc; 632 struct cam_periph_map_info mapinfo; 633 xpt_opcode fc; 634 int error; 635 636 softc = (struct pass_softc *)periph->softc; 637 638 /* 639 * There are some fields in the CCB header that need to be 640 * preserved, the rest we get from the user. 641 */ 642 xpt_merge_ccb(ccb, inccb); 643 644 /* 645 * Let cam_periph_mapmem do a sanity check on the data pointer format. 646 * Even if no data transfer is needed, it's a cheap check and it 647 * simplifies the code. 648 */ 649 fc = ccb->ccb_h.func_code; 650 if ((fc == XPT_SCSI_IO) || (fc == XPT_ATA_IO) || (fc == XPT_SMP_IO) 651 || (fc == XPT_DEV_MATCH) || (fc == XPT_DEV_ADVINFO)) { 652 bzero(&mapinfo, sizeof(mapinfo)); 653 654 /* 655 * cam_periph_mapmem calls into proc and vm functions that can 656 * sleep as well as trigger I/O, so we can't hold the lock. 657 * Dropping it here is reasonably safe. 658 */ 659 cam_periph_unlock(periph); 660 error = cam_periph_mapmem(ccb, &mapinfo); 661 cam_periph_lock(periph); 662 663 /* 664 * cam_periph_mapmem returned an error, we can't continue. 665 * Return the error to the user. 666 */ 667 if (error) 668 return(error); 669 } else 670 /* Ensure that the unmap call later on is a no-op. */ 671 mapinfo.num_bufs_used = 0; 672 673 /* 674 * If the user wants us to perform any error recovery, then honor 675 * that request. Otherwise, it's up to the user to perform any 676 * error recovery. 677 */ 678 cam_periph_runccb(ccb, passerror, /* cam_flags */ CAM_RETRY_SELTO, 679 /* sense_flags */ ((ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? 680 SF_RETRY_UA : SF_NO_RECOVERY) | SF_NO_PRINT, 681 softc->device_stats); 682 683 cam_periph_unmapmem(ccb, &mapinfo); 684 685 ccb->ccb_h.cbfcnp = NULL; 686 ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv; 687 bcopy(ccb, inccb, sizeof(union ccb)); 688 689 return(0); 690 } 691 692 static int 693 passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 694 { 695 struct cam_periph *periph; 696 struct pass_softc *softc; 697 698 periph = xpt_path_periph(ccb->ccb_h.path); 699 softc = (struct pass_softc *)periph->softc; 700 701 return(cam_periph_error(ccb, cam_flags, sense_flags, 702 &softc->saved_ccb)); 703 } 704