summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl/ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/ctl/ctl.c')
-rw-r--r--sys/cam/ctl/ctl.c537
1 files changed, 472 insertions, 65 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 91c9fdb..1364f3c 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam.h>
#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_cd.h>
#include <cam/scsi/scsi_da.h>
#include <cam/ctl/ctl_io.h>
#include <cam/ctl/ctl.h>
@@ -3821,8 +3822,14 @@ ctl_init_page_index(struct ctl_lun *lun)
for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
page_index = &lun->mode_pages.index[i];
- if (lun->be_lun->lun_type != T_DIRECT &&
- (page_index->page_flags & CTL_PAGE_FLAG_DISK_ONLY))
+ if (lun->be_lun->lun_type == T_DIRECT &&
+ (page_index->page_flags & CTL_PAGE_FLAG_DIRECT) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_PROCESSOR &&
+ (page_index->page_flags & CTL_PAGE_FLAG_PROC) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_CDROM &&
+ (page_index->page_flags & CTL_PAGE_FLAG_CDROM) == 0)
continue;
switch (page_index->page_code & SMPH_PC_MASK) {
@@ -4207,8 +4214,14 @@ ctl_init_log_page_index(struct ctl_lun *lun)
for (i = 0, j = 0, k = 0; i < CTL_NUM_LOG_PAGES; i++) {
page_index = &lun->log_pages.index[i];
- if (lun->be_lun->lun_type != T_DIRECT &&
- (page_index->page_flags & CTL_PAGE_FLAG_DISK_ONLY))
+ if (lun->be_lun->lun_type == T_DIRECT &&
+ (page_index->page_flags & CTL_PAGE_FLAG_DIRECT) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_PROCESSOR &&
+ (page_index->page_flags & CTL_PAGE_FLAG_PROC) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_CDROM &&
+ (page_index->page_flags & CTL_PAGE_FLAG_CDROM) == 0)
continue;
if (page_index->page_code == SLS_LOGICAL_BLOCK_PROVISIONING &&
@@ -4284,7 +4297,7 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
struct ctl_lun *nlun, *lun;
struct scsi_vpd_id_descriptor *desc;
struct scsi_vpd_id_t10 *t10id;
- const char *eui, *naa, *scsiname, *vendor;
+ const char *eui, *naa, *scsiname, *vendor, *value;
int lun_number, i, lun_malloced;
int devidlen, idlen1, idlen2 = 0, len;
@@ -4296,8 +4309,8 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
*/
switch (be_lun->lun_type) {
case T_DIRECT:
- break;
case T_PROCESSOR:
+ case T_CDROM:
break;
case T_SEQUENTIAL:
case T_CHANGER:
@@ -4450,6 +4463,13 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
if (be_lun->flags & CTL_LUN_FLAG_PRIMARY)
lun->flags |= CTL_LUN_PRIMARY_SC;
+ value = ctl_get_opt(&be_lun->options, "removable");
+ if (value != NULL) {
+ if (strcmp(value, "on") == 0)
+ lun->flags |= CTL_LUN_REMOVABLE;
+ } else if (be_lun->lun_type == T_CDROM)
+ lun->flags |= CTL_LUN_REMOVABLE;
+
lun->ctl_softc = ctl_softc;
#ifdef CTL_TIME_IO
lun->last_busy = getsbinuptime();
@@ -5126,14 +5146,14 @@ ctl_start_stop(struct ctl_scsiio *ctsio)
}
}
- /*
- * If there is no backend on this device, we can't start or stop
- * it. In theory we shouldn't get any start/stop commands in the
- * first place at this level if the LUN doesn't have a backend.
- * That should get stopped by the command decode code.
- */
- if (lun->backend == NULL) {
- ctl_set_invalid_opcode(ctsio);
+ if ((cdb->how & SSS_LOEJ) &&
+ (lun->flags & CTL_LUN_REMOVABLE) == 0) {
+ ctl_set_invalid_field(ctsio,
+ /*sks_valid*/ 1,
+ /*command*/ 1,
+ /*field*/ 4,
+ /*bit_valid*/ 1,
+ /*bit*/ 1);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
}
@@ -5163,6 +5183,26 @@ ctl_start_stop(struct ctl_scsiio *ctsio)
return (retval);
}
+int
+ctl_prevent_allow(struct ctl_scsiio *ctsio)
+{
+ struct ctl_lun *lun;
+ int retval;
+
+ CTL_DEBUG_PRINT(("ctl_prevent_allow\n"));
+
+ lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+
+ if ((lun->flags & CTL_LUN_REMOVABLE) == 0) {
+ ctl_set_invalid_opcode(ctsio);
+ ctl_done((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+ }
+
+ retval = lun->backend->config_write((union ctl_io *)ctsio);
+ return (retval);
+}
+
/*
* We support the SYNCHRONIZE CACHE command (10 and 16 byte versions), but
* we don't really do anything with the LBA and length fields if the user
@@ -5224,15 +5264,6 @@ ctl_sync_cache(struct ctl_scsiio *ctsio)
goto bailout;
}
- /*
- * If this LUN has no backend, we can't flush the cache anyway.
- */
- if (lun->backend == NULL) {
- ctl_set_invalid_opcode(ctsio);
- ctl_done((union ctl_io *)ctsio);
- goto bailout;
- }
-
lbalen = (struct ctl_lba_len_flags *)&ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
lbalen->lba = starting_lba;
lbalen->len = block_count;
@@ -5935,13 +5966,18 @@ do_next_page:
* XXX KDM should we do something with the block descriptor?
*/
for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
-
- if (lun->be_lun->lun_type != T_DIRECT &&
- (lun->mode_pages.index[i].page_flags &
- CTL_PAGE_FLAG_DISK_ONLY))
+ page_index = &lun->mode_pages.index[i];
+ if (lun->be_lun->lun_type == T_DIRECT &&
+ (page_index->page_flags & CTL_PAGE_FLAG_DIRECT) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_PROCESSOR &&
+ (page_index->page_flags & CTL_PAGE_FLAG_PROC) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_CDROM &&
+ (page_index->page_flags & CTL_PAGE_FLAG_CDROM) == 0)
continue;
- if ((lun->mode_pages.index[i].page_code & SMPH_PC_MASK) !=
+ if ((page_index->page_code & SMPH_PC_MASK) !=
(page_header->page_code & SMPH_PC_MASK))
continue;
@@ -5949,9 +5985,8 @@ do_next_page:
* If neither page has a subpage code, then we've got a
* match.
*/
- if (((lun->mode_pages.index[i].page_code & SMPH_SPF) == 0)
+ if (((page_index->page_code & SMPH_SPF) == 0)
&& ((page_header->page_code & SMPH_SPF) == 0)) {
- page_index = &lun->mode_pages.index[i];
page_len = page_header->page_length;
break;
}
@@ -5960,15 +5995,12 @@ do_next_page:
* If both pages have subpages, then the subpage numbers
* have to match.
*/
- if ((lun->mode_pages.index[i].page_code & SMPH_SPF)
+ if ((page_index->page_code & SMPH_SPF)
&& (page_header->page_code & SMPH_SPF)) {
struct scsi_mode_page_header_sp *sph;
sph = (struct scsi_mode_page_header_sp *)page_header;
-
- if (lun->mode_pages.index[i].subpage ==
- sph->subpage) {
- page_index = &lun->mode_pages.index[i];
+ if (page_index->subpage == sph->subpage) {
page_len = scsi_2btoul(sph->page_length);
break;
}
@@ -5979,7 +6011,7 @@ do_next_page:
* If we couldn't find the page, or if we don't have a mode select
* handler for it, send back an error to the user.
*/
- if ((page_index == NULL)
+ if ((i >= CTL_NUM_MODE_PAGES)
|| (page_index->select_handler == NULL)) {
ctl_set_invalid_field(ctsio,
/*sks_valid*/ 1,
@@ -6238,7 +6270,6 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
dbd = 0;
llba = 0;
block_desc = NULL;
- page_index = NULL;
CTL_DEBUG_PRINT(("ctl_mode_sense\n"));
@@ -6315,26 +6346,33 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
}
for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
- if (lun->be_lun->lun_type != T_DIRECT &&
- (lun->mode_pages.index[i].page_flags &
- CTL_PAGE_FLAG_DISK_ONLY))
+ page_index = &lun->mode_pages.index[i];
+
+ /* Make sure the page is supported for this dev type */
+ if (lun->be_lun->lun_type == T_DIRECT &&
+ (page_index->page_flags & CTL_PAGE_FLAG_DIRECT) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_PROCESSOR &&
+ (page_index->page_flags & CTL_PAGE_FLAG_PROC) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_CDROM &&
+ (page_index->page_flags & CTL_PAGE_FLAG_CDROM) == 0)
continue;
/*
* We don't use this subpage if the user didn't
* request all subpages.
*/
- if ((lun->mode_pages.index[i].subpage != 0)
+ if ((page_index->subpage != 0)
&& (subpage == SMS_SUBPAGE_PAGE_0))
continue;
#if 0
printf("found page %#x len %d\n",
- lun->mode_pages.index[i].page_code &
- SMPH_PC_MASK,
- lun->mode_pages.index[i].page_len);
+ page_index->page_code & SMPH_PC_MASK,
+ page_index->page_len);
#endif
- page_len += lun->mode_pages.index[i].page_len;
+ page_len += page_index->page_len;
}
break;
}
@@ -6344,30 +6382,35 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
page_len = 0;
for (i = 0; i < CTL_NUM_MODE_PAGES; i++) {
+ page_index = &lun->mode_pages.index[i];
+
+ /* Make sure the page is supported for this dev type */
+ if (lun->be_lun->lun_type == T_DIRECT &&
+ (page_index->page_flags & CTL_PAGE_FLAG_DIRECT) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_PROCESSOR &&
+ (page_index->page_flags & CTL_PAGE_FLAG_PROC) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_CDROM &&
+ (page_index->page_flags & CTL_PAGE_FLAG_CDROM) == 0)
+ continue;
+
/* Look for the right page code */
- if ((lun->mode_pages.index[i].page_code &
- SMPH_PC_MASK) != page_code)
+ if ((page_index->page_code & SMPH_PC_MASK) != page_code)
continue;
/* Look for the right subpage or the subpage wildcard*/
- if ((lun->mode_pages.index[i].subpage != subpage)
+ if ((page_index->subpage != subpage)
&& (subpage != SMS_SUBPAGE_ALL))
continue;
- /* Make sure the page is supported for this dev type */
- if (lun->be_lun->lun_type != T_DIRECT &&
- (lun->mode_pages.index[i].page_flags &
- CTL_PAGE_FLAG_DISK_ONLY))
- continue;
-
#if 0
printf("found page %#x len %d\n",
- lun->mode_pages.index[i].page_code &
- SMPH_PC_MASK,
- lun->mode_pages.index[i].page_len);
+ page_index->page_code & SMPH_PC_MASK,
+ page_index->page_len);
#endif
- page_len += lun->mode_pages.index[i].page_len;
+ page_len += page_index->page_len;
}
if (page_len == 0) {
@@ -6475,9 +6518,14 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
struct ctl_page_index *page_index;
page_index = &lun->mode_pages.index[i];
-
- if (lun->be_lun->lun_type != T_DIRECT &&
- (page_index->page_flags & CTL_PAGE_FLAG_DISK_ONLY))
+ if (lun->be_lun->lun_type == T_DIRECT &&
+ (page_index->page_flags & CTL_PAGE_FLAG_DIRECT) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_PROCESSOR &&
+ (page_index->page_flags & CTL_PAGE_FLAG_PROC) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_CDROM &&
+ (page_index->page_flags & CTL_PAGE_FLAG_CDROM) == 0)
continue;
/*
@@ -6525,8 +6573,14 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
continue;
/* Make sure the page is supported for this dev type */
- if (lun->be_lun->lun_type != T_DIRECT &&
- (page_index->page_flags & CTL_PAGE_FLAG_DISK_ONLY))
+ if (lun->be_lun->lun_type == T_DIRECT &&
+ (page_index->page_flags & CTL_PAGE_FLAG_DIRECT) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_PROCESSOR &&
+ (page_index->page_flags & CTL_PAGE_FLAG_PROC) == 0)
+ continue;
+ if (lun->be_lun->lun_type == T_CDROM &&
+ (page_index->page_flags & CTL_PAGE_FLAG_CDROM) == 0)
continue;
/*
@@ -10052,6 +10106,8 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
inq_ptr->device = (SID_QUAL_LU_OFFLINE << 5) |
lun->be_lun->lun_type;
}
+ if (lun->flags & CTL_LUN_REMOVABLE)
+ inq_ptr->dev_qual2 |= SID_RMB;
} else
inq_ptr->device = (SID_QUAL_BAD_LU << 5) | T_NODEVICE;
@@ -10116,6 +10172,10 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
strncpy(inq_ptr->product, CTL_PROCESSOR_PRODUCT,
sizeof(inq_ptr->product));
break;
+ case T_CDROM:
+ strncpy(inq_ptr->product, CTL_CDROM_PRODUCT,
+ sizeof(inq_ptr->product));
+ break;
default:
strncpy(inq_ptr->product, CTL_UNKNOWN_PRODUCT,
sizeof(inq_ptr->product));
@@ -10178,6 +10238,11 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
scsi_ulto2b(0x0600, inq_ptr->version4);
break;
case T_PROCESSOR:
+ break;
+ case T_CDROM:
+ /* MMC-6 (no version claimed) */
+ scsi_ulto2b(0x04E0, inq_ptr->version4);
+ break;
default:
break;
}
@@ -10217,6 +10282,344 @@ ctl_inquiry(struct ctl_scsiio *ctsio)
return (retval);
}
+int
+ctl_get_config(struct ctl_scsiio *ctsio)
+{
+ struct scsi_get_config_header *hdr;
+ struct scsi_get_config_feature *feature;
+ struct scsi_get_config *cdb;
+ struct ctl_lun *lun;
+ uint32_t alloc_len, data_len;
+ int rt, starting;
+
+ lun = ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ cdb = (struct scsi_get_config *)ctsio->cdb;
+ rt = (cdb->rt & SGC_RT_MASK);
+ starting = scsi_2btoul(cdb->starting_feature);
+ alloc_len = scsi_2btoul(cdb->length);
+
+ data_len = sizeof(struct scsi_get_config_header) +
+ sizeof(struct scsi_get_config_feature) + 8 +
+ sizeof(struct scsi_get_config_feature) + 8 +
+ sizeof(struct scsi_get_config_feature) + 4 +
+ sizeof(struct scsi_get_config_feature) + 4 +
+ sizeof(struct scsi_get_config_feature) + 8 +
+ sizeof(struct scsi_get_config_feature) +
+ sizeof(struct scsi_get_config_feature) + 4 +
+ sizeof(struct scsi_get_config_feature) + 4;
+ ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
+ ctsio->kern_sg_entries = 0;
+ ctsio->kern_data_resid = 0;
+ ctsio->kern_rel_offset = 0;
+
+ hdr = (struct scsi_get_config_header *)ctsio->kern_data_ptr;
+ if (lun->flags & CTL_LUN_OFFLINE)
+ scsi_ulto2b(0x0000, hdr->current_profile);
+ else
+ scsi_ulto2b(0x0010, hdr->current_profile);
+ feature = (struct scsi_get_config_feature *)(hdr + 1);
+
+ if (starting > 0x001f)
+ goto done;
+ if (starting > 0x001e)
+ goto f1f;
+ if (starting > 0x001d)
+ goto f1e;
+ if (starting > 0x0010)
+ goto f1d;
+ if (starting > 0x0003)
+ goto f10;
+ if (starting > 0x0002)
+ goto f3;
+ if (starting > 0x0001)
+ goto f2;
+ if (starting > 0x0000)
+ goto f1;
+
+ /* Profile List */
+ scsi_ulto2b(0x0000, feature->feature_code);
+ feature->flags = SGC_F_PERSISTENT | SGC_F_CURRENT;
+ feature->add_length = 8;
+ scsi_ulto2b(0x0008, &feature->feature_data[0]); /* CD-ROM */
+ feature->feature_data[2] = 0x00;
+ scsi_ulto2b(0x0010, &feature->feature_data[4]); /* DVD-ROM */
+ feature->feature_data[6] = 0x01;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+f1: /* Core */
+ scsi_ulto2b(0x0001, feature->feature_code);
+ feature->flags = 0x08 | SGC_F_PERSISTENT | SGC_F_CURRENT;
+ feature->add_length = 8;
+ scsi_ulto4b(0x00000000, &feature->feature_data[0]);
+ feature->feature_data[4] = 0x03;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+f2: /* Morphing */
+ scsi_ulto2b(0x0002, feature->feature_code);
+ feature->flags = 0x04 | SGC_F_PERSISTENT | SGC_F_CURRENT;
+ feature->add_length = 4;
+ feature->feature_data[0] = 0x02;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+f3: /* Removable Medium */
+ scsi_ulto2b(0x0003, feature->feature_code);
+ feature->flags = 0x04 | SGC_F_PERSISTENT | SGC_F_CURRENT;
+ feature->add_length = 4;
+ feature->feature_data[0] = 0x39;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+ if (rt == SGC_RT_CURRENT && (lun->flags & CTL_LUN_OFFLINE))
+ goto done;
+
+f10: /* Random Read */
+ scsi_ulto2b(0x0010, feature->feature_code);
+ feature->flags = 0x00;
+ if ((lun->flags & CTL_LUN_OFFLINE) == 0)
+ feature->flags |= SGC_F_CURRENT;
+ feature->add_length = 8;
+ scsi_ulto4b(lun->be_lun->blocksize, &feature->feature_data[0]);
+ scsi_ulto2b(1, &feature->feature_data[4]);
+ feature->feature_data[6] = 0x00;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+f1d: /* Multi-Read */
+ scsi_ulto2b(0x001D, feature->feature_code);
+ feature->flags = 0x00;
+ if ((lun->flags & CTL_LUN_OFFLINE) == 0)
+ feature->flags |= SGC_F_CURRENT;
+ feature->add_length = 0;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+f1e: /* CD Read */
+ scsi_ulto2b(0x001E, feature->feature_code);
+ feature->flags = 0x00;
+ if ((lun->flags & CTL_LUN_OFFLINE) == 0)
+ feature->flags |= SGC_F_CURRENT;
+ feature->add_length = 4;
+ feature->feature_data[0] = 0x00;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+f1f: /* DVD Read */
+ scsi_ulto2b(0x001F, feature->feature_code);
+ feature->flags = 0x08;
+ if ((lun->flags & CTL_LUN_OFFLINE) == 0)
+ feature->flags |= SGC_F_CURRENT;
+ feature->add_length = 4;
+ feature->feature_data[0] = 0x01;
+ feature->feature_data[2] = 0x03;
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+
+done:
+ data_len = (uint8_t *)feature - (uint8_t *)hdr;
+ if (rt == SGC_RT_SPECIFIC && data_len > 4) {
+ feature = (struct scsi_get_config_feature *)(hdr + 1);
+ if (scsi_2btoul(feature->feature_code) == starting)
+ feature = (struct scsi_get_config_feature *)
+ &feature->feature_data[feature->add_length];
+ data_len = (uint8_t *)feature - (uint8_t *)hdr;
+ }
+ scsi_ulto4b(data_len - 4, hdr->data_length);
+ if (data_len < alloc_len) {
+ ctsio->residual = alloc_len - data_len;
+ ctsio->kern_data_len = data_len;
+ ctsio->kern_total_len = data_len;
+ } else {
+ ctsio->residual = 0;
+ ctsio->kern_data_len = alloc_len;
+ ctsio->kern_total_len = alloc_len;
+ }
+
+ ctl_set_success(ctsio);
+ ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+ ctsio->be_move_done = ctl_config_move_done;
+ ctl_datamove((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+}
+
+int
+ctl_get_event_status(struct ctl_scsiio *ctsio)
+{
+ struct scsi_get_event_status_header *hdr;
+ struct scsi_get_event_status *cdb;
+ struct ctl_lun *lun;
+ uint32_t alloc_len, data_len;
+ int notif_class;
+
+ lun = ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ cdb = (struct scsi_get_event_status *)ctsio->cdb;
+ if ((cdb->byte2 & SGESN_POLLED) == 0) {
+ ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1,
+ /*field*/ 1, /*bit_valid*/ 1, /*bit*/ 0);
+ ctl_done((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+ }
+ notif_class = cdb->notif_class;
+ alloc_len = scsi_2btoul(cdb->length);
+
+ data_len = sizeof(struct scsi_get_event_status_header);
+ ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
+ ctsio->kern_sg_entries = 0;
+ ctsio->kern_data_resid = 0;
+ ctsio->kern_rel_offset = 0;
+
+ if (data_len < alloc_len) {
+ ctsio->residual = alloc_len - data_len;
+ ctsio->kern_data_len = data_len;
+ ctsio->kern_total_len = data_len;
+ } else {
+ ctsio->residual = 0;
+ ctsio->kern_data_len = alloc_len;
+ ctsio->kern_total_len = alloc_len;
+ }
+
+ hdr = (struct scsi_get_event_status_header *)ctsio->kern_data_ptr;
+ scsi_ulto2b(0, hdr->descr_length);
+ hdr->nea_class = SGESN_NEA;
+ hdr->supported_class = 0;
+
+ ctl_set_success(ctsio);
+ ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+ ctsio->be_move_done = ctl_config_move_done;
+ ctl_datamove((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+}
+
+int
+ctl_mechanism_status(struct ctl_scsiio *ctsio)
+{
+ struct scsi_mechanism_status_header *hdr;
+ struct scsi_mechanism_status *cdb;
+ struct ctl_lun *lun;
+ uint32_t alloc_len, data_len;
+
+ lun = ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ cdb = (struct scsi_mechanism_status *)ctsio->cdb;
+ alloc_len = scsi_2btoul(cdb->length);
+
+ data_len = sizeof(struct scsi_mechanism_status_header);
+ ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
+ ctsio->kern_sg_entries = 0;
+ ctsio->kern_data_resid = 0;
+ ctsio->kern_rel_offset = 0;
+
+ if (data_len < alloc_len) {
+ ctsio->residual = alloc_len - data_len;
+ ctsio->kern_data_len = data_len;
+ ctsio->kern_total_len = data_len;
+ } else {
+ ctsio->residual = 0;
+ ctsio->kern_data_len = alloc_len;
+ ctsio->kern_total_len = alloc_len;
+ }
+
+ hdr = (struct scsi_mechanism_status_header *)ctsio->kern_data_ptr;
+ hdr->state1 = 0x00;
+ hdr->state2 = 0xe0;
+ scsi_ulto3b(0, hdr->lba);
+ hdr->slots_num = 0;
+ scsi_ulto2b(0, hdr->slots_length);
+
+ ctl_set_success(ctsio);
+ ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+ ctsio->be_move_done = ctl_config_move_done;
+ ctl_datamove((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+}
+
+static void
+ctl_ultomsf(uint32_t lba, uint8_t *buf)
+{
+
+ lba += 150;
+ buf[0] = 0;
+ buf[1] = bin2bcd((lba / 75) / 60);
+ buf[2] = bin2bcd((lba / 75) % 60);
+ buf[3] = bin2bcd(lba % 75);
+}
+
+int
+ctl_read_toc(struct ctl_scsiio *ctsio)
+{
+ struct scsi_read_toc_hdr *hdr;
+ struct scsi_read_toc_type01_descr *descr;
+ struct scsi_read_toc *cdb;
+ struct ctl_lun *lun;
+ uint32_t alloc_len, data_len;
+ int format, msf;
+
+ lun = ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ cdb = (struct scsi_read_toc *)ctsio->cdb;
+ msf = (cdb->byte2 & CD_MSF) != 0;
+ format = cdb->format;
+ alloc_len = scsi_2btoul(cdb->data_len);
+
+ data_len = sizeof(struct scsi_read_toc_hdr);
+ if (format == 0)
+ data_len += 2 * sizeof(struct scsi_read_toc_type01_descr);
+ else
+ data_len += sizeof(struct scsi_read_toc_type01_descr);
+ ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
+ ctsio->kern_sg_entries = 0;
+ ctsio->kern_data_resid = 0;
+ ctsio->kern_rel_offset = 0;
+
+ if (data_len < alloc_len) {
+ ctsio->residual = alloc_len - data_len;
+ ctsio->kern_data_len = data_len;
+ ctsio->kern_total_len = data_len;
+ } else {
+ ctsio->residual = 0;
+ ctsio->kern_data_len = alloc_len;
+ ctsio->kern_total_len = alloc_len;
+ }
+
+ hdr = (struct scsi_read_toc_hdr *)ctsio->kern_data_ptr;
+ if (format == 0) {
+ scsi_ulto2b(0x12, hdr->data_length);
+ hdr->first = 1;
+ hdr->last = 1;
+ descr = (struct scsi_read_toc_type01_descr *)(hdr + 1);
+ descr->addr_ctl = 0x14;
+ descr->track_number = 1;
+ if (msf)
+ ctl_ultomsf(0, descr->track_start);
+ else
+ scsi_ulto4b(0, descr->track_start);
+ descr++;
+ descr->addr_ctl = 0x14;
+ descr->track_number = 0xaa;
+ if (msf)
+ ctl_ultomsf(lun->be_lun->maxlba+1, descr->track_start);
+ else
+ scsi_ulto4b(lun->be_lun->maxlba+1, descr->track_start);
+ } else {
+ scsi_ulto2b(0x0a, hdr->data_length);
+ hdr->first = 1;
+ hdr->last = 1;
+ descr = (struct scsi_read_toc_type01_descr *)(hdr + 1);
+ descr->addr_ctl = 0x14;
+ descr->track_number = 1;
+ if (msf)
+ ctl_ultomsf(0, descr->track_start);
+ else
+ scsi_ulto4b(0, descr->track_start);
+ }
+
+ ctl_set_success(ctsio);
+ ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+ ctsio->be_move_done = ctl_config_move_done;
+ ctl_datamove((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+}
+
/*
* For known CDB types, parse the LBA and length.
*/
@@ -11266,12 +11669,16 @@ ctl_cmd_applicable(uint8_t lun_type, const struct ctl_cmd_entry *entry)
{
switch (lun_type) {
+ case T_DIRECT:
+ if ((entry->flags & CTL_CMD_FLAG_OK_ON_DIRECT) == 0)
+ return (0);
+ break;
case T_PROCESSOR:
if ((entry->flags & CTL_CMD_FLAG_OK_ON_PROC) == 0)
return (0);
break;
- case T_DIRECT:
- if ((entry->flags & CTL_CMD_FLAG_OK_ON_SLUN) == 0)
+ case T_CDROM:
+ if ((entry->flags & CTL_CMD_FLAG_OK_ON_CDROM) == 0)
return (0);
break;
default:
OpenPOWER on IntegriCloud