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_NEEDGIANT | 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 bzero(&cpi, sizeof(cpi)); 328 xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 329 cpi.ccb_h.func_code = XPT_PATH_INQ; 330 xpt_action((union ccb *)&cpi); 331 332 if (cpi.maxio == 0) 333 softc->maxio = DFLTPHYS; /* traditional default */ 334 else if (cpi.maxio > MAXPHYS) 335 softc->maxio = MAXPHYS; /* for safety */ 336 else 337 softc->maxio = cpi.maxio; /* real value */ 338 339 /* 340 * We pass in 0 for all blocksize, since we don't know what the 341 * blocksize of the device is, if it even has a blocksize. 342 */ 343 cam_periph_unlock(periph); 344 no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; 345 softc->device_stats = devstat_new_entry("sg", 346 periph->unit_number, 0, 347 DEVSTAT_NO_BLOCKSIZE 348 | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0), 349 softc->pd_type | 350 XPORT_DEVSTAT_TYPE(cpi.transport) | 351 DEVSTAT_TYPE_PASS, 352 DEVSTAT_PRIORITY_PASS); 353 354 /* 355 * Acquire a reference to the periph before we create the devfs 356 * instance for it. We'll release this reference once the devfs 357 * instance has been freed. 358 */ 359 if (cam_periph_acquire(periph) != CAM_REQ_CMP) { 360 xpt_print(periph->path, "%s: lost periph during " 361 "registration!\n", __func__); 362 cam_periph_lock(periph); 363 return (CAM_REQ_CMP_ERR); 364 } 365 366 /* Register the device */ 367 make_dev_args_init(&args); 368 args.mda_devsw = &sg_cdevsw; 369 args.mda_unit = periph->unit_number; 370 args.mda_uid = UID_ROOT; 371 args.mda_gid = GID_OPERATOR; 372 args.mda_mode = 0600; 373 args.mda_si_drv1 = periph; 374 error = make_dev_s(&args, &softc->dev, "%s%d", 375 periph->periph_name, periph->unit_number); 376 if (error != 0) { 377 cam_periph_lock(periph); 378 cam_periph_release_locked(periph); 379 return (CAM_REQ_CMP_ERR); 380 } 381 if (periph->unit_number < 26) { 382 (void)make_dev_alias(softc->dev, "sg%c", 383 periph->unit_number + 'a'); 384 } else { 385 (void)make_dev_alias(softc->dev, "sg%c%c", 386 ((periph->unit_number / 26) - 1) + 'a', 387 (periph->unit_number % 26) + 'a'); 388 } 389 cam_periph_lock(periph); 390 391 /* 392 * Add as async callback so that we get 393 * notified if this device goes away. 394 */ 395 xpt_register_async(AC_LOST_DEVICE, sgasync, periph, periph->path); 396 397 if (bootverbose) 398 xpt_announce_periph(periph, NULL); 399 400 return (CAM_REQ_CMP); 401 } 402 403 static void 404 sgdone(struct cam_periph *periph, union ccb *done_ccb) 405 { 406 struct sg_softc *softc; 407 struct ccb_scsiio *csio; 408 409 softc = (struct sg_softc *)periph->softc; 410 csio = &done_ccb->csio; 411 switch (csio->ccb_h.ccb_type) { 412 case SG_CCB_RDWR_IO: 413 { 414 struct sg_rdwr *rdwr; 415 int state; 416 417 devstat_end_transaction(softc->device_stats, 418 csio->dxfer_len, 419 csio->tag_action & 0xf, 420 ((csio->ccb_h.flags & CAM_DIR_MASK) == 421 CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 422 (csio->ccb_h.flags & CAM_DIR_OUT) ? 423 DEVSTAT_WRITE : DEVSTAT_READ, 424 NULL, NULL); 425 426 rdwr = done_ccb->ccb_h.ccb_rdwr; 427 state = rdwr->state; 428 rdwr->state = SG_RDWR_DONE; 429 wakeup(rdwr); 430 break; 431 } 432 default: 433 panic("unknown sg CCB type"); 434 } 435 } 436 437 static int 438 sgopen(struct cdev *dev, int flags, int fmt, struct thread *td) 439 { 440 struct cam_periph *periph; 441 struct sg_softc *softc; 442 int error = 0; 443 444 periph = (struct cam_periph *)dev->si_drv1; 445 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 446 return (ENXIO); 447 448 /* 449 * Don't allow access when we're running at a high securelevel. 450 */ 451 error = securelevel_gt(td->td_ucred, 1); 452 if (error) { 453 cam_periph_release(periph); 454 return (error); 455 } 456 457 cam_periph_lock(periph); 458 459 softc = (struct sg_softc *)periph->softc; 460 if (softc->flags & SG_FLAG_INVALID) { 461 cam_periph_release_locked(periph); 462 cam_periph_unlock(periph); 463 return (ENXIO); 464 } 465 466 softc->open_count++; 467 468 cam_periph_unlock(periph); 469 470 return (error); 471 } 472 473 static int 474 sgclose(struct cdev *dev, int flag, int fmt, struct thread *td) 475 { 476 struct cam_periph *periph; 477 struct sg_softc *softc; 478 struct mtx *mtx; 479 480 periph = (struct cam_periph *)dev->si_drv1; 481 mtx = cam_periph_mtx(periph); 482 mtx_lock(mtx); 483 484 softc = periph->softc; 485 softc->open_count--; 486 487 cam_periph_release_locked(periph); 488 489 /* 490 * We reference the lock directly here, instead of using 491 * cam_periph_unlock(). The reason is that the call to 492 * cam_periph_release_locked() above could result in the periph 493 * getting freed. If that is the case, dereferencing the periph 494 * with a cam_periph_unlock() call would cause a page fault. 495 * 496 * cam_periph_release() avoids this problem using the same method, 497 * but we're manually acquiring and dropping the lock here to 498 * protect the open count and avoid another lock acquisition and 499 * release. 500 */ 501 mtx_unlock(mtx); 502 503 return (0); 504 } 505 506 static int 507 sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 508 { 509 union ccb *ccb; 510 struct ccb_scsiio *csio; 511 struct cam_periph *periph; 512 struct sg_softc *softc; 513 struct sg_io_hdr *req; 514 int dir, error; 515 516 periph = (struct cam_periph *)dev->si_drv1; 517 cam_periph_lock(periph); 518 519 softc = (struct sg_softc *)periph->softc; 520 error = 0; 521 522 switch (cmd) { 523 case SG_GET_VERSION_NUM: 524 { 525 int *version = (int *)arg; 526 527 *version = sg_version; 528 break; 529 } 530 case SG_SET_TIMEOUT: 531 { 532 u_int user_timeout = *(u_int *)arg; 533 534 softc->sg_user_timeout = user_timeout; 535 softc->sg_timeout = user_timeout / SG_DEFAULT_HZ * hz; 536 break; 537 } 538 case SG_GET_TIMEOUT: 539 /* 540 * The value is returned directly to the syscall. 541 */ 542 td->td_retval[0] = softc->sg_user_timeout; 543 error = 0; 544 break; 545 case SG_IO: 546 req = (struct sg_io_hdr *)arg; 547 548 if (req->cmd_len > IOCDBLEN) { 549 error = EINVAL; 550 break; 551 } 552 553 if (req->iovec_count != 0) { 554 error = EOPNOTSUPP; 555 break; 556 } 557 558 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 559 csio = &ccb->csio; 560 561 error = copyin(req->cmdp, &csio->cdb_io.cdb_bytes, 562 req->cmd_len); 563 if (error) { 564 xpt_release_ccb(ccb); 565 break; 566 } 567 568 switch(req->dxfer_direction) { 569 case SG_DXFER_TO_DEV: 570 dir = CAM_DIR_OUT; 571 break; 572 case SG_DXFER_FROM_DEV: 573 dir = CAM_DIR_IN; 574 break; 575 case SG_DXFER_TO_FROM_DEV: 576 dir = CAM_DIR_IN | CAM_DIR_OUT; 577 break; 578 case SG_DXFER_NONE: 579 default: 580 dir = CAM_DIR_NONE; 581 break; 582 } 583 584 cam_fill_csio(csio, 585 /*retries*/1, 586 sgdone, 587 dir|CAM_DEV_QFRZDIS, 588 MSG_SIMPLE_Q_TAG, 589 req->dxferp, 590 req->dxfer_len, 591 req->mx_sb_len, 592 req->cmd_len, 593 req->timeout); 594 595 error = sgsendccb(periph, ccb); 596 if (error) { 597 req->host_status = DID_ERROR; 598 req->driver_status = DRIVER_INVALID; 599 xpt_release_ccb(ccb); 600 break; 601 } 602 603 req->status = csio->scsi_status; 604 req->masked_status = (csio->scsi_status >> 1) & 0x7f; 605 sg_scsiio_status(csio, &req->host_status, &req->driver_status); 606 req->resid = csio->resid; 607 req->duration = csio->ccb_h.timeout; 608 req->info = 0; 609 610 if ((csio->ccb_h.status & CAM_AUTOSNS_VALID) 611 && (req->sbp != NULL)) { 612 req->sb_len_wr = req->mx_sb_len - csio->sense_resid; 613 error = copyout(&csio->sense_data, req->sbp, 614 req->sb_len_wr); 615 } 616 617 xpt_release_ccb(ccb); 618 break; 619 620 case SG_GET_RESERVED_SIZE: 621 { 622 int *size = (int *)arg; 623 *size = DFLTPHYS; 624 break; 625 } 626 627 case SG_GET_SCSI_ID: 628 { 629 struct sg_scsi_id *id = (struct sg_scsi_id *)arg; 630 631 id->host_no = cam_sim_path(xpt_path_sim(periph->path)); 632 id->channel = xpt_path_path_id(periph->path); 633 id->scsi_id = xpt_path_target_id(periph->path); 634 id->lun = xpt_path_lun_id(periph->path); 635 id->scsi_type = softc->pd_type; 636 id->h_cmd_per_lun = 1; 637 id->d_queue_depth = 1; 638 id->unused[0] = 0; 639 id->unused[1] = 0; 640 break; 641 } 642 643 case SG_GET_SG_TABLESIZE: 644 { 645 int *size = (int *)arg; 646 *size = 0; 647 break; 648 } 649 650 case SG_EMULATED_HOST: 651 case SG_SET_TRANSFORM: 652 case SG_GET_TRANSFORM: 653 case SG_GET_NUM_WAITING: 654 case SG_SCSI_RESET: 655 case SG_GET_REQUEST_TABLE: 656 case SG_SET_KEEP_ORPHAN: 657 case SG_GET_KEEP_ORPHAN: 658 case SG_GET_ACCESS_COUNT: 659 case SG_SET_FORCE_LOW_DMA: 660 case SG_GET_LOW_DMA: 661 case SG_SET_FORCE_PACK_ID: 662 case SG_GET_PACK_ID: 663 case SG_SET_RESERVED_SIZE: 664 case SG_GET_COMMAND_Q: 665 case SG_SET_COMMAND_Q: 666 case SG_SET_DEBUG: 667 case SG_NEXT_CMD_LEN: 668 default: 669 #ifdef CAMDEBUG 670 printf("sgioctl: rejecting cmd 0x%lx\n", cmd); 671 #endif 672 error = ENODEV; 673 break; 674 } 675 676 cam_periph_unlock(periph); 677 return (error); 678 } 679 680 static int 681 sgwrite(struct cdev *dev, struct uio *uio, int ioflag) 682 { 683 union ccb *ccb; 684 struct cam_periph *periph; 685 struct ccb_scsiio *csio; 686 struct sg_softc *sc; 687 struct sg_header *hdr; 688 struct sg_rdwr *rdwr; 689 u_char cdb_cmd; 690 char *buf; 691 int error = 0, cdb_len, buf_len, dir; 692 693 periph = dev->si_drv1; 694 rdwr = malloc(sizeof(*rdwr), M_DEVBUF, M_WAITOK | M_ZERO); 695 hdr = &rdwr->hdr.hdr; 696 697 /* Copy in the header block and sanity check it */ 698 if (uio->uio_resid < sizeof(*hdr)) { 699 error = EINVAL; 700 goto out_hdr; 701 } 702 error = uiomove(hdr, sizeof(*hdr), uio); 703 if (error) 704 goto out_hdr; 705 706 /* XXX: We don't support SG 3.x read/write API. */ 707 if (hdr->reply_len < 0) { 708 error = ENODEV; 709 goto out_hdr; 710 } 711 712 ccb = xpt_alloc_ccb(); 713 if (ccb == NULL) { 714 error = ENOMEM; 715 goto out_hdr; 716 } 717 csio = &ccb->csio; 718 719 /* 720 * Copy in the CDB block. The designers of the interface didn't 721 * bother to provide a size for this in the header, so we have to 722 * figure it out ourselves. 723 */ 724 if (uio->uio_resid < 1) 725 goto out_ccb; 726 error = uiomove(&cdb_cmd, 1, uio); 727 if (error) 728 goto out_ccb; 729 if (hdr->twelve_byte) 730 cdb_len = 12; 731 else 732 cdb_len = scsi_group_len(cdb_cmd); 733 /* 734 * We've already read the first byte of the CDB and advanced the uio 735 * pointer. Just read the rest. 736 */ 737 csio->cdb_io.cdb_bytes[0] = cdb_cmd; 738 error = uiomove(&csio->cdb_io.cdb_bytes[1], cdb_len - 1, uio); 739 if (error) 740 goto out_ccb; 741 742 /* 743 * Now set up the data block. Again, the designers didn't bother 744 * to make this reliable. 745 */ 746 buf_len = uio->uio_resid; 747 if (buf_len != 0) { 748 buf = malloc(buf_len, M_DEVBUF, M_WAITOK | M_ZERO); 749 error = uiomove(buf, buf_len, uio); 750 if (error) 751 goto out_buf; 752 dir = CAM_DIR_OUT; 753 } else if (hdr->reply_len != 0) { 754 buf = malloc(hdr->reply_len, M_DEVBUF, M_WAITOK | M_ZERO); 755 buf_len = hdr->reply_len; 756 dir = CAM_DIR_IN; 757 } else { 758 buf = NULL; 759 buf_len = 0; 760 dir = CAM_DIR_NONE; 761 } 762 763 cam_periph_lock(periph); 764 sc = periph->softc; 765 xpt_setup_ccb(&ccb->ccb_h, periph->path, CAM_PRIORITY_NORMAL); 766 cam_fill_csio(csio, 767 /*retries*/1, 768 sgdone, 769 dir|CAM_DEV_QFRZDIS, 770 MSG_SIMPLE_Q_TAG, 771 buf, 772 buf_len, 773 SG_MAX_SENSE, 774 cdb_len, 775 sc->sg_timeout); 776 777 /* 778 * Send off the command and hope that it works. This path does not 779 * go through sgstart because the I/O is supposed to be asynchronous. 780 */ 781 rdwr->buf = buf; 782 rdwr->buf_len = buf_len; 783 rdwr->tag = hdr->pack_id; 784 rdwr->ccb = ccb; 785 rdwr->state = SG_RDWR_INPROG; 786 ccb->ccb_h.ccb_rdwr = rdwr; 787 ccb->ccb_h.ccb_type = SG_CCB_RDWR_IO; 788 TAILQ_INSERT_TAIL(&sc->rdwr_done, rdwr, rdwr_link); 789 error = sgsendrdwr(periph, ccb); 790 cam_periph_unlock(periph); 791 return (error); 792 793 out_buf: 794 free(buf, M_DEVBUF); 795 out_ccb: 796 xpt_free_ccb(ccb); 797 out_hdr: 798 free(rdwr, M_DEVBUF); 799 return (error); 800 } 801 802 static int 803 sgread(struct cdev *dev, struct uio *uio, int ioflag) 804 { 805 struct ccb_scsiio *csio; 806 struct cam_periph *periph; 807 struct sg_softc *sc; 808 struct sg_header *hdr; 809 struct sg_rdwr *rdwr; 810 u_short hstat, dstat; 811 int error, pack_len, reply_len, pack_id; 812 813 periph = dev->si_drv1; 814 815 /* XXX The pack len field needs to be updated and written out instead 816 * of discarded. Not sure how to do that. 817 */ 818 uio->uio_rw = UIO_WRITE; 819 if ((error = uiomove(&pack_len, 4, uio)) != 0) 820 return (error); 821 if ((error = uiomove(&reply_len, 4, uio)) != 0) 822 return (error); 823 if ((error = uiomove(&pack_id, 4, uio)) != 0) 824 return (error); 825 uio->uio_rw = UIO_READ; 826 827 cam_periph_lock(periph); 828 sc = periph->softc; 829 search: 830 TAILQ_FOREACH(rdwr, &sc->rdwr_done, rdwr_link) { 831 if (rdwr->tag == pack_id) 832 break; 833 } 834 if ((rdwr == NULL) || (rdwr->state != SG_RDWR_DONE)) { 835 if (cam_periph_sleep(periph, rdwr, PCATCH, "sgread", 0) == ERESTART) 836 return (EAGAIN); 837 goto search; 838 } 839 TAILQ_REMOVE(&sc->rdwr_done, rdwr, rdwr_link); 840 cam_periph_unlock(periph); 841 842 hdr = &rdwr->hdr.hdr; 843 csio = &rdwr->ccb->csio; 844 sg_scsiio_status(csio, &hstat, &dstat); 845 hdr->host_status = hstat; 846 hdr->driver_status = dstat; 847 hdr->target_status = csio->scsi_status >> 1; 848 849 switch (hstat) { 850 case DID_OK: 851 case DID_PASSTHROUGH: 852 case DID_SOFT_ERROR: 853 hdr->result = 0; 854 break; 855 case DID_NO_CONNECT: 856 case DID_BUS_BUSY: 857 case DID_TIME_OUT: 858 hdr->result = EBUSY; 859 break; 860 case DID_BAD_TARGET: 861 case DID_ABORT: 862 case DID_PARITY: 863 case DID_RESET: 864 case DID_BAD_INTR: 865 case DID_ERROR: 866 default: 867 hdr->result = EIO; 868 break; 869 } 870 871 if (dstat == DRIVER_SENSE) { 872 bcopy(&csio->sense_data, hdr->sense_buffer, 873 min(csio->sense_len, SG_MAX_SENSE)); 874 #ifdef CAMDEBUG 875 scsi_sense_print(csio); 876 #endif 877 } 878 879 error = uiomove(&hdr->result, sizeof(*hdr) - 880 offsetof(struct sg_header, result), uio); 881 if ((error == 0) && (hdr->result == 0)) 882 error = uiomove(rdwr->buf, rdwr->buf_len, uio); 883 884 cam_periph_lock(periph); 885 xpt_free_ccb(rdwr->ccb); 886 cam_periph_unlock(periph); 887 free(rdwr->buf, M_DEVBUF); 888 free(rdwr, M_DEVBUF); 889 return (error); 890 } 891 892 static int 893 sgsendccb(struct cam_periph *periph, union ccb *ccb) 894 { 895 struct sg_softc *softc; 896 struct cam_periph_map_info mapinfo; 897 int error; 898 899 softc = periph->softc; 900 bzero(&mapinfo, sizeof(mapinfo)); 901 902 /* 903 * cam_periph_mapmem calls into proc and vm functions that can 904 * sleep as well as trigger I/O, so we can't hold the lock. 905 * Dropping it here is reasonably safe. 906 * The only CCB opcode that is possible here is XPT_SCSI_IO, no 907 * need for additional checks. 908 */ 909 cam_periph_unlock(periph); 910 error = cam_periph_mapmem(ccb, &mapinfo, softc->maxio); 911 cam_periph_lock(periph); 912 if (error) 913 return (error); 914 915 error = cam_periph_runccb(ccb, 916 sgerror, 917 CAM_RETRY_SELTO, 918 SF_RETRY_UA, 919 softc->device_stats); 920 921 cam_periph_unmapmem(ccb, &mapinfo); 922 923 return (error); 924 } 925 926 static int 927 sgsendrdwr(struct cam_periph *periph, union ccb *ccb) 928 { 929 struct sg_softc *softc; 930 931 softc = periph->softc; 932 devstat_start_transaction(softc->device_stats, NULL); 933 xpt_action(ccb); 934 return (0); 935 } 936 937 static int 938 sgerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags) 939 { 940 struct cam_periph *periph; 941 struct sg_softc *softc; 942 943 periph = xpt_path_periph(ccb->ccb_h.path); 944 softc = (struct sg_softc *)periph->softc; 945 946 return (cam_periph_error(ccb, cam_flags, sense_flags, 947 &softc->saved_ccb)); 948 } 949 950 static void 951 sg_scsiio_status(struct ccb_scsiio *csio, u_short *hoststat, u_short *drvstat) 952 { 953 int status; 954 955 status = csio->ccb_h.status; 956 957 switch (status & CAM_STATUS_MASK) { 958 case CAM_REQ_CMP: 959 *hoststat = DID_OK; 960 *drvstat = 0; 961 break; 962 case CAM_REQ_CMP_ERR: 963 *hoststat = DID_ERROR; 964 *drvstat = 0; 965 break; 966 case CAM_REQ_ABORTED: 967 *hoststat = DID_ABORT; 968 *drvstat = 0; 969 break; 970 case CAM_REQ_INVALID: 971 *hoststat = DID_ERROR; 972 *drvstat = DRIVER_INVALID; 973 break; 974 case CAM_DEV_NOT_THERE: 975 *hoststat = DID_BAD_TARGET; 976 *drvstat = 0; 977 break; 978 case CAM_SEL_TIMEOUT: 979 *hoststat = DID_NO_CONNECT; 980 *drvstat = 0; 981 break; 982 case CAM_CMD_TIMEOUT: 983 *hoststat = DID_TIME_OUT; 984 *drvstat = 0; 985 break; 986 case CAM_SCSI_STATUS_ERROR: 987 *hoststat = DID_ERROR; 988 *drvstat = 0; 989 break; 990 case CAM_SCSI_BUS_RESET: 991 *hoststat = DID_RESET; 992 *drvstat = 0; 993 break; 994 case CAM_UNCOR_PARITY: 995 *hoststat = DID_PARITY; 996 *drvstat = 0; 997 break; 998 case CAM_SCSI_BUSY: 999 *hoststat = DID_BUS_BUSY; 1000 *drvstat = 0; 1001 break; 1002 default: 1003 *hoststat = DID_ERROR; 1004 *drvstat = DRIVER_ERROR; 1005 } 1006 1007 if (status & CAM_AUTOSNS_VALID) 1008 *drvstat = DRIVER_SENSE; 1009 } 1010 1011 static int 1012 scsi_group_len(u_char cmd) 1013 { 1014 int len[] = {6, 10, 10, 12, 12, 12, 10, 10}; 1015 int group; 1016 1017 group = (cmd >> 5) & 0x7; 1018 return (len[group]); 1019 } 1020 1021