1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2007 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 * scsi_sg peripheral driver. This driver is meant to implement the Linux 31 * SG passthrough interface for SCSI. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/types.h> 41 #include <sys/bio.h> 42 #include <sys/malloc.h> 43 #include <sys/fcntl.h> 44 #include <sys/ioccom.h> 45 #include <sys/conf.h> 46 #include <sys/errno.h> 47 #include <sys/devicestat.h> 48 #include <sys/proc.h> 49 #include <sys/uio.h> 50 51 #include <cam/cam.h> 52 #include <cam/cam_ccb.h> 53 #include <cam/cam_periph.h> 54 #include <cam/cam_queue.h> 55 #include <cam/cam_xpt_periph.h> 56 #include <cam/cam_debug.h> 57 #include <cam/cam_sim.h> 58 59 #include <cam/scsi/scsi_all.h> 60 #include <cam/scsi/scsi_message.h> 61 #include <cam/scsi/scsi_sg.h> 62 63 typedef enum { 64 SG_FLAG_LOCKED = 0x01, 65 SG_FLAG_INVALID = 0x02 66 } sg_flags; 67 68 typedef enum { 69 SG_STATE_NORMAL 70 } sg_state; 71 72 typedef enum { 73 SG_RDWR_FREE, 74 SG_RDWR_INPROG, 75 SG_RDWR_DONE 76 } sg_rdwr_state; 77 78 typedef enum { 79 SG_CCB_RDWR_IO 80 } sg_ccb_types; 81 82 #define ccb_type ppriv_field0 83 #define ccb_rdwr ppriv_ptr1 84 85 struct sg_rdwr { 86 TAILQ_ENTRY(sg_rdwr) rdwr_link; 87 int tag; 88 int state; 89 int buf_len; 90 char *buf; 91 union ccb *ccb; 92 union { 93 struct sg_header hdr; 94 struct sg_io_hdr io_hdr; 95 } hdr; 96 }; 97 98 struct sg_softc { 99 sg_state state; 100 sg_flags flags; 101 int open_count; 102 u_int maxio; 103 struct devstat *device_stats; 104 TAILQ_HEAD(, sg_rdwr) rdwr_done; 105 struct cdev *dev; 106 int sg_timeout; 107 int sg_user_timeout; 108 uint8_t pd_type; 109 }; 110 111 static d_open_t sgopen; 112 static d_close_t sgclose; 113 static d_ioctl_t sgioctl; 114 static d_write_t sgwrite; 115 static d_read_t sgread; 116 117 static periph_init_t sginit; 118 static periph_ctor_t sgregister; 119 static periph_oninv_t sgoninvalidate; 120 static periph_dtor_t sgcleanup; 121 static void sgasync(void *callback_arg, uint32_t code, 122 struct cam_path *path, void *arg); 123 static void sgdone(struct cam_periph *periph, union ccb *done_ccb); 124 static int sgsendccb(struct cam_periph *periph, union ccb *ccb); 125 static int sgsendrdwr(struct cam_periph *periph, union ccb *ccb); 126 static int sgerror(union ccb *ccb, uint32_t cam_flags, 127 uint32_t sense_flags); 128 static void sg_scsiio_status(struct ccb_scsiio *csio, 129 u_short *hoststat, u_short *drvstat); 130 131 static int scsi_group_len(u_char cmd); 132 133 static struct periph_driver sgdriver = 134 { 135 sginit, "sg", 136 TAILQ_HEAD_INITIALIZER(sgdriver.units), /* gen */ 0 137 }; 138 PERIPHDRIVER_DECLARE(sg, sgdriver); 139 140 static struct cdevsw sg_cdevsw = { 141 .d_version = D_VERSION, 142 .d_flags = D_TRACKCLOSE, 143 .d_open = sgopen, 144 .d_close = sgclose, 145 .d_ioctl = sgioctl, 146 .d_write = sgwrite, 147 .d_read = sgread, 148 .d_name = "sg", 149 }; 150 151 static int sg_version = 30125; 152 153 static void 154 sginit(void) 155 { 156 cam_status status; 157 158 /* 159 * Install a global async callback. This callback will receive aync 160 * callbacks like "new device found". 161 */ 162 status = xpt_register_async(AC_FOUND_DEVICE, sgasync, NULL, NULL); 163 164 if (status != CAM_REQ_CMP) { 165 printf("sg: Failed to attach master async callbac " 166 "due to status 0x%x!\n", status); 167 } 168 } 169 170 static void 171 sgdevgonecb(void *arg) 172 { 173 struct cam_periph *periph; 174 struct sg_softc *softc; 175 struct mtx *mtx; 176 int i; 177 178 periph = (struct cam_periph *)arg; 179 mtx = cam_periph_mtx(periph); 180 mtx_lock(mtx); 181 182 softc = (struct sg_softc *)periph->softc; 183 KASSERT(softc->open_count >= 0, ("Negative open count %d", 184 softc->open_count)); 185 186 /* 187 * When we get this callback, we will get no more close calls from 188 * devfs. So if we have any dangling opens, we need to release the 189 * reference held for that particular context. 190 */ 191 for (i = 0; i < softc->open_count; i++) 192 cam_periph_release_locked(periph); 193 194 softc->open_count = 0; 195 196 /* 197 * Release the reference held for the device node, it is gone now. 198 */ 199 cam_periph_release_locked(periph); 200 201 /* 202 * We reference the lock directly here, instead of using 203 * cam_periph_unlock(). The reason is that the final call to 204 * cam_periph_release_locked() above could result in the periph 205 * getting freed. If that is the case, dereferencing the periph 206 * with a cam_periph_unlock() call would cause a page fault. 207 */ 208 mtx_unlock(mtx); 209 } 210 211 static void 212 sgoninvalidate(struct cam_periph *periph) 213 { 214 struct sg_softc *softc; 215 216 softc = (struct sg_softc *)periph->softc; 217 218 /* 219 * Deregister any async callbacks. 220 */ 221 xpt_register_async(0, sgasync, periph, periph->path); 222 223 softc->flags |= SG_FLAG_INVALID; 224 225 /* 226 * Tell devfs this device has gone away, and ask for a callback 227 * when it has cleaned up its state. 228 */ 229 destroy_dev_sched_cb(softc->dev, sgdevgonecb, periph); 230 231 /* 232 * XXX Return all queued I/O with ENXIO. 233 * XXX Handle any transactions queued to the card 234 * with XPT_ABORT_CCB. 235 */ 236 237 } 238 239 static void 240 sgcleanup(struct cam_periph *periph) 241 { 242 struct sg_softc *softc; 243 244 softc = (struct sg_softc *)periph->softc; 245 246 devstat_remove_entry(softc->device_stats); 247 248 free(softc, M_DEVBUF); 249 } 250 251 static void 252 sgasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 253 { 254 struct cam_periph *periph; 255 256 periph = (struct cam_periph *)callback_arg; 257 258 switch (code) { 259 case AC_FOUND_DEVICE: 260 { 261 struct ccb_getdev *cgd; 262 cam_status status; 263 264 cgd = (struct ccb_getdev *)arg; 265 if (cgd == NULL) 266 break; 267 268 if (cgd->protocol != PROTO_SCSI) 269 break; 270 271 /* 272 * Allocate a peripheral instance for this device and 273 * start the probe process. 274 */ 275 status = cam_periph_alloc(sgregister, sgoninvalidate, 276 sgcleanup, NULL, "sg", 277 CAM_PERIPH_BIO, path, 278 sgasync, AC_FOUND_DEVICE, cgd); 279 if ((status != CAM_REQ_CMP) && (status != CAM_REQ_INPROG)) { 280 const struct cam_status_entry *entry; 281 282 entry = cam_fetch_status_entry(status); 283 printf("sgasync: Unable to attach new device " 284 "due to status %#x: %s\n", status, entry ? 285 entry->status_text : "Unknown"); 286 } 287 break; 288 } 289 default: 290 cam_periph_async(periph, code, path, arg); 291 break; 292 } 293 } 294 295 static cam_status 296 sgregister(struct cam_periph *periph, void *arg) 297 { 298 struct sg_softc *softc; 299 struct ccb_getdev *cgd; 300 struct ccb_pathinq cpi; 301 struct make_dev_args args; 302 int no_tags, error; 303 304 cgd = (struct ccb_getdev *)arg; 305 if (cgd == NULL) { 306 printf("sgregister: no getdev CCB, can't register device\n"); 307 return (CAM_REQ_CMP_ERR); 308 } 309 310 softc = malloc(sizeof(*softc), M_DEVBUF, M_ZERO | M_NOWAIT); 311 if (softc == NULL) { 312 printf("sgregister: Unable to allocate softc\n"); 313 return (CAM_REQ_CMP_ERR); 314 } 315 316 softc->state = SG_STATE_NORMAL; 317 softc->pd_type = SID_TYPE(&cgd->inq_data); 318 softc->sg_timeout = SG_DEFAULT_TIMEOUT / SG_DEFAULT_HZ * hz; 319 softc->sg_user_timeout = SG_DEFAULT_TIMEOUT; 320 TAILQ_INIT(&softc->rdwr_done); 321 periph->softc = softc; 322 323 xpt_path_inq(&cpi, periph->path); 324 325 if (cpi.maxio == 0) 326 softc->maxio = DFLTPHYS; /* traditional default */ 327 else if (cpi.maxio > maxphys) 328 softc->maxio = maxphys; /* for safety */ 329 else 330 softc->maxio = cpi.maxio; /* real value */ 331 332 /* 333 * We pass in 0 for all blocksize, since we don't know what the 334 * blocksize of the device is, if it even has a blocksize. 335 */ 336 cam_periph_unlock(periph); 337 no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; 338 softc->device_stats = devstat_new_entry("sg", 339 periph->unit_number, 0, 340 DEVSTAT_NO_BLOCKSIZE 341 | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0), 342 softc->pd_type | 343 XPORT_DEVSTAT_TYPE(cpi.transport) | 344 DEVSTAT_TYPE_PASS, 345 DEVSTAT_PRIORITY_PASS); 346 347 /* 348 * Acquire a reference to the periph before we create the devfs 349 * instance for it. We'll release this reference once the devfs 350 * instance has been freed. 351 */ 352 if (cam_periph_acquire(periph) != 0) { 353 xpt_print(periph->path, "%s: lost periph during " 354 "registration!\n", __func__); 355 cam_periph_lock(periph); 356 return (CAM_REQ_CMP_ERR); 357 } 358 359 /* Register the device */ 360 make_dev_args_init(&args); 361 args.mda_devsw = &sg_cdevsw; 362 args.mda_unit = periph->unit_number; 363 args.mda_uid = UID_ROOT; 364 args.mda_gid = GID_OPERATOR; 365 args.mda_mode = 0600; 366 args.mda_si_drv1 = periph; 367 error = make_dev_s(&args, &softc->dev, "%s%d", 368 periph->periph_name, periph->unit_number); 369 if (error != 0) { 370 cam_periph_lock(periph); 371 cam_periph_release_locked(periph); 372 return (CAM_REQ_CMP_ERR); 373 } 374 if (periph->unit_number < 26) { 375 (void)make_dev_alias(softc->dev, "sg%c", 376 periph->unit_number + 'a'); 377 } else { 378 (void)make_dev_alias(softc->dev, "sg%c%c", 379 ((periph->unit_number / 26) - 1) + 'a', 380 (periph->unit_number % 26) + 'a'); 381 } 382 cam_periph_lock(periph); 383 384 /* 385 * Add as async callback so that we get 386 * notified if this device goes away. 387 */ 388 xpt_register_async(AC_LOST_DEVICE, sgasync, periph, periph->path); 389 390 if (bootverbose) 391 xpt_announce_periph(periph, NULL); 392 393 return (CAM_REQ_CMP); 394 } 395 396 static void 397 sgdone(struct cam_periph *periph, union ccb *done_ccb) 398 { 399 struct sg_softc *softc; 400 struct ccb_scsiio *csio; 401 402 softc = (struct sg_softc *)periph->softc; 403 csio = &done_ccb->csio; 404 switch (csio->ccb_h.ccb_type) { 405 case SG_CCB_RDWR_IO: 406 { 407 struct sg_rdwr *rdwr; 408 int state; 409 410 devstat_end_transaction(softc->device_stats, 411 csio->dxfer_len, 412 csio->tag_action & 0xf, 413 ((csio->ccb_h.flags & CAM_DIR_MASK) == 414 CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 415 (csio->ccb_h.flags & CAM_DIR_OUT) ? 416 DEVSTAT_WRITE : DEVSTAT_READ, 417 NULL, NULL); 418 419 rdwr = done_ccb->ccb_h.ccb_rdwr; 420 state = rdwr->state; 421 rdwr->state = SG_RDWR_DONE; 422 wakeup(rdwr); 423 break; 424 } 425 default: 426 panic("unknown sg CCB type"); 427 } 428 } 429 430 static int 431 sgopen(struct cdev *dev, int flags, int fmt, struct thread *td) 432 { 433 struct cam_periph *periph; 434 struct sg_softc *softc; 435 int error = 0; 436 437 periph = (struct cam_periph *)dev->si_drv1; 438 if (cam_periph_acquire(periph) != 0) 439 return (ENXIO); 440 441 /* 442 * Don't allow access when we're running at a high securelevel. 443 */ 444 error = securelevel_gt(td->td_ucred, 1); 445 if (error) { 446 cam_periph_release(periph); 447 return (error); 448 } 449 450 cam_periph_lock(periph); 451 452 softc = (struct sg_softc *)periph->softc; 453 if (softc->flags & SG_FLAG_INVALID) { 454 cam_periph_release_locked(periph); 455 cam_periph_unlock(periph); 456 return (ENXIO); 457 } 458 459 softc->open_count++; 460 461 cam_periph_unlock(periph); 462 463 return (error); 464 } 465 466 static int 467 sgclose(struct cdev *dev, int flag, int fmt, struct thread *td) 468 { 469 struct cam_periph *periph; 470 struct sg_softc *softc; 471 struct mtx *mtx; 472 473 periph = (struct cam_periph *)dev->si_drv1; 474 mtx = cam_periph_mtx(periph); 475 mtx_lock(mtx); 476 477 softc = periph->softc; 478 softc->open_count--; 479 480 cam_periph_release_locked(periph); 481 482 /* 483 * We reference the lock directly here, instead of using 484 * cam_periph_unlock(). The reason is that the call to 485 * cam_periph_release_locked() above could result in the periph 486 * getting freed. If that is the case, dereferencing the periph 487 * with a cam_periph_unlock() call would cause a page fault. 488 * 489 * cam_periph_release() avoids this problem using the same method, 490 * but we're manually acquiring and dropping the lock here to 491 * protect the open count and avoid another lock acquisition and 492 * release. 493 */ 494 mtx_unlock(mtx); 495 496 return (0); 497 } 498 499 static int 500 sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 501 { 502 union ccb *ccb; 503 struct ccb_scsiio *csio; 504 struct cam_periph *periph; 505 struct sg_softc *softc; 506 struct sg_io_hdr *req; 507 int dir, error; 508 509 periph = (struct cam_periph *)dev->si_drv1; 510 cam_periph_lock(periph); 511 512 softc = (struct sg_softc *)periph->softc; 513 error = 0; 514 515 switch (cmd) { 516 case SG_GET_VERSION_NUM: 517 { 518 int *version = (int *)arg; 519 520 *version = sg_version; 521 break; 522 } 523 case SG_SET_TIMEOUT: 524 { 525 u_int user_timeout = *(u_int *)arg; 526 527 softc->sg_user_timeout = user_timeout; 528 softc->sg_timeout = user_timeout / SG_DEFAULT_HZ * hz; 529 break; 530 } 531 case SG_GET_TIMEOUT: 532 /* 533 * The value is returned directly to the syscall. 534 */ 535 td->td_retval[0] = softc->sg_user_timeout; 536 error = 0; 537 break; 538 case SG_IO: 539 req = (struct sg_io_hdr *)arg; 540 541 if (req->cmd_len > IOCDBLEN) { 542 error = EINVAL; 543 break; 544 } 545 546 if (req->iovec_count != 0) { 547 error = EOPNOTSUPP; 548 break; 549 } 550 551 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 552 csio = &ccb->csio; 553 554 error = copyin(req->cmdp, &csio->cdb_io.cdb_bytes, 555 req->cmd_len); 556 if (error) { 557 xpt_release_ccb(ccb); 558 break; 559 } 560 561 switch(req->dxfer_direction) { 562 case SG_DXFER_TO_DEV: 563 dir = CAM_DIR_OUT; 564 break; 565 case SG_DXFER_FROM_DEV: 566 dir = CAM_DIR_IN; 567 break; 568 case SG_DXFER_TO_FROM_DEV: 569 dir = CAM_DIR_BOTH; 570 break; 571 case SG_DXFER_NONE: 572 default: 573 dir = CAM_DIR_NONE; 574 break; 575 } 576 577 cam_fill_csio(csio, 578 /*retries*/1, 579 /*cbfcnp*/NULL, 580 dir|CAM_DEV_QFRZDIS, 581 MSG_SIMPLE_Q_TAG, 582 req->dxferp, 583 req->dxfer_len, 584 req->mx_sb_len, 585 req->cmd_len, 586 req->timeout); 587 588 error = sgsendccb(periph, ccb); 589 if (error) { 590 req->host_status = DID_ERROR; 591 req->driver_status = DRIVER_INVALID; 592 xpt_release_ccb(ccb); 593 break; 594 } 595 596 req->status = csio->scsi_status; 597 req->masked_status = (csio->scsi_status >> 1) & 0x7f; 598 sg_scsiio_status(csio, &req->host_status, &req->driver_status); 599 req->resid = csio->resid; 600 req->duration = csio->ccb_h.timeout; 601 req->info = 0; 602 603 if ((csio->ccb_h.status & CAM_AUTOSNS_VALID) 604 && (req->sbp != NULL)) { 605 req->sb_len_wr = req->mx_sb_len - csio->sense_resid; 606 error = copyout(&csio->sense_data, req->sbp, 607 req->sb_len_wr); 608 } 609 610 xpt_release_ccb(ccb); 611 break; 612 613 case SG_GET_RESERVED_SIZE: 614 { 615 int *size = (int *)arg; 616 *size = DFLTPHYS; 617 break; 618 } 619 620 case SG_GET_SCSI_ID: 621 { 622 struct sg_scsi_id *id = (struct sg_scsi_id *)arg; 623 624 id->host_no = cam_sim_path(xpt_path_sim(periph->path)); 625 id->channel = xpt_path_path_id(periph->path); 626 id->scsi_id = xpt_path_target_id(periph->path); 627 id->lun = xpt_path_lun_id(periph->path); 628 id->scsi_type = softc->pd_type; 629 id->h_cmd_per_lun = 1; 630 id->d_queue_depth = 1; 631 id->unused[0] = 0; 632 id->unused[1] = 0; 633 break; 634 } 635 636 case SG_GET_SG_TABLESIZE: 637 { 638 int *size = (int *)arg; 639 *size = 0; 640 break; 641 } 642 643 case SG_EMULATED_HOST: 644 case SG_SET_TRANSFORM: 645 case SG_GET_TRANSFORM: 646 case SG_GET_NUM_WAITING: 647 case SG_SCSI_RESET: 648 case SG_GET_REQUEST_TABLE: 649 case SG_SET_KEEP_ORPHAN: 650 case SG_GET_KEEP_ORPHAN: 651 case SG_GET_ACCESS_COUNT: 652 case SG_SET_FORCE_LOW_DMA: 653 case SG_GET_LOW_DMA: 654 case SG_SET_FORCE_PACK_ID: 655 case SG_GET_PACK_ID: 656 case SG_SET_RESERVED_SIZE: 657 case SG_GET_COMMAND_Q: 658 case SG_SET_COMMAND_Q: 659 case SG_SET_DEBUG: 660 case SG_NEXT_CMD_LEN: 661 default: 662 #ifdef CAMDEBUG 663 printf("sgioctl: rejecting cmd 0x%lx\n", cmd); 664 #endif 665 error = ENODEV; 666 break; 667 } 668 669 cam_periph_unlock(periph); 670 return (error); 671 } 672 673 static int 674 sgwrite(struct cdev *dev, struct uio *uio, int ioflag) 675 { 676 union ccb *ccb; 677 struct cam_periph *periph; 678 struct ccb_scsiio *csio; 679 struct sg_softc *sc; 680 struct sg_header *hdr; 681 struct sg_rdwr *rdwr; 682 u_char cdb_cmd; 683 char *buf; 684 int error = 0, cdb_len, buf_len, dir; 685 686 periph = dev->si_drv1; 687 rdwr = malloc(sizeof(*rdwr), M_DEVBUF, M_WAITOK | M_ZERO); 688 hdr = &rdwr->hdr.hdr; 689 690 /* Copy in the header block and sanity check it */ 691 if (uio->uio_resid < sizeof(*hdr)) { 692 error = EINVAL; 693 goto out_hdr; 694 } 695 error = uiomove(hdr, sizeof(*hdr), uio); 696 if (error) 697 goto out_hdr; 698 699 /* XXX: We don't support SG 3.x read/write API. */ 700 if (hdr->reply_len < 0) { 701 error = ENODEV; 702 goto out_hdr; 703 } 704 705 ccb = xpt_alloc_ccb(); 706 if (ccb == NULL) { 707 error = ENOMEM; 708 goto out_hdr; 709 } 710 csio = &ccb->csio; 711 712 /* 713 * Copy in the CDB block. The designers of the interface didn't 714 * bother to provide a size for this in the header, so we have to 715 * figure it out ourselves. 716 */ 717 if (uio->uio_resid < 1) 718 goto out_ccb; 719 error = uiomove(&cdb_cmd, 1, uio); 720 if (error) 721 goto out_ccb; 722 if (hdr->twelve_byte) 723 cdb_len = 12; 724 else 725 cdb_len = scsi_group_len(cdb_cmd); 726 /* 727 * We've already read the first byte of the CDB and advanced the uio 728 * pointer. Just read the rest. 729 */ 730 csio->cdb_io.cdb_bytes[0] = cdb_cmd; 731 error = uiomove(&csio->cdb_io.cdb_bytes[1], cdb_len - 1, uio); 732 if (error) 733 goto out_ccb; 734 735 /* 736 * Now set up the data block. Again, the designers didn't bother 737 * to make this reliable. 738 */ 739 buf_len = uio->uio_resid; 740 if (buf_len != 0) { 741 buf = malloc(buf_len, M_DEVBUF, M_WAITOK | M_ZERO); 742 error = uiomove(buf, buf_len, uio); 743 if (error) 744 goto out_buf; 745 dir = CAM_DIR_OUT; 746 } else if (hdr->reply_len != 0) { 747 buf = malloc(hdr->reply_len, M_DEVBUF, M_WAITOK | M_ZERO); 748 buf_len = hdr->reply_len; 749 dir = CAM_DIR_IN; 750 } else { 751 buf = NULL; 752 buf_len = 0; 753 dir = CAM_DIR_NONE; 754 } 755 756 cam_periph_lock(periph); 757 sc = periph->softc; 758 xpt_setup_ccb(&ccb->ccb_h, periph->path, CAM_PRIORITY_NORMAL); 759 cam_fill_csio(csio, 760 /*retries*/1, 761 sgdone, 762 dir|CAM_DEV_QFRZDIS, 763 MSG_SIMPLE_Q_TAG, 764 buf, 765 buf_len, 766 SG_MAX_SENSE, 767 cdb_len, 768 sc->sg_timeout); 769 770 /* 771 * Send off the command and hope that it works. This path does not 772 * go through sgstart because the I/O is supposed to be asynchronous. 773 */ 774 rdwr->buf = buf; 775 rdwr->buf_len = buf_len; 776 rdwr->tag = hdr->pack_id; 777 rdwr->ccb = ccb; 778 rdwr->state = SG_RDWR_INPROG; 779 ccb->ccb_h.ccb_rdwr = rdwr; 780 ccb->ccb_h.ccb_type = SG_CCB_RDWR_IO; 781 TAILQ_INSERT_TAIL(&sc->rdwr_done, rdwr, rdwr_link); 782 error = sgsendrdwr(periph, ccb); 783 cam_periph_unlock(periph); 784 return (error); 785 786 out_buf: 787 free(buf, M_DEVBUF); 788 out_ccb: 789 xpt_free_ccb(ccb); 790 out_hdr: 791 free(rdwr, M_DEVBUF); 792 return (error); 793 } 794 795 static int 796 sgread(struct cdev *dev, struct uio *uio, int ioflag) 797 { 798 struct ccb_scsiio *csio; 799 struct cam_periph *periph; 800 struct sg_softc *sc; 801 struct sg_header *hdr; 802 struct sg_rdwr *rdwr; 803 u_short hstat, dstat; 804 int error, pack_len, reply_len, pack_id; 805 806 periph = dev->si_drv1; 807 808 /* XXX The pack len field needs to be updated and written out instead 809 * of discarded. Not sure how to do that. 810 */ 811 uio->uio_rw = UIO_WRITE; 812 if ((error = uiomove(&pack_len, 4, uio)) != 0) 813 return (error); 814 if ((error = uiomove(&reply_len, 4, uio)) != 0) 815 return (error); 816 if ((error = uiomove(&pack_id, 4, uio)) != 0) 817 return (error); 818 uio->uio_rw = UIO_READ; 819 820 cam_periph_lock(periph); 821 sc = periph->softc; 822 search: 823 TAILQ_FOREACH(rdwr, &sc->rdwr_done, rdwr_link) { 824 if (rdwr->tag == pack_id) 825 break; 826 } 827 if ((rdwr == NULL) || (rdwr->state != SG_RDWR_DONE)) { 828 if (cam_periph_sleep(periph, rdwr, PCATCH, "sgread", 0) == ERESTART) 829 return (EAGAIN); 830 goto search; 831 } 832 TAILQ_REMOVE(&sc->rdwr_done, rdwr, rdwr_link); 833 cam_periph_unlock(periph); 834 835 hdr = &rdwr->hdr.hdr; 836 csio = &rdwr->ccb->csio; 837 sg_scsiio_status(csio, &hstat, &dstat); 838 hdr->host_status = hstat; 839 hdr->driver_status = dstat; 840 hdr->target_status = csio->scsi_status >> 1; 841 842 switch (hstat) { 843 case DID_OK: 844 case DID_PASSTHROUGH: 845 case DID_SOFT_ERROR: 846 hdr->result = 0; 847 break; 848 case DID_NO_CONNECT: 849 case DID_BUS_BUSY: 850 case DID_TIME_OUT: 851 hdr->result = EBUSY; 852 break; 853 case DID_BAD_TARGET: 854 case DID_ABORT: 855 case DID_PARITY: 856 case DID_RESET: 857 case DID_BAD_INTR: 858 case DID_ERROR: 859 default: 860 hdr->result = EIO; 861 break; 862 } 863 864 if (dstat == DRIVER_SENSE) { 865 bcopy(&csio->sense_data, hdr->sense_buffer, 866 min(csio->sense_len, SG_MAX_SENSE)); 867 #ifdef CAMDEBUG 868 scsi_sense_print(csio); 869 #endif 870 } 871 872 error = uiomove(&hdr->result, sizeof(*hdr) - 873 offsetof(struct sg_header, result), uio); 874 if ((error == 0) && (hdr->result == 0)) 875 error = uiomove(rdwr->buf, rdwr->buf_len, uio); 876 877 cam_periph_lock(periph); 878 xpt_free_ccb(rdwr->ccb); 879 cam_periph_unlock(periph); 880 free(rdwr->buf, M_DEVBUF); 881 free(rdwr, M_DEVBUF); 882 return (error); 883 } 884 885 static int 886 sgsendccb(struct cam_periph *periph, union ccb *ccb) 887 { 888 struct sg_softc *softc; 889 struct cam_periph_map_info mapinfo; 890 int error; 891 892 softc = periph->softc; 893 bzero(&mapinfo, sizeof(mapinfo)); 894 895 /* 896 * cam_periph_mapmem calls into proc and vm functions that can 897 * sleep as well as trigger I/O, so we can't hold the lock. 898 * Dropping it here is reasonably safe. 899 * The only CCB opcode that is possible here is XPT_SCSI_IO, no 900 * need for additional checks. 901 */ 902 cam_periph_unlock(periph); 903 error = cam_periph_mapmem(ccb, &mapinfo, softc->maxio); 904 cam_periph_lock(periph); 905 if (error) 906 return (error); 907 908 error = cam_periph_runccb(ccb, 909 sgerror, 910 CAM_RETRY_SELTO, 911 SF_RETRY_UA, 912 softc->device_stats); 913 914 cam_periph_unlock(periph); 915 cam_periph_unmapmem(ccb, &mapinfo); 916 cam_periph_lock(periph); 917 918 return (error); 919 } 920 921 static int 922 sgsendrdwr(struct cam_periph *periph, union ccb *ccb) 923 { 924 struct sg_softc *softc; 925 926 softc = periph->softc; 927 devstat_start_transaction(softc->device_stats, NULL); 928 xpt_action(ccb); 929 return (0); 930 } 931 932 static int 933 sgerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags) 934 { 935 struct cam_periph *periph; 936 struct sg_softc *softc; 937 938 periph = xpt_path_periph(ccb->ccb_h.path); 939 softc = (struct sg_softc *)periph->softc; 940 941 return (cam_periph_error(ccb, cam_flags, sense_flags)); 942 } 943 944 static void 945 sg_scsiio_status(struct ccb_scsiio *csio, u_short *hoststat, u_short *drvstat) 946 { 947 int status; 948 949 status = csio->ccb_h.status; 950 951 switch (status & CAM_STATUS_MASK) { 952 case CAM_REQ_CMP: 953 *hoststat = DID_OK; 954 *drvstat = 0; 955 break; 956 case CAM_REQ_CMP_ERR: 957 *hoststat = DID_ERROR; 958 *drvstat = 0; 959 break; 960 case CAM_REQ_ABORTED: 961 *hoststat = DID_ABORT; 962 *drvstat = 0; 963 break; 964 case CAM_REQ_INVALID: 965 *hoststat = DID_ERROR; 966 *drvstat = DRIVER_INVALID; 967 break; 968 case CAM_DEV_NOT_THERE: 969 *hoststat = DID_BAD_TARGET; 970 *drvstat = 0; 971 break; 972 case CAM_SEL_TIMEOUT: 973 *hoststat = DID_NO_CONNECT; 974 *drvstat = 0; 975 break; 976 case CAM_CMD_TIMEOUT: 977 *hoststat = DID_TIME_OUT; 978 *drvstat = 0; 979 break; 980 case CAM_SCSI_STATUS_ERROR: 981 *hoststat = DID_ERROR; 982 *drvstat = 0; 983 break; 984 case CAM_SCSI_BUS_RESET: 985 *hoststat = DID_RESET; 986 *drvstat = 0; 987 break; 988 case CAM_UNCOR_PARITY: 989 *hoststat = DID_PARITY; 990 *drvstat = 0; 991 break; 992 case CAM_SCSI_BUSY: 993 *hoststat = DID_BUS_BUSY; 994 *drvstat = 0; 995 break; 996 default: 997 *hoststat = DID_ERROR; 998 *drvstat = DRIVER_ERROR; 999 } 1000 1001 if (status & CAM_AUTOSNS_VALID) 1002 *drvstat = DRIVER_SENSE; 1003 } 1004 1005 static int 1006 scsi_group_len(u_char cmd) 1007 { 1008 int len[] = {6, 10, 10, 12, 12, 12, 10, 10}; 1009 int group; 1010 1011 group = (cmd >> 5) & 0x7; 1012 return (len[group]); 1013 } 1014