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