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