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