- 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:
parent
dae6d925a2
commit
068d70bad8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121184
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user