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