scsi_cmds.c (157670) | scsi_cmds.c (162704) |
---|---|
1/* 2 * SCSI Disk Emulator 3 * 4 * Copyright (c) 2002 Nate Lawson. 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 --- 11 unchanged lines hidden (view full) --- 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 * | 1/* 2 * SCSI Disk Emulator 3 * 4 * Copyright (c) 2002 Nate Lawson. 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 --- 11 unchanged lines hidden (view full) --- 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 * $FreeBSD: head/share/examples/scsi_target/scsi_cmds.c 157670 2006-04-11 21:36:43Z mjacob $ | 28 * $FreeBSD: head/share/examples/scsi_target/scsi_cmds.c 162704 2006-09-27 15:38:13Z mjacob $ |
29 */ 30 31#include <stdio.h> 32#include <stddef.h> 33#include <stdarg.h> 34#include <stdlib.h> 35#include <string.h> 36#include <err.h> 37#include <aio.h> | 29 */ 30 31#include <stdio.h> 32#include <stddef.h> 33#include <stdarg.h> 34#include <stdlib.h> 35#include <string.h> 36#include <err.h> 37#include <aio.h> |
38#include <unistd.h> |
|
38#include <assert.h> 39#include <sys/param.h> 40#include <sys/types.h> 41 42#include <cam/cam.h> 43#include <cam/cam_ccb.h> 44#include <cam/scsi/scsi_all.h> 45#include <cam/scsi/scsi_targetio.h> --- 309 unchanged lines hidden (view full) --- 355 */ 356 if ((req_flags & SID_Addr16) != 0) { 357 sim_flags |= SID_Addr16; 358 warnx("Not sure SIM supports Addr16 but enabling it anyway"); 359 } 360 361 /* Advertise only what the SIM can actually support */ 362 req_flags &= sim_flags; | 39#include <assert.h> 40#include <sys/param.h> 41#include <sys/types.h> 42 43#include <cam/cam.h> 44#include <cam/cam_ccb.h> 45#include <cam/scsi/scsi_all.h> 46#include <cam/scsi/scsi_targetio.h> --- 309 unchanged lines hidden (view full) --- 356 */ 357 if ((req_flags & SID_Addr16) != 0) { 358 sim_flags |= SID_Addr16; 359 warnx("Not sure SIM supports Addr16 but enabling it anyway"); 360 } 361 362 /* Advertise only what the SIM can actually support */ 363 req_flags &= sim_flags; |
363 scsi_ulto2b(req_flags, &inq->reserved[1]); | 364 scsi_ulto2b(req_flags, &inq->spc2_flags); |
364 365 inq->response_format = 2; /* SCSI2 Inquiry Format */ 366 inq->additional_length = SHORT_INQUIRY_LENGTH - 367 offsetof(struct scsi_inquiry_data, additional_length); 368 bcopy("FreeBSD ", inq->vendor, SID_VENDOR_SIZE); 369 bcopy("Emulated Disk ", inq->product, SID_PRODUCT_SIZE); 370 bcopy("0.1 ", inq->revision, SID_REVISION_SIZE); 371 return (0); --- 119 unchanged lines hidden (view full) --- 491 } 492 } 493 ctio->ccb_h.flags |= a_descr->flags; 494 495 /* Call appropriate work function */ 496 if ((a_descr->flags & CAM_DIR_IN) != 0) { 497 ret = start_io(atio, ctio, CAM_DIR_IN); 498 if (debug) | 365 366 inq->response_format = 2; /* SCSI2 Inquiry Format */ 367 inq->additional_length = SHORT_INQUIRY_LENGTH - 368 offsetof(struct scsi_inquiry_data, additional_length); 369 bcopy("FreeBSD ", inq->vendor, SID_VENDOR_SIZE); 370 bcopy("Emulated Disk ", inq->product, SID_PRODUCT_SIZE); 371 bcopy("0.1 ", inq->revision, SID_REVISION_SIZE); 372 return (0); --- 119 unchanged lines hidden (view full) --- 492 } 493 } 494 ctio->ccb_h.flags |= a_descr->flags; 495 496 /* Call appropriate work function */ 497 if ((a_descr->flags & CAM_DIR_IN) != 0) { 498 ret = start_io(atio, ctio, CAM_DIR_IN); 499 if (debug) |
499#if __FreeBSD_version >= 500000 500 warnx("Starting DIR_IN @%jd:%u", 501#else 502 warnx("Starting DIR_IN @%lld:%u", 503#endif 504 c_descr->offset, a_descr->targ_req); | 500 warnx("Starting %p DIR_IN @" OFF_FMT ":%u", 501 a_descr, c_descr->offset, a_descr->targ_req); |
505 } else { 506 ret = start_io(atio, ctio, CAM_DIR_OUT); 507 if (debug) | 502 } else { 503 ret = start_io(atio, ctio, CAM_DIR_OUT); 504 if (debug) |
508#if __FreeBSD_version >= 500000 509 warnx("Starting DIR_OUT @%jd:%u", 510#else 511 warnx("Starting DIR_OUT @%lld:%u", 512#endif 513 c_descr->offset, a_descr->init_req); | 505 warnx("Starting %p DIR_OUT @" OFF_FMT ":%u", 506 a_descr, c_descr->offset, a_descr->init_req); |
514 } 515 516 return (ret); 517} 518 519static int 520tcmd_rdwr_decode(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio) 521{ --- 45 unchanged lines hidden (view full) --- 567 return (0); 568 } 569 570 /* Get an (overall) data length and set direction */ 571 a_descr->base_off = ((off_t)blkno) * sector_size; 572 a_descr->total_len = count * sector_size; 573 if (a_descr->total_len == 0) { 574 if (debug) | 507 } 508 509 return (ret); 510} 511 512static int 513tcmd_rdwr_decode(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio) 514{ --- 45 unchanged lines hidden (view full) --- 560 return (0); 561 } 562 563 /* Get an (overall) data length and set direction */ 564 a_descr->base_off = ((off_t)blkno) * sector_size; 565 a_descr->total_len = count * sector_size; 566 if (a_descr->total_len == 0) { 567 if (debug) |
575#if __FreeBSD_version >= 500000 576 warnx("r/w 0 blocks @ blkno %ju", blkno); 577#else 578 warnx("r/w 0 blocks @ blkno %llu", blkno); 579#endif | 568 warnx("r/w 0 blocks @ blkno " OFF_FMT, blkno); |
580 tcmd_null_ok(atio, ctio); 581 return (0); 582 } else if (cdb[0] == WRITE_6 || cdb[0] == WRITE_10) { 583 a_descr->flags |= CAM_DIR_OUT; 584 if (debug) | 569 tcmd_null_ok(atio, ctio); 570 return (0); 571 } else if (cdb[0] == WRITE_6 || cdb[0] == WRITE_10) { 572 a_descr->flags |= CAM_DIR_OUT; 573 if (debug) |
585#if __FreeBSD_version >= 500000 586 warnx("write %u blocks @ blkno %ju", count, blkno); 587#else 588 warnx("write %u blocks @ blkno %llu", count, blkno); 589#endif | 574 warnx("write %u blocks @ blkno " OFF_FMT, count, blkno); |
590 } else { 591 a_descr->flags |= CAM_DIR_IN; 592 if (debug) | 575 } else { 576 a_descr->flags |= CAM_DIR_IN; 577 if (debug) |
593#if __FreeBSD_version >= 500000 594 warnx("read %u blocks @ blkno %ju", count, blkno); 595#else 596 warnx("read %u blocks @ blkno %llu", count, blkno); 597#endif | 578 warnx("read %u blocks @ blkno " OFF_FMT, count, blkno); |
598 } 599 return (1); 600} 601 602static int 603start_io(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio, int dir) 604{ 605 struct atio_descr *a_descr; --- 15 unchanged lines hidden (view full) --- 621 assert(ctio->dxfer_len >= 0); 622 623 c_descr->aiocb.aio_offset = c_descr->offset; 624 c_descr->aiocb.aio_nbytes = ctio->dxfer_len; 625 626 /* If DIR_IN, start read from target, otherwise begin CTIO xfer. */ 627 ret = 1; 628 if (dir == CAM_DIR_IN) { | 579 } 580 return (1); 581} 582 583static int 584start_io(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio, int dir) 585{ 586 struct atio_descr *a_descr; --- 15 unchanged lines hidden (view full) --- 602 assert(ctio->dxfer_len >= 0); 603 604 c_descr->aiocb.aio_offset = c_descr->offset; 605 c_descr->aiocb.aio_nbytes = ctio->dxfer_len; 606 607 /* If DIR_IN, start read from target, otherwise begin CTIO xfer. */ 608 ret = 1; 609 if (dir == CAM_DIR_IN) { |
629 if (aio_read(&c_descr->aiocb) < 0) 630 err(1, "aio_read"); /* XXX */ | 610 if (notaio) { 611 if (debug) 612 warnx("read sync %lud @ block " OFF_FMT, 613 (unsigned long) 614 (ctio->dxfer_len / sector_size), 615 c_descr->offset / sector_size); 616 if (lseek(c_descr->aiocb.aio_fildes, 617 c_descr->aiocb.aio_offset, SEEK_SET) < 0) { 618 perror("lseek"); 619 err(1, "lseek"); 620 } 621 if (read(c_descr->aiocb.aio_fildes, 622 (void *)c_descr->aiocb.aio_buf, 623 ctio->dxfer_len) != ctio->dxfer_len) { 624 err(1, "read"); 625 } 626 } else { 627 if (debug) 628 warnx("read async %lud @ block " OFF_FMT, 629 (unsigned long) 630 (ctio->dxfer_len / sector_size), 631 c_descr->offset / sector_size); 632 if (aio_read(&c_descr->aiocb) < 0) { 633 err(1, "aio_read"); /* XXX */ 634 } 635 } |
631 a_descr->targ_req += ctio->dxfer_len; | 636 a_descr->targ_req += ctio->dxfer_len; |
637 /* if we're done, we can mark the CCB as to send status */ |
|
632 if (a_descr->targ_req == a_descr->total_len) { 633 ctio->ccb_h.flags |= CAM_SEND_STATUS; 634 ctio->scsi_status = SCSI_STATUS_OK; 635 ret = 0; 636 } | 638 if (a_descr->targ_req == a_descr->total_len) { 639 ctio->ccb_h.flags |= CAM_SEND_STATUS; 640 ctio->scsi_status = SCSI_STATUS_OK; 641 ret = 0; 642 } |
643 if (notaio) 644 tcmd_rdwr_done(atio, ctio, AIO_DONE); |
|
637 } else { 638 if (a_descr->targ_ack == a_descr->total_len) 639 tcmd_null_ok(atio, ctio); 640 a_descr->init_req += ctio->dxfer_len; 641 if (a_descr->init_req == a_descr->total_len && 642 ctio->dxfer_len > 0) { 643 /* 644 * If data phase done, remove atio from workq. --- 15 unchanged lines hidden (view full) --- 660 struct atio_descr *a_descr; 661 struct ctio_descr *c_descr; 662 663 a_descr = (struct atio_descr *)atio->ccb_h.targ_descr; 664 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; 665 666 switch (event) { 667 case AIO_DONE: | 645 } else { 646 if (a_descr->targ_ack == a_descr->total_len) 647 tcmd_null_ok(atio, ctio); 648 a_descr->init_req += ctio->dxfer_len; 649 if (a_descr->init_req == a_descr->total_len && 650 ctio->dxfer_len > 0) { 651 /* 652 * If data phase done, remove atio from workq. --- 15 unchanged lines hidden (view full) --- 668 struct atio_descr *a_descr; 669 struct ctio_descr *c_descr; 670 671 a_descr = (struct atio_descr *)atio->ccb_h.targ_descr; 672 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; 673 674 switch (event) { 675 case AIO_DONE: |
668 if (aio_return(&c_descr->aiocb) < 0) { | 676 if (!notaio && aio_return(&c_descr->aiocb) < 0) { |
669 warn("aio_return error"); 670 /* XXX */ 671 tcmd_sense(ctio->init_id, ctio, 672 SSD_KEY_MEDIUM_ERROR, 0, 0); 673 send_ccb((union ccb *)ctio, /*priority*/1); 674 break; 675 } 676 a_descr->targ_ack += ctio->dxfer_len; 677 if ((a_descr->flags & CAM_DIR_IN) != 0) { | 677 warn("aio_return error"); 678 /* XXX */ 679 tcmd_sense(ctio->init_id, ctio, 680 SSD_KEY_MEDIUM_ERROR, 0, 0); 681 send_ccb((union ccb *)ctio, /*priority*/1); 682 break; 683 } 684 a_descr->targ_ack += ctio->dxfer_len; 685 if ((a_descr->flags & CAM_DIR_IN) != 0) { |
678 if (debug) 679 warnx("sending CTIO for AIO read"); | 686 if (debug) { 687 if (notaio) 688 warnx("sending CTIO for AIO read"); 689 else 690 warnx("sending CTIO for sync read"); 691 } |
680 a_descr->init_req += ctio->dxfer_len; 681 send_ccb((union ccb *)ctio, /*priority*/1); 682 } else { 683 /* Use work function to send final status */ 684 if (a_descr->init_req == a_descr->total_len) 685 work_atio(atio); 686 if (debug) 687 warnx("AIO done freeing CTIO"); --- 17 unchanged lines hidden (view full) --- 705 } 706 return; 707 default: 708 errx(1, "CTIO failed, status %#x", ctio->ccb_h.status); 709 } 710 a_descr->init_ack += ctio->dxfer_len; 711 if ((a_descr->flags & CAM_DIR_MASK) == CAM_DIR_OUT && 712 ctio->dxfer_len > 0) { | 692 a_descr->init_req += ctio->dxfer_len; 693 send_ccb((union ccb *)ctio, /*priority*/1); 694 } else { 695 /* Use work function to send final status */ 696 if (a_descr->init_req == a_descr->total_len) 697 work_atio(atio); 698 if (debug) 699 warnx("AIO done freeing CTIO"); --- 17 unchanged lines hidden (view full) --- 717 } 718 return; 719 default: 720 errx(1, "CTIO failed, status %#x", ctio->ccb_h.status); 721 } 722 a_descr->init_ack += ctio->dxfer_len; 723 if ((a_descr->flags & CAM_DIR_MASK) == CAM_DIR_OUT && 724 ctio->dxfer_len > 0) { |
713 if (debug) 714 warnx("sending AIO for CTIO write"); | |
715 a_descr->targ_req += ctio->dxfer_len; | 725 a_descr->targ_req += ctio->dxfer_len; |
716 if (aio_write(&c_descr->aiocb) < 0) 717 err(1, "aio_write"); /* XXX */ | 726 if (notaio) { 727 if (debug) 728 warnx("write sync %lud @ block " 729 OFF_FMT, (unsigned long) 730 (ctio->dxfer_len / sector_size), 731 c_descr->offset / sector_size); 732 if (lseek(c_descr->aiocb.aio_fildes, 733 c_descr->aiocb.aio_offset, SEEK_SET) < 0) { 734 perror("lseek"); 735 err(1, "lseek"); 736 } 737 if (write(c_descr->aiocb.aio_fildes, 738 (void *) c_descr->aiocb.aio_buf, 739 ctio->dxfer_len) != ctio->dxfer_len) { 740 err(1, "write"); 741 } 742 tcmd_rdwr_done(atio, ctio, AIO_DONE); 743 } else { 744 if (debug) 745 warnx("write async %lud @ block " 746 OFF_FMT, (unsigned long) 747 (ctio->dxfer_len / sector_size), 748 c_descr->offset / sector_size); 749 if (aio_write(&c_descr->aiocb) < 0) { 750 err(1, "aio_write"); /* XXX */ 751 } 752 } |
718 } else { 719 if (debug) 720 warnx("CTIO done freeing CTIO"); 721 free_ccb((union ccb *)ctio); 722 } 723 break; 724 default: 725 warnx("Unknown completion code %d", event); --- 53 unchanged lines hidden --- | 753 } else { 754 if (debug) 755 warnx("CTIO done freeing CTIO"); 756 free_ccb((union ccb *)ctio); 757 } 758 break; 759 default: 760 warnx("Unknown completion code %d", event); --- 53 unchanged lines hidden --- |