- Enable 16byte commands.

- Fix printf warnings on 64bit architectures.
- Accept 'k', 'm' and etc. for -s option.

Reviewed by: njl
This commit is contained in:
Hidetoshi Shimokawa 2003-10-18 04:54:08 +00:00
parent dae6d925a2
commit 068d70bad8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121184
4 changed files with 160 additions and 20 deletions

View File

@ -36,6 +36,7 @@
#include <err.h>
#include <aio.h>
#include <assert.h>
#include <sys/param.h>
#include <sys/types.h>
#include <cam/cam.h>
@ -58,6 +59,9 @@ struct targ_cdb_handlers {
static targ_start_func tcmd_inquiry;
static targ_start_func tcmd_req_sense;
static targ_start_func tcmd_rd_cap;
#ifdef READ_16
static targ_start_func tcmd_rd_cap16;
#endif
static targ_start_func tcmd_rdwr;
static targ_start_func tcmd_rdwr_decode;
static targ_done_func tcmd_rdwr_done;
@ -83,13 +87,18 @@ static struct targ_cdb_handlers cdb_handlers[] = {
{ SYNCHRONIZE_CACHE, tcmd_null_ok, NULL },
{ MODE_SENSE_6, tcmd_illegal_req, NULL },
{ MODE_SELECT_6, tcmd_illegal_req, NULL },
#ifdef READ_16
{ READ_16, tcmd_rdwr, tcmd_rdwr_done },
{ WRITE_16, tcmd_rdwr, tcmd_rdwr_done },
{ SERVICE_ACTION_IN, tcmd_rd_cap16, NULL },
#endif
{ ILLEGAL_CDB, NULL, NULL }
};
static struct scsi_inquiry_data inq_data;
static struct initiator_state istates[MAX_INITIATORS];
extern int debug;
extern u_int32_t volume_size;
extern uint64_t volume_size;
extern size_t sector_size;
extern size_t buf_size;
@ -398,17 +407,23 @@ tcmd_rd_cap(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
{
struct scsi_read_capacity_data *srp;
struct atio_descr *a_descr;
uint32_t vsize;
a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
srp = (struct scsi_read_capacity_data *)ctio->data_ptr;
if (volume_size > 0xffffffff)
vsize = 0xffffffff;
else
vsize = (uint32_t)(volume_size - 1);
if (debug) {
cdb_debug(a_descr->cdb, "READ CAP from %u (%u, %u): ",
atio->init_id, volume_size - 1, sector_size);
atio->init_id, vsize, sector_size);
}
bzero(srp, sizeof(*srp));
scsi_ulto4b(volume_size - 1, srp->addr);
scsi_ulto4b(vsize, srp->addr);
scsi_ulto4b(sector_size, srp->length);
ctio->dxfer_len = sizeof(*srp);
@ -417,6 +432,39 @@ tcmd_rd_cap(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
return (0);
}
#ifdef READ_16
static int
tcmd_rd_cap16(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
{
struct scsi_read_capacity_16 *scsi_cmd;
struct scsi_read_capacity_data_long *srp;
struct atio_descr *a_descr;
a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
scsi_cmd = (struct scsi_read_capacity_16 *)a_descr->cdb;
srp = (struct scsi_read_capacity_data_long *)ctio->data_ptr;
if (scsi_cmd->service_action != SRC16_SERVICE_ACTION) {
tcmd_illegal_req(atio, ctio);
return (0);
}
if (debug) {
cdb_debug(a_descr->cdb, "READ CAP16 from %u (%u, %u): ",
atio->init_id, volume_size - 1, sector_size);
}
bzero(srp, sizeof(*srp));
scsi_u64to8b(volume_size - 1, srp->addr);
scsi_ulto4b(sector_size, srp->length);
ctio->dxfer_len = sizeof(*srp);
ctio->ccb_h.flags |= CAM_DIR_IN | CAM_SEND_STATUS;
ctio->scsi_status = SCSI_STATUS_OK;
return (0);
}
#endif
static int
tcmd_rdwr(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
{
@ -443,13 +491,21 @@ tcmd_rdwr(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
if ((a_descr->flags & CAM_DIR_IN) != 0) {
ret = start_io(atio, ctio, CAM_DIR_IN);
if (debug)
warnx("Starting DIR_IN @%lld:%u", c_descr->offset,
a_descr->targ_req);
#if __FreeBSD_version >= 500000
warnx("Starting DIR_IN @%jd:%u",
#else
warnx("Starting DIR_IN @%lld:%u",
#endif
c_descr->offset, a_descr->targ_req);
} else {
ret = start_io(atio, ctio, CAM_DIR_OUT);
if (debug)
warnx("Starting DIR_OUT @%lld:%u", c_descr->offset,
a_descr->init_req);
#if __FreeBSD_version >= 500000
warnx("Starting DIR_OUT @%jd:%u",
#else
warnx("Starting DIR_OUT @%lld:%u",
#endif
c_descr->offset, a_descr->init_req);
}
return (ret);
@ -458,7 +514,8 @@ tcmd_rdwr(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
static int
tcmd_rdwr_decode(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
{
u_int32_t blkno, count;
uint64_t blkno;
uint32_t count;
struct atio_descr *a_descr;
u_int8_t *cdb;
@ -467,14 +524,36 @@ tcmd_rdwr_decode(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
if (debug)
cdb_debug(cdb, "R/W from %u: ", atio->init_id);
if (cdb[0] == READ_6 || cdb[0] == WRITE_6) {
switch (cdb[0]) {
case READ_6:
case WRITE_6:
{
struct scsi_rw_6 *rw_6 = (struct scsi_rw_6 *)cdb;
blkno = scsi_3btoul(rw_6->addr);
count = rw_6->length;
} else {
break;
}
case READ_10:
case WRITE_10:
{
struct scsi_rw_10 *rw_10 = (struct scsi_rw_10 *)cdb;
blkno = scsi_4btoul(rw_10->addr);
count = scsi_2btoul(rw_10->length);
break;
}
#ifdef READ_16
case READ_16:
case WRITE_16:
{
struct scsi_rw_16 *rw_16 = (struct scsi_rw_16 *)cdb;
blkno = scsi_8btou64(rw_16->addr);
count = scsi_4btoul(rw_16->length);
break;
}
#endif
default:
tcmd_illegal_req(atio, ctio);
return (0);
}
if (blkno + count > volume_size) {
warnx("Attempt to access past end of volume");
@ -488,17 +567,29 @@ tcmd_rdwr_decode(struct ccb_accept_tio *atio, struct ccb_scsiio *ctio)
a_descr->total_len = count * sector_size;
if (a_descr->total_len == 0) {
if (debug)
warnx("r/w 0 blocks @ blkno %u", blkno);
#if __FreeBSD_version >= 500000
warnx("r/w 0 blocks @ blkno %ju", blkno);
#else
warnx("r/w 0 blocks @ blkno %llu", blkno);
#endif
tcmd_null_ok(atio, ctio);
return (0);
} else if (cdb[0] == WRITE_6 || cdb[0] == WRITE_10) {
a_descr->flags |= CAM_DIR_OUT;
if (debug)
warnx("write %u blocks @ blkno %u", count, blkno);
#if __FreeBSD_version >= 500000
warnx("write %u blocks @ blkno %ju", count, blkno);
#else
warnx("write %u blocks @ blkno %llu", count, blkno);
#endif
} else {
a_descr->flags |= CAM_DIR_IN;
if (debug)
warnx("read %u blocks @ blkno %u", count, blkno);
#if __FreeBSD_version >= 500000
warnx("read %u blocks @ blkno %ju", count, blkno);
#else
warnx("read %u blocks @ blkno %llu", count, blkno);
#endif
}
return (1);
}

View File

@ -94,6 +94,17 @@ and its associated control device.
Use a different size for the emulated volume.
Must be less than or equal to the size of
.Ar filename .
If the number ends with a
.Dq Li k ,
.Dq Li m ,
.Dq Li g ,
.Dq Li t ,
.Dq Li p ,
or
.Dq Li e ,
the number is multiplied by 2^10 (1K), 2^20 (1M), 2^30 (1G), 2^40 (1T),
2^50 (1P) and 2^60 (1E)
respectively.
.El
.Pp
Required arguments:

View File

@ -29,6 +29,7 @@
*/
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <err.h>
#include <fcntl.h>
@ -61,8 +62,8 @@
/* Global variables */
int debug;
u_int32_t volume_size;
size_t sector_size;
off_t volume_size;
u_int sector_size;
size_t buf_size;
/* Local variables */
@ -141,10 +142,39 @@ main(int argc, char *argv[])
errx(1, "Unreasonable sector size: %s", optarg);
break;
case 's':
{
int last, shift = 0;
last = strlen(optarg) - 1;
if (last > 0) {
switch (tolower(optarg[last])) {
case 'e':
shift += 10;
/* FALLTHROUGH */
case 'p':
shift += 10;
/* FALLTHROUGH */
case 't':
shift += 10;
/* FALLTHROUGH */
case 'g':
shift += 10;
/* FALLTHROUGH */
case 'm':
shift += 10;
/* FALLTHROUGH */
case 'k':
shift += 10;
optarg[last] = 0;
break;
}
}
user_size = strtoll(optarg, (char **)NULL, /*base*/10);
user_size <<= shift;
if (user_size < 0)
errx(1, "Unreasonable volume size: %s", optarg);
break;
}
case 'W':
req_flags &= ~(SID_WBus16 | SID_WBus32);
switch (atoi(optarg)) {
@ -215,6 +245,14 @@ main(int argc, char *argv[])
} else {
volume_size = user_size / sector_size;
}
if (debug)
#if __FreeBSD_version >= 500000
warnx("volume_size: %d bytes x %jd sectors",
#else
warnx("volume_size: %d bytes x %lld sectors",
#endif
sector_size, volume_size);
if (volume_size <= 0)
errx(1, "volume must be larger than %d", sector_size);

View File

@ -51,11 +51,11 @@ TAILQ_HEAD(io_queue, ccb_hdr);
/* Descriptor attached to each ATIO */
struct atio_descr {
off_t base_off; /* Base offset for ATIO */
size_t total_len; /* Total xfer len for this ATIO */
size_t init_req; /* Transfer count requested to/from init */
size_t init_ack; /* Data transferred ok to/from init */
size_t targ_req; /* Transfer count requested to/from target */
size_t targ_ack; /* Data transferred ok to/from target */
uint total_len; /* Total xfer len for this ATIO */
uint init_req; /* Transfer count requested to/from init */
uint init_ack; /* Data transferred ok to/from init */
uint targ_req; /* Transfer count requested to/from target */
uint targ_ack; /* Data transferred ok to/from target */
int flags; /* Flags for CTIOs */
u_int8_t *cdb; /* Pointer to received CDB */
/* List of completed AIO/CTIOs */