Add support for Long LBA mode parameter block descriptor.

It is formally required for SBC Base 2016 feature set.

MFC after:	2 weeks
This commit is contained in:
Alexander Motin 2019-07-26 19:14:12 +00:00
parent ba9b2ede8a
commit ed3bf01599
2 changed files with 62 additions and 30 deletions

View File

@ -6365,13 +6365,12 @@ int
ctl_mode_sense(struct ctl_scsiio *ctsio)
{
struct ctl_lun *lun = CTL_LUN(ctsio);
int pc, page_code, dbd, subpage;
int alloc_len, page_len, header_len, total_len;
struct scsi_mode_block_descr *block_desc;
int pc, page_code, llba, subpage;
int alloc_len, page_len, header_len, bd_len, total_len;
void *block_desc;
struct ctl_page_index *page_index;
dbd = 0;
block_desc = NULL;
llba = 0;
CTL_DEBUG_PRINT(("ctl_mode_sense\n"));
@ -6383,9 +6382,10 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
header_len = sizeof(struct scsi_mode_hdr_6);
if (cdb->byte2 & SMS_DBD)
dbd = 1;
bd_len = 0;
else
header_len += sizeof(struct scsi_mode_block_descr);
bd_len = sizeof(struct scsi_mode_block_descr);
header_len += bd_len;
pc = (cdb->page & SMS_PAGE_CTRL_MASK) >> 6;
page_code = cdb->page & SMS_PAGE_CODE;
@ -6399,11 +6399,18 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
cdb = (struct scsi_mode_sense_10 *)ctsio->cdb;
header_len = sizeof(struct scsi_mode_hdr_10);
if (cdb->byte2 & SMS_DBD) {
bd_len = 0;
} else if (lun->be_lun->lun_type == T_DIRECT) {
if (cdb->byte2 & SMS10_LLBAA) {
llba = 1;
bd_len = sizeof(struct scsi_mode_block_descr_dlong);
} else
bd_len = sizeof(struct scsi_mode_block_descr_dshort);
} else
bd_len = sizeof(struct scsi_mode_block_descr);
header_len += bd_len;
if (cdb->byte2 & SMS_DBD)
dbd = 1;
else
header_len += sizeof(struct scsi_mode_block_descr);
pc = (cdb->page & SMS_PAGE_CTRL_MASK) >> 6;
page_code = cdb->page & SMS_PAGE_CODE;
subpage = cdb->subpage;
@ -6536,12 +6543,8 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
(lun->MODE_CTRL.eca_and_aen & SCP_SWP) != 0)
header->dev_specific |= 0x80; /* WP */
}
if (dbd)
header->block_descr_len = 0;
else
header->block_descr_len =
sizeof(struct scsi_mode_block_descr);
block_desc = (struct scsi_mode_block_descr *)&header[1];
header->block_descr_len = bd_len;
block_desc = &header[1];
break;
}
case MODE_SENSE_10: {
@ -6558,12 +6561,10 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
(lun->MODE_CTRL.eca_and_aen & SCP_SWP) != 0)
header->dev_specific |= 0x80; /* WP */
}
if (dbd)
scsi_ulto2b(0, header->block_descr_len);
else
scsi_ulto2b(sizeof(struct scsi_mode_block_descr),
header->block_descr_len);
block_desc = (struct scsi_mode_block_descr *)&header[1];
if (llba)
header->flags |= SMH_LONGLBA;
scsi_ulto2b(bd_len, header->block_descr_len);
block_desc = &header[1];
break;
}
default:
@ -6574,12 +6575,27 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
* If we've got a disk, use its blocksize in the block
* descriptor. Otherwise, just set it to 0.
*/
if (dbd == 0) {
if (lun->be_lun->lun_type == T_DIRECT)
scsi_ulto3b(lun->be_lun->blocksize,
block_desc->block_len);
else
scsi_ulto3b(0, block_desc->block_len);
if (bd_len > 0) {
if (lun->be_lun->lun_type == T_DIRECT) {
if (llba) {
struct scsi_mode_block_descr_dlong *bd = block_desc;
if (lun->be_lun->maxlba != 0)
scsi_u64to8b(lun->be_lun->maxlba + 1,
bd->num_blocks);
scsi_ulto4b(lun->be_lun->blocksize,
bd->block_len);
} else {
struct scsi_mode_block_descr_dshort *bd = block_desc;
if (lun->be_lun->maxlba != 0)
scsi_ulto4b(MIN(lun->be_lun->maxlba+1,
UINT32_MAX), bd->num_blocks);
scsi_ulto3b(lun->be_lun->blocksize,
bd->block_len);
}
} else {
struct scsi_mode_block_descr *bd = block_desc;
scsi_ulto3b(0, bd->block_len);
}
}
switch (page_code) {

View File

@ -264,7 +264,9 @@ struct scsi_mode_hdr_10
u_int8_t datalen[2];
u_int8_t medium_type;
u_int8_t dev_specific;
u_int8_t reserved[2];
u_int8_t flags;
#define SMH_LONGLBA 0x01
u_int8_t reserved;
u_int8_t block_descr_len[2];
};
@ -276,6 +278,20 @@ struct scsi_mode_block_descr
u_int8_t block_len[3];
};
struct scsi_mode_block_descr_dshort
{
u_int8_t num_blocks[4];
u_int8_t reserved;
u_int8_t block_len[3];
};
struct scsi_mode_block_descr_dlong
{
u_int8_t num_blocks[8];
u_int8_t reserved[4];
u_int8_t block_len[4];
};
struct scsi_per_res_in
{
u_int8_t opcode;