Add READ BUFFER and improve WRITE BUFFER SCSI commands support.
This gives some use to 512KB per-LUN buffers, allocated for Copan-specific processor code and not used. It allows, for example, to test transport performance and/or correctness without accessing the media, as supported by Linux version of sg3_utils. MFC after: 2 weeks
This commit is contained in:
parent
d8e37c5f72
commit
85165a3f70
@ -4854,6 +4854,7 @@ ctl_config_move_done(union ctl_io *io)
|
||||
/*sks_valid*/ 1,
|
||||
/*retry_count*/
|
||||
io->io_hdr.port_status);
|
||||
if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
|
||||
free(io->scsiio.kern_data_ptr, M_CTL);
|
||||
ctl_done(io);
|
||||
goto bailout;
|
||||
@ -4867,6 +4868,7 @@ ctl_config_move_done(union ctl_io *io)
|
||||
* S/G list. If we start using S/G lists for config data,
|
||||
* we'll need to know how to clean them up here as well.
|
||||
*/
|
||||
if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
|
||||
free(io->scsiio.kern_data_ptr, M_CTL);
|
||||
/* Hopefully the user has already set the status... */
|
||||
ctl_done(io);
|
||||
@ -5611,24 +5613,106 @@ ctl_format(struct ctl_scsiio *ctsio)
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_read_buffer(struct ctl_scsiio *ctsio)
|
||||
{
|
||||
struct scsi_read_buffer *cdb;
|
||||
struct ctl_lun *lun;
|
||||
int buffer_offset, len;
|
||||
static uint8_t descr[4];
|
||||
static uint8_t echo_descr[4] = { 0 };
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_read_buffer\n"));
|
||||
|
||||
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
|
||||
cdb = (struct scsi_read_buffer *)ctsio->cdb;
|
||||
|
||||
if (lun->flags & CTL_LUN_PR_RESERVED) {
|
||||
uint32_t residx;
|
||||
|
||||
/*
|
||||
* XXX KDM need a lock here.
|
||||
*/
|
||||
residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
|
||||
if ((lun->res_type == SPR_TYPE_EX_AC
|
||||
&& residx != lun->pr_res_idx)
|
||||
|| ((lun->res_type == SPR_TYPE_EX_AC_RO
|
||||
|| lun->res_type == SPR_TYPE_EX_AC_AR)
|
||||
&& !lun->per_res[residx].registered)) {
|
||||
ctl_set_reservation_conflict(ctsio);
|
||||
ctl_done((union ctl_io *)ctsio);
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((cdb->byte2 & RWB_MODE) != RWB_MODE_DATA &&
|
||||
(cdb->byte2 & RWB_MODE) != RWB_MODE_ECHO_DESCR &&
|
||||
(cdb->byte2 & RWB_MODE) != RWB_MODE_DESCR) {
|
||||
ctl_set_invalid_field(ctsio,
|
||||
/*sks_valid*/ 1,
|
||||
/*command*/ 1,
|
||||
/*field*/ 1,
|
||||
/*bit_valid*/ 1,
|
||||
/*bit*/ 4);
|
||||
ctl_done((union ctl_io *)ctsio);
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
if (cdb->buffer_id != 0) {
|
||||
ctl_set_invalid_field(ctsio,
|
||||
/*sks_valid*/ 1,
|
||||
/*command*/ 1,
|
||||
/*field*/ 2,
|
||||
/*bit_valid*/ 0,
|
||||
/*bit*/ 0);
|
||||
ctl_done((union ctl_io *)ctsio);
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
len = scsi_3btoul(cdb->length);
|
||||
buffer_offset = scsi_3btoul(cdb->offset);
|
||||
|
||||
if (buffer_offset + len > sizeof(lun->write_buffer)) {
|
||||
ctl_set_invalid_field(ctsio,
|
||||
/*sks_valid*/ 1,
|
||||
/*command*/ 1,
|
||||
/*field*/ 6,
|
||||
/*bit_valid*/ 0,
|
||||
/*bit*/ 0);
|
||||
ctl_done((union ctl_io *)ctsio);
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
if ((cdb->byte2 & RWB_MODE) == RWB_MODE_DESCR) {
|
||||
descr[0] = 0;
|
||||
scsi_ulto3b(sizeof(lun->write_buffer), &descr[1]);
|
||||
ctsio->kern_data_ptr = descr;
|
||||
len = min(len, sizeof(descr));
|
||||
} else if ((cdb->byte2 & RWB_MODE) == RWB_MODE_ECHO_DESCR) {
|
||||
ctsio->kern_data_ptr = echo_descr;
|
||||
len = min(len, sizeof(echo_descr));
|
||||
} else
|
||||
ctsio->kern_data_ptr = lun->write_buffer + buffer_offset;
|
||||
ctsio->kern_data_len = len;
|
||||
ctsio->kern_total_len = len;
|
||||
ctsio->kern_data_resid = 0;
|
||||
ctsio->kern_rel_offset = 0;
|
||||
ctsio->kern_sg_entries = 0;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_write_buffer(struct ctl_scsiio *ctsio)
|
||||
{
|
||||
struct scsi_write_buffer *cdb;
|
||||
struct copan_page_header *header;
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_softc *ctl_softc;
|
||||
int buffer_offset, len;
|
||||
int retval;
|
||||
|
||||
header = NULL;
|
||||
|
||||
retval = CTL_RETVAL_COMPLETE;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_write_buffer\n"));
|
||||
|
||||
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
|
||||
ctl_softc = control_softc;
|
||||
cdb = (struct scsi_write_buffer *)ctsio->cdb;
|
||||
|
||||
if ((cdb->byte2 & RWB_MODE) != RWB_MODE_DATA) {
|
||||
@ -5655,7 +5739,7 @@ ctl_write_buffer(struct ctl_scsiio *ctsio)
|
||||
len = scsi_3btoul(cdb->length);
|
||||
buffer_offset = scsi_3btoul(cdb->offset);
|
||||
|
||||
if (len > sizeof(lun->write_buffer)) {
|
||||
if (buffer_offset + len > sizeof(lun->write_buffer)) {
|
||||
ctl_set_invalid_field(ctsio,
|
||||
/*sks_valid*/ 1,
|
||||
/*command*/ 1,
|
||||
@ -5666,23 +5750,12 @@ ctl_write_buffer(struct ctl_scsiio *ctsio)
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
if (buffer_offset != 0) {
|
||||
ctl_set_invalid_field(ctsio,
|
||||
/*sks_valid*/ 1,
|
||||
/*command*/ 1,
|
||||
/*field*/ 3,
|
||||
/*bit_valid*/ 0,
|
||||
/*bit*/ 0);
|
||||
ctl_done((union ctl_io *)ctsio);
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've got a kernel request that hasn't been malloced yet,
|
||||
* malloc it and tell the caller the data buffer is here.
|
||||
*/
|
||||
if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) {
|
||||
ctsio->kern_data_ptr = lun->write_buffer;
|
||||
ctsio->kern_data_ptr = lun->write_buffer + buffer_offset;
|
||||
ctsio->kern_data_len = len;
|
||||
ctsio->kern_total_len = len;
|
||||
ctsio->kern_data_resid = 0;
|
||||
@ -6893,6 +6966,7 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -6952,6 +7026,7 @@ ctl_read_capacity(struct ctl_scsiio *ctsio)
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -7014,6 +7089,7 @@ ctl_read_capacity_16(struct ctl_scsiio *ctsio)
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -7184,6 +7260,7 @@ ctl_maintenance_in(struct ctl_scsiio *ctsio)
|
||||
}
|
||||
}
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
|
||||
CTL_DEBUG_PRINT(("buf = %x %x %x %x %x %x %x %x\n",
|
||||
@ -7409,6 +7486,7 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
|
||||
}
|
||||
mtx_unlock(&lun->lun_lock);
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
|
||||
CTL_DEBUG_PRINT(("buf = %x %x %x %x %x %x %x %x\n",
|
||||
@ -9120,6 +9198,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
|
||||
*/
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9246,7 +9325,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
|
||||
* parameter data.
|
||||
*/
|
||||
ctsio->sense_len = 0;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9275,6 +9354,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
|
||||
* autosense in this case. We're reporting sense as parameter data.
|
||||
*/
|
||||
ctsio->sense_len = 0;
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9362,6 +9442,7 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9417,6 +9498,7 @@ ctl_inquiry_evpd_serial(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
}
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9602,6 +9684,7 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9658,6 +9741,7 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length);
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9707,6 +9791,7 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
lbp_ptr->flags = SVPD_LBP_UNMAP | SVPD_LBP_WS16 | SVPD_LBP_WS10;
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
@ -9989,6 +10074,7 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
if (ctsio->kern_data_len > 0) {
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
} else {
|
||||
|
@ -314,12 +314,15 @@ struct ctl_cmd_entry ctl_cmd_table[] =
|
||||
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
|
||||
|
||||
/* 3B WRITE BUFFER */
|
||||
{ctl_write_buffer, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_PROC |
|
||||
{ctl_write_buffer, CTL_SERIDX_MD_SEL, CTL_CMD_FLAG_OK_ON_BOTH |
|
||||
CTL_FLAG_DATA_OUT,
|
||||
CTL_LUN_PAT_NONE},
|
||||
|
||||
/* 3C READ BUFFER */
|
||||
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
|
||||
{ctl_read_buffer, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_BOTH |
|
||||
CTL_FLAG_DATA_IN |
|
||||
CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
|
||||
CTL_LUN_PAT_NONE},
|
||||
|
||||
/* 3D UPDATE BLOCK */
|
||||
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
|
||||
|
@ -2239,6 +2239,7 @@ cfiscsi_devid(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
|
@ -476,6 +476,7 @@ int ctl_scsi_reserve(struct ctl_scsiio *ctsio);
|
||||
int ctl_start_stop(struct ctl_scsiio *ctsio);
|
||||
int ctl_sync_cache(struct ctl_scsiio *ctsio);
|
||||
int ctl_format(struct ctl_scsiio *ctsio);
|
||||
int ctl_read_buffer(struct ctl_scsiio *ctsio);
|
||||
int ctl_write_buffer(struct ctl_scsiio *ctsio);
|
||||
int ctl_write_same(struct ctl_scsiio *ctsio);
|
||||
int ctl_unmap(struct ctl_scsiio *ctsio);
|
||||
|
Loading…
Reference in New Issue
Block a user