1 /*- 2 * Copyright (c) 2007 Scott Long 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. The name of the author may not be used to endorse or promote products 12 * derived from this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * scsi_sg peripheral driver. This driver is meant to implement the Linux 29 * SG passthrough interface for SCSI. 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/types.h> 39 #include <sys/bio.h> 40 #include <sys/malloc.h> 41 #include <sys/fcntl.h> 42 #include <sys/ioccom.h> 43 #include <sys/conf.h> 44 #include <sys/errno.h> 45 #include <sys/devicestat.h> 46 #include <sys/proc.h> 47 #include <sys/uio.h> 48 49 #include <cam/cam.h> 50 #include <cam/cam_ccb.h> 51 #include <cam/cam_periph.h> 52 #include <cam/cam_queue.h> 53 #include <cam/cam_xpt_periph.h> 54 #include <cam/cam_debug.h> 55 #include <cam/cam_sim.h> 56 57 #include <cam/scsi/scsi_all.h> 58 #include <cam/scsi/scsi_message.h> 59 #include <cam/scsi/scsi_sg.h> 60 61 #include <compat/linux/linux_ioctl.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_NEEDGIANT | 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 213 static void 214 sgoninvalidate(struct cam_periph *periph) 215 { 216 struct sg_softc *softc; 217 218 softc = (struct sg_softc *)periph->softc; 219 220 /* 221 * Deregister any async callbacks. 222 */ 223 xpt_register_async(0, sgasync, periph, periph->path); 224 225 softc->flags |= SG_FLAG_INVALID; 226 227 /* 228 * Tell devfs this device has gone away, and ask for a callback 229 * when it has cleaned up its state. 230 */ 231 destroy_dev_sched_cb(softc->dev, sgdevgonecb, periph); 232 233 /* 234 * XXX Return all queued I/O with ENXIO. 235 * XXX Handle any transactions queued to the card 236 * with XPT_ABORT_CCB. 237 */ 238 239 } 240 241 static void 242 sgcleanup(struct cam_periph *periph) 243 { 244 struct sg_softc *softc; 245 246 softc = (struct sg_softc *)periph->softc; 247 248 devstat_remove_entry(softc->device_stats); 249 250 free(softc, M_DEVBUF); 251 } 252 253 static void 254 sgasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 255 { 256 struct cam_periph *periph; 257 258 periph = (struct cam_periph *)callback_arg; 259 260 switch (code) { 261 case AC_FOUND_DEVICE: 262 { 263 struct ccb_getdev *cgd; 264 cam_status status; 265 266 cgd = (struct ccb_getdev *)arg; 267 if (cgd == NULL) 268 break; 269 270 if (cgd->protocol != PROTO_SCSI) 271 break; 272 273 /* 274 * Allocate a peripheral instance for this device and 275 * start the probe process. 276 */ 277 status = cam_periph_alloc(sgregister, sgoninvalidate, 278 sgcleanup, NULL, "sg", 279 CAM_PERIPH_BIO, path, 280 sgasync, AC_FOUND_DEVICE, cgd); 281 if ((status != CAM_REQ_CMP) && (status != CAM_REQ_INPROG)) { 282 const struct cam_status_entry *entry; 283 284 entry = cam_fetch_status_entry(status); 285 printf("sgasync: Unable to attach new device " 286 "due to status %#x: %s\n", status, entry ? 287 entry->status_text : "Unknown"); 288 } 289 break; 290 } 291 default: 292 cam_periph_async(periph, code, path, arg); 293 break; 294 } 295 } 296 297 static cam_status 298 sgregister(struct cam_periph *periph, void *arg) 299 { 300 struct sg_softc *softc; 301 struct ccb_getdev *cgd; 302 struct ccb_pathinq cpi; 303 struct make_dev_args args; 304 int no_tags, error; 305 306 cgd = (struct ccb_getdev *)arg; 307 if (cgd == NULL) { 308 printf("sgregister: no getdev CCB, can't register device\n"); 309 return (CAM_REQ_CMP_ERR); 310 } 311 312 softc = malloc(sizeof(*softc), M_DEVBUF, M_ZERO | M_NOWAIT); 313 if (softc == NULL) { 314 printf("sgregister: Unable to allocate softc\n"); 315 return (CAM_REQ_CMP_ERR); 316 } 317 318 softc->state = SG_STATE_NORMAL; 319 softc->pd_type = SID_TYPE(&cgd->inq_data); 320 softc->sg_timeout = SG_DEFAULT_TIMEOUT / SG_DEFAULT_HZ * hz; 321 softc->sg_user_timeout = SG_DEFAULT_TIMEOUT; 322 TAILQ_INIT(&softc->rdwr_done); 323 periph->softc = softc; 324 325 bzero(&cpi, sizeof(cpi)); 326 xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 327 cpi.ccb_h.func_code = XPT_PATH_INQ; 328 xpt_action((union ccb *)&cpi); 329 330 if (cpi.maxio == 0) 331 softc->maxio = DFLTPHYS; /* traditional default */ 332 else if (cpi.maxio > MAXPHYS) 333 softc->maxio = MAXPHYS; /* for safety */ 334 else 335 softc->maxio = cpi.maxio; /* real value */ 336 337 /* 338 * We pass in 0 for all blocksize, since we don't know what the 339 * blocksize of the device is, if it even has a blocksize. 340 */ 341 cam_periph_unlock(periph); 342 no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; 343 softc->device_stats = devstat_new_entry("sg", 344 periph->unit_number, 0, 345 DEVSTAT_NO_BLOCKSIZE 346 | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0), 347 softc->pd_type | 348 XPORT_DEVSTAT_TYPE(cpi.transport) | 349 DEVSTAT_TYPE_PASS, 350 DEVSTAT_PRIORITY_PASS); 351 352 /* 353 * Acquire a reference to the periph before we create the devfs 354 * instance for it. We'll release this reference once the devfs 355 * instance has been freed. 356 */ 357 if (cam_periph_acquire(periph) != CAM_REQ_CMP) { 358 xpt_print(periph->path, "%s: lost periph during " 359 "registration!\n", __func__); 360 cam_periph_lock(periph); 361 return (CAM_REQ_CMP_ERR); 362 } 363 364 /* Register the device */ 365 make_dev_args_init(&args); 366 args.mda_devsw = &sg_cdevsw; 367 args.mda_unit = periph->unit_number; 368 args.mda_uid = UID_ROOT; 369 args.mda_gid = GID_OPERATOR; 370 args.mda_mode = 0600; 371 args.mda_si_drv1 = periph; 372 error = make_dev_s(&args, &softc->dev, "%s%d", 373 periph->periph_name, periph->unit_number); 374 if (error != 0) { 375 cam_periph_lock(periph); 376 cam_periph_release_locked(periph); 377 return (CAM_REQ_CMP_ERR); 378 } 379 if (periph->unit_number < 26) { 380 (void)make_dev_alias(softc->dev, "sg%c", 381 periph->unit_number + 'a'); 382 } else { 383 (void)make_dev_alias(softc->dev, "sg%c%c", 384 ((periph->unit_number / 26) - 1) + 'a', 385 (periph->unit_number % 26) + 'a'); 386 } 387 cam_periph_lock(periph); 388 389 /* 390 * Add as async callback so that we get 391 * notified if this device goes away. 392 */ 393 xpt_register_async(AC_LOST_DEVICE, sgasync, periph, periph->path); 394 395 if (bootverbose) 396 xpt_announce_periph(periph, NULL); 397 398 return (CAM_REQ_CMP); 399 } 400 401 static void 402 sgdone(struct cam_periph *periph, union ccb *done_ccb) 403 { 404 struct sg_softc *softc; 405 struct ccb_scsiio *csio; 406 407 softc = (struct sg_softc *)periph->softc; 408 csio = &done_ccb->csio; 409 switch (csio->ccb_h.ccb_type) { 410 case SG_CCB_RDWR_IO: 411 { 412 struct sg_rdwr *rdwr; 413 int state; 414 415 devstat_end_transaction(softc->device_stats, 416 csio->dxfer_len, 417 csio->tag_action & 0xf, 418 ((csio->ccb_h.flags & CAM_DIR_MASK) == 419 CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 420 (csio->ccb_h.flags & CAM_DIR_OUT) ? 421 DEVSTAT_WRITE : DEVSTAT_READ, 422 NULL, NULL); 423 424 rdwr = done_ccb->ccb_h.ccb_rdwr; 425 state = rdwr->state; 426 rdwr->state = SG_RDWR_DONE; 427 wakeup(rdwr); 428 break; 429 } 430 default: 431 panic("unknown sg CCB type"); 432 } 433 } 434 435 static int 436 sgopen(struct cdev *dev, int flags, int fmt, struct thread *td) 437 { 438 struct cam_periph *periph; 439 struct sg_softc *softc; 440 int error = 0; 441 442 periph = (struct cam_periph *)dev->si_drv1; 443 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 444 return (ENXIO); 445 446 /* 447 * Don't allow access when we're running at a high securelevel. 448 */ 449 error = securelevel_gt(td->td_ucred, 1); 450 if (error) { 451 cam_periph_release(periph); 452 return (error); 453 } 454 455 cam_periph_lock(periph); 456 457 softc = (struct sg_softc *)periph->softc; 458 if (softc->flags & SG_FLAG_INVALID) { 459 cam_periph_release_locked(periph); 460 cam_periph_unlock(periph); 461 return (ENXIO); 462 } 463 464 softc->open_count++; 465 466 cam_periph_unlock(periph); 467 468 return (error); 469 } 470 471 static int 472 sgclose(struct cdev *dev, int flag, int fmt, struct thread *td) 473 { 474 struct cam_periph *periph; 475 struct sg_softc *softc; 476 struct mtx *mtx; 477 478 periph = (struct cam_periph *)dev->si_drv1; 479 mtx = cam_periph_mtx(periph); 480 mtx_lock(mtx); 481 482 softc = periph->softc; 483 softc->open_count--; 484 485 cam_periph_release_locked(periph); 486 487 /* 488 * We reference the lock directly here, instead of using 489 * cam_periph_unlock(). The reason is that the call to 490 * cam_periph_release_locked() above could result in the periph 491 * getting freed. If that is the case, dereferencing the periph 492 * with a cam_periph_unlock() call would cause a page fault. 493 * 494 * cam_periph_release() avoids this problem using the same method, 495 * but we're manually acquiring and dropping the lock here to 496 * protect the open count and avoid another lock acquisition and 497 * release. 498 */ 499 mtx_unlock(mtx); 500 501 return (0); 502 } 503 504 static int 505 sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 506 { 507 union ccb *ccb; 508 struct ccb_scsiio *csio; 509 struct cam_periph *periph; 510 struct sg_softc *softc; 511 struct sg_io_hdr *req; 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 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 557 csio = &ccb->csio; 558 559 error = copyin(req->cmdp, &csio->cdb_io.cdb_bytes, 560 req->cmd_len); 561 if (error) { 562 xpt_release_ccb(ccb); 563 break; 564 } 565 566 switch(req->dxfer_direction) { 567 case SG_DXFER_TO_DEV: 568 dir = CAM_DIR_OUT; 569 break; 570 case SG_DXFER_FROM_DEV: 571 dir = CAM_DIR_IN; 572 break; 573 case SG_DXFER_TO_FROM_DEV: 574 dir = CAM_DIR_IN | CAM_DIR_OUT; 575 break; 576 case SG_DXFER_NONE: 577 default: 578 dir = CAM_DIR_NONE; 579 break; 580 } 581 582 cam_fill_csio(csio, 583 /*retries*/1, 584 sgdone, 585 dir|CAM_DEV_QFRZDIS, 586 MSG_SIMPLE_Q_TAG, 587 req->dxferp, 588 req->dxfer_len, 589 req->mx_sb_len, 590 req->cmd_len, 591 req->timeout); 592 593 error = sgsendccb(periph, ccb); 594 if (error) { 595 req->host_status = DID_ERROR; 596 req->driver_status = DRIVER_INVALID; 597 xpt_release_ccb(ccb); 598 break; 599 } 600 601 req->status = csio->scsi_status; 602 req->masked_status = (csio->scsi_status >> 1) & 0x7f; 603 sg_scsiio_status(csio, &req->host_status, &req->driver_status); 604 req->resid = csio->resid; 605 req->duration = csio->ccb_h.timeout; 606 req->info = 0; 607 608 if ((csio->ccb_h.status & CAM_AUTOSNS_VALID) 609 && (req->sbp != NULL)) { 610 req->sb_len_wr = req->mx_sb_len - csio->sense_resid; 611 error = copyout(&csio->sense_data, req->sbp, 612 req->sb_len_wr); 613 } 614 615 xpt_release_ccb(ccb); 616 break; 617 618 case SG_GET_RESERVED_SIZE: 619 { 620 int *size = (int *)arg; 621 *size = DFLTPHYS; 622 break; 623 } 624 625 case SG_GET_SCSI_ID: 626 { 627 struct sg_scsi_id *id = (struct sg_scsi_id *)arg; 628 629 id->host_no = cam_sim_path(xpt_path_sim(periph->path)); 630 id->channel = xpt_path_path_id(periph->path); 631 id->scsi_id = xpt_path_target_id(periph->path); 632 id->lun = xpt_path_lun_id(periph->path); 633 id->scsi_type = softc->pd_type; 634 id->h_cmd_per_lun = 1; 635 id->d_queue_depth = 1; 636 id->unused[0] = 0; 637 id->unused[1] = 0; 638 break; 639 } 640 641 case SG_GET_SG_TABLESIZE: 642 { 643 int *size = (int *)arg; 644 *size = 0; 645 break; 646 } 647 648 case SG_EMULATED_HOST: 649 case SG_SET_TRANSFORM: 650 case SG_GET_TRANSFORM: 651 case SG_GET_NUM_WAITING: 652 case SG_SCSI_RESET: 653 case SG_GET_REQUEST_TABLE: 654 case SG_SET_KEEP_ORPHAN: 655 case SG_GET_KEEP_ORPHAN: 656 case SG_GET_ACCESS_COUNT: 657 case SG_SET_FORCE_LOW_DMA: 658 case SG_GET_LOW_DMA: 659 case SG_SET_FORCE_PACK_ID: 660 case SG_GET_PACK_ID: 661 case SG_SET_RESERVED_SIZE: 662 case SG_GET_COMMAND_Q: 663 case SG_SET_COMMAND_Q: 664 case SG_SET_DEBUG: 665 case SG_NEXT_CMD_LEN: 666 default: 667 #ifdef CAMDEBUG 668 printf("sgioctl: rejecting cmd 0x%lx\n", cmd); 669 #endif 670 error = ENODEV; 671 break; 672 } 673 674 cam_periph_unlock(periph); 675 return (error); 676 } 677 678 static int 679 sgwrite(struct cdev *dev, struct uio *uio, int ioflag) 680 { 681 union ccb *ccb; 682 struct cam_periph *periph; 683 struct ccb_scsiio *csio; 684 struct sg_softc *sc; 685 struct sg_header *hdr; 686 struct sg_rdwr *rdwr; 687 u_char cdb_cmd; 688 char *buf; 689 int error = 0, cdb_len, buf_len, dir; 690 691 periph = dev->si_drv1; 692 rdwr = malloc(sizeof(*rdwr), M_DEVBUF, M_WAITOK | M_ZERO); 693 hdr = &rdwr->hdr.hdr; 694 695 /* Copy in the header block and sanity check it */ 696 if (uio->uio_resid < sizeof(*hdr)) { 697 error = EINVAL; 698 goto out_hdr; 699 } 700 error = uiomove(hdr, sizeof(*hdr), uio); 701 if (error) 702 goto out_hdr; 703 704 /* XXX: We don't support SG 3.x read/write API. */ 705 if (hdr->reply_len < 0) { 706 error = ENODEV; 707 goto out_hdr; 708 } 709 710 ccb = xpt_alloc_ccb(); 711 if (ccb == NULL) { 712 error = ENOMEM; 713 goto out_hdr; 714 } 715 csio = &ccb->csio; 716 717 /* 718 * Copy in the CDB block. The designers of the interface didn't 719 * bother to provide a size for this in the header, so we have to 720 * figure it out ourselves. 721 */ 722 if (uio->uio_resid < 1) 723 goto out_ccb; 724 error = uiomove(&cdb_cmd, 1, uio); 725 if (error) 726 goto out_ccb; 727 if (hdr->twelve_byte) 728 cdb_len = 12; 729 else 730 cdb_len = scsi_group_len(cdb_cmd); 731 /* 732 * We've already read the first byte of the CDB and advanced the uio 733 * pointer. Just read the rest. 734 */ 735 csio->cdb_io.cdb_bytes[0] = cdb_cmd; 736 error = uiomove(&csio->cdb_io.cdb_bytes[1], cdb_len - 1, uio); 737 if (error) 738 goto out_ccb; 739 740 /* 741 * Now set up the data block. Again, the designers didn't bother 742 * to make this reliable. 743 */ 744 buf_len = uio->uio_resid; 745 if (buf_len != 0) { 746 buf = malloc(buf_len, M_DEVBUF, M_WAITOK | M_ZERO); 747 error = uiomove(buf, buf_len, uio); 748 if (error) 749 goto out_buf; 750 dir = CAM_DIR_OUT; 751 } else if (hdr->reply_len != 0) { 752 buf = malloc(hdr->reply_len, M_DEVBUF, M_WAITOK | M_ZERO); 753 buf_len = hdr->reply_len; 754 dir = CAM_DIR_IN; 755 } else { 756 buf = NULL; 757 buf_len = 0; 758 dir = CAM_DIR_NONE; 759 } 760 761 cam_periph_lock(periph); 762 sc = periph->softc; 763 xpt_setup_ccb(&ccb->ccb_h, periph->path, CAM_PRIORITY_NORMAL); 764 cam_fill_csio(csio, 765 /*retries*/1, 766 sgdone, 767 dir|CAM_DEV_QFRZDIS, 768 MSG_SIMPLE_Q_TAG, 769 buf, 770 buf_len, 771 SG_MAX_SENSE, 772 cdb_len, 773 sc->sg_timeout); 774 775 /* 776 * Send off the command and hope that it works. This path does not 777 * go through sgstart because the I/O is supposed to be asynchronous. 778 */ 779 rdwr->buf = buf; 780 rdwr->buf_len = buf_len; 781 rdwr->tag = hdr->pack_id; 782 rdwr->ccb = ccb; 783 rdwr->state = SG_RDWR_INPROG; 784 ccb->ccb_h.ccb_rdwr = rdwr; 785 ccb->ccb_h.ccb_type = SG_CCB_RDWR_IO; 786 TAILQ_INSERT_TAIL(&sc->rdwr_done, rdwr, rdwr_link); 787 error = sgsendrdwr(periph, ccb); 788 cam_periph_unlock(periph); 789 return (error); 790 791 out_buf: 792 free(buf, M_DEVBUF); 793 out_ccb: 794 xpt_free_ccb(ccb); 795 out_hdr: 796 free(rdwr, M_DEVBUF); 797 return (error); 798 } 799 800 static int 801 sgread(struct cdev *dev, struct uio *uio, int ioflag) 802 { 803 struct ccb_scsiio *csio; 804 struct cam_periph *periph; 805 struct sg_softc *sc; 806 struct sg_header *hdr; 807 struct sg_rdwr *rdwr; 808 u_short hstat, dstat; 809 int error, pack_len, reply_len, pack_id; 810 811 periph = dev->si_drv1; 812 813 /* XXX The pack len field needs to be updated and written out instead 814 * of discarded. Not sure how to do that. 815 */ 816 uio->uio_rw = UIO_WRITE; 817 if ((error = uiomove(&pack_len, 4, uio)) != 0) 818 return (error); 819 if ((error = uiomove(&reply_len, 4, uio)) != 0) 820 return (error); 821 if ((error = uiomove(&pack_id, 4, uio)) != 0) 822 return (error); 823 uio->uio_rw = UIO_READ; 824 825 cam_periph_lock(periph); 826 sc = periph->softc; 827 search: 828 TAILQ_FOREACH(rdwr, &sc->rdwr_done, rdwr_link) { 829 if (rdwr->tag == pack_id) 830 break; 831 } 832 if ((rdwr == NULL) || (rdwr->state != SG_RDWR_DONE)) { 833 if (cam_periph_sleep(periph, rdwr, PCATCH, "sgread", 0) == ERESTART) 834 return (EAGAIN); 835 goto search; 836 } 837 TAILQ_REMOVE(&sc->rdwr_done, rdwr, rdwr_link); 838 cam_periph_unlock(periph); 839 840 hdr = &rdwr->hdr.hdr; 841 csio = &rdwr->ccb->csio; 842 sg_scsiio_status(csio, &hstat, &dstat); 843 hdr->host_status = hstat; 844 hdr->driver_status = dstat; 845 hdr->target_status = csio->scsi_status >> 1; 846 847 switch (hstat) { 848 case DID_OK: 849 case DID_PASSTHROUGH: 850 case DID_SOFT_ERROR: 851 hdr->result = 0; 852 break; 853 case DID_NO_CONNECT: 854 case DID_BUS_BUSY: 855 case DID_TIME_OUT: 856 hdr->result = EBUSY; 857 break; 858 case DID_BAD_TARGET: 859 case DID_ABORT: 860 case DID_PARITY: 861 case DID_RESET: 862 case DID_BAD_INTR: 863 case DID_ERROR: 864 default: 865 hdr->result = EIO; 866 break; 867 } 868 869 if (dstat == DRIVER_SENSE) { 870 bcopy(&csio->sense_data, hdr->sense_buffer, 871 min(csio->sense_len, SG_MAX_SENSE)); 872 #ifdef CAMDEBUG 873 scsi_sense_print(csio); 874 #endif 875 } 876 877 error = uiomove(&hdr->result, sizeof(*hdr) - 878 offsetof(struct sg_header, result), uio); 879 if ((error == 0) && (hdr->result == 0)) 880 error = uiomove(rdwr->buf, rdwr->buf_len, uio); 881 882 cam_periph_lock(periph); 883 xpt_free_ccb(rdwr->ccb); 884 cam_periph_unlock(periph); 885 free(rdwr->buf, M_DEVBUF); 886 free(rdwr, M_DEVBUF); 887 return (error); 888 } 889 890 static int 891 sgsendccb(struct cam_periph *periph, union ccb *ccb) 892 { 893 struct sg_softc *softc; 894 struct cam_periph_map_info mapinfo; 895 int error; 896 897 softc = periph->softc; 898 bzero(&mapinfo, sizeof(mapinfo)); 899 900 /* 901 * cam_periph_mapmem calls into proc and vm functions that can 902 * sleep as well as trigger I/O, so we can't hold the lock. 903 * Dropping it here is reasonably safe. 904 * The only CCB opcode that is possible here is XPT_SCSI_IO, no 905 * need for additional checks. 906 */ 907 cam_periph_unlock(periph); 908 error = cam_periph_mapmem(ccb, &mapinfo, softc->maxio); 909 cam_periph_lock(periph); 910 if (error) 911 return (error); 912 913 error = cam_periph_runccb(ccb, 914 sgerror, 915 CAM_RETRY_SELTO, 916 SF_RETRY_UA, 917 softc->device_stats); 918 919 cam_periph_unmapmem(ccb, &mapinfo); 920 921 return (error); 922 } 923 924 static int 925 sgsendrdwr(struct cam_periph *periph, union ccb *ccb) 926 { 927 struct sg_softc *softc; 928 929 softc = periph->softc; 930 devstat_start_transaction(softc->device_stats, NULL); 931 xpt_action(ccb); 932 return (0); 933 } 934 935 static int 936 sgerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags) 937 { 938 struct cam_periph *periph; 939 struct sg_softc *softc; 940 941 periph = xpt_path_periph(ccb->ccb_h.path); 942 softc = (struct sg_softc *)periph->softc; 943 944 return (cam_periph_error(ccb, cam_flags, sense_flags, 945 &softc->saved_ccb)); 946 } 947 948 static void 949 sg_scsiio_status(struct ccb_scsiio *csio, u_short *hoststat, u_short *drvstat) 950 { 951 int status; 952 953 status = csio->ccb_h.status; 954 955 switch (status & CAM_STATUS_MASK) { 956 case CAM_REQ_CMP: 957 *hoststat = DID_OK; 958 *drvstat = 0; 959 break; 960 case CAM_REQ_CMP_ERR: 961 *hoststat = DID_ERROR; 962 *drvstat = 0; 963 break; 964 case CAM_REQ_ABORTED: 965 *hoststat = DID_ABORT; 966 *drvstat = 0; 967 break; 968 case CAM_REQ_INVALID: 969 *hoststat = DID_ERROR; 970 *drvstat = DRIVER_INVALID; 971 break; 972 case CAM_DEV_NOT_THERE: 973 *hoststat = DID_BAD_TARGET; 974 *drvstat = 0; 975 break; 976 case CAM_SEL_TIMEOUT: 977 *hoststat = DID_NO_CONNECT; 978 *drvstat = 0; 979 break; 980 case CAM_CMD_TIMEOUT: 981 *hoststat = DID_TIME_OUT; 982 *drvstat = 0; 983 break; 984 case CAM_SCSI_STATUS_ERROR: 985 *hoststat = DID_ERROR; 986 *drvstat = 0; 987 break; 988 case CAM_SCSI_BUS_RESET: 989 *hoststat = DID_RESET; 990 *drvstat = 0; 991 break; 992 case CAM_UNCOR_PARITY: 993 *hoststat = DID_PARITY; 994 *drvstat = 0; 995 break; 996 case CAM_SCSI_BUSY: 997 *hoststat = DID_BUS_BUSY; 998 *drvstat = 0; 999 break; 1000 default: 1001 *hoststat = DID_ERROR; 1002 *drvstat = DRIVER_ERROR; 1003 } 1004 1005 if (status & CAM_AUTOSNS_VALID) 1006 *drvstat = DRIVER_SENSE; 1007 } 1008 1009 static int 1010 scsi_group_len(u_char cmd) 1011 { 1012 int len[] = {6, 10, 10, 12, 12, 12, 10, 10}; 1013 int group; 1014 1015 group = (cmd >> 5) & 0x7; 1016 return (len[group]); 1017 } 1018 1019