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