diff options
author | mav <mav@FreeBSD.org> | 2015-10-05 11:30:18 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2015-10-05 11:30:18 +0000 |
commit | 3e85febb126fcf3fc33ad9460816254312716ff6 (patch) | |
tree | 92e9b1a78fb5ea854e3363a3c1ee70c0de6022ac | |
parent | c019c6978215679df0e5954ea514dbe52fb17c8e (diff) | |
download | FreeBSD-src-3e85febb126fcf3fc33ad9460816254312716ff6.zip FreeBSD-src-3e85febb126fcf3fc33ad9460816254312716ff6.tar.gz |
MFC r288310: Add to CTL initial support for CDROMs and removable devices.
Relnotes: yes
-rw-r--r-- | share/man/man4/ctl.4 | 4 | ||||
-rw-r--r-- | sys/cam/ctl/README.ctl.txt | 8 | ||||
-rw-r--r-- | sys/cam/ctl/ctl.c | 537 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend_block.c | 20 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend_ramdisk.c | 11 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_cmd_table.c | 105 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_private.h | 50 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_cd.h | 99 | ||||
-rw-r--r-- | usr.sbin/ctladm/ctladm.8 | 7 | ||||
-rw-r--r-- | usr.sbin/ctld/ctl.conf.5 | 6 | ||||
-rw-r--r-- | usr.sbin/ctld/ctld.c | 7 | ||||
-rw-r--r-- | usr.sbin/ctld/ctld.h | 2 | ||||
-rw-r--r-- | usr.sbin/ctld/kernel.c | 6 | ||||
-rw-r--r-- | usr.sbin/ctld/parse.y | 31 | ||||
-rw-r--r-- | usr.sbin/ctld/token.l | 1 |
15 files changed, 754 insertions, 140 deletions
diff --git a/share/man/man4/ctl.4 b/share/man/man4/ctl.4 index 279764a..7e6cb8d 100644 --- a/share/man/man4/ctl.4 +++ b/share/man/man4/ctl.4 @@ -24,7 +24,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd September 12, 2015 +.Dd September 27, 2015 .Dt CTL 4 .Os .Sh NAME @@ -53,7 +53,7 @@ It supports features such as: .Pp .Bl -bullet -compact .It -Disk and processor device emulation +Disk, processor and cdrom device emulation .It Tagged queueing .It diff --git a/sys/cam/ctl/README.ctl.txt b/sys/cam/ctl/README.ctl.txt index c37527b..89030e2 100644 --- a/sys/cam/ctl/README.ctl.txt +++ b/sys/cam/ctl/README.ctl.txt @@ -19,9 +19,9 @@ Userland Commands Introduction: ============ -CTL is a disk and processor device emulation subsystem originally written -for Copan Systems under Linux starting in 2003. It has been shipping in -Copan (now SGI) products since 2005. +CTL is a disk, processor and cdrom device emulation subsystem originally +written for Copan Systems under Linux starting in 2003. It has been +shipping in Copan (now SGI) products since 2005. It was ported to FreeBSD in 2008, and thanks to an agreement between SGI (who acquired Copan's assets in 2010) and Spectra Logic in 2010, CTL is @@ -31,7 +31,7 @@ that Spectra would work to get CTL into the FreeBSD tree. Features: ======== - - Disk and processor device emulation. + - Disk, processor and cdrom device emulation. - Tagged queueing - SCSI task attribute support (ordered, head of queue, simple tags) - SCSI implicit command ordering support. (e.g. if a read follows a mode 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: diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index 51215ac..71ea521 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -1872,6 +1872,8 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) */ if (params->blocksize_bytes != 0) cbe_lun->blocksize = params->blocksize_bytes; + else if (cbe_lun->lun_type == T_CDROM) + cbe_lun->blocksize = 2048; else cbe_lun->blocksize = 512; be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize; @@ -2000,7 +2002,9 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) "requested blocksize %u < backing device " "blocksize %u", params->blocksize_bytes, tmp); return (EINVAL); - } else + } else if (cbe_lun->lun_type == T_CDROM) + cbe_lun->blocksize = MAX(tmp, 2048); + else cbe_lun->blocksize = tmp; error = csw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&otmp, FREAD, @@ -2171,7 +2175,10 @@ ctl_be_block_open(struct ctl_be_block_softc *softc, flags = FREAD; value = ctl_get_opt(&cbe_lun->options, "readonly"); - if (value == NULL || strcmp(value, "on") != 0) + if (value != NULL) { + if (strcmp(value, "on") != 0) + flags |= FWRITE; + } else if (cbe_lun->lun_type == T_DIRECT) flags |= FWRITE; again: @@ -2287,10 +2294,13 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; - if (cbe_lun->lun_type == T_DIRECT) { + if (cbe_lun->lun_type == T_DIRECT || + cbe_lun->lun_type == T_CDROM) { be_lun->size_bytes = params->lun_size_bytes; if (params->blocksize_bytes != 0) cbe_lun->blocksize = params->blocksize_bytes; + else if (cbe_lun->lun_type == T_CDROM) + cbe_lun->blocksize = 2048; else cbe_lun->blocksize = 512; be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize; @@ -2775,6 +2785,10 @@ ctl_be_block_config_write(union ctl_io *io) ctl_config_write_done(io); break; } + case PREVENT_ALLOW: + ctl_set_success(&io->scsiio); + ctl_config_write_done(io); + break; default: ctl_set_invalid_opcode(&io->scsiio); ctl_config_write_done(io); diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c index caf3059..efa41e6 100644 --- a/sys/cam/ctl/ctl_backend_ramdisk.c +++ b/sys/cam/ctl/ctl_backend_ramdisk.c @@ -530,9 +530,12 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc, } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; - if (cbe_lun->lun_type == T_DIRECT) { + if (cbe_lun->lun_type == T_DIRECT || + cbe_lun->lun_type == T_CDROM) { if (params->blocksize_bytes != 0) cbe_lun->blocksize = params->blocksize_bytes; + else if (cbe_lun->lun_type == T_CDROM) + cbe_lun->blocksize = 2048; else cbe_lun->blocksize = 512; if (params->lun_size_bytes < cbe_lun->blocksize) { @@ -556,7 +559,10 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc, if (value != NULL && strcmp(value, "on") == 0) cbe_lun->flags |= CTL_LUN_FLAG_UNMAP; value = ctl_get_opt(&cbe_lun->options, "readonly"); - if (value != NULL && strcmp(value, "on") == 0) + if (value != NULL) { + if (strcmp(value, "on") == 0) + cbe_lun->flags |= CTL_LUN_FLAG_READONLY; + } else if (cbe_lun->lun_type != T_DIRECT) cbe_lun->flags |= CTL_LUN_FLAG_READONLY; cbe_lun->serseq = CTL_LUN_SERSEQ_OFF; value = ctl_get_opt(&cbe_lun->options, "serseq"); @@ -896,6 +902,7 @@ ctl_backend_ramdisk_config_write(union ctl_io *io) ctl_config_write_done(io); break; } + case PREVENT_ALLOW: case WRITE_SAME_10: case WRITE_SAME_16: case UNMAP: diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c index 94b3b6e..e7f298e 100644 --- a/sys/cam/ctl/ctl_cmd_table.c +++ b/sys/cam/ctl/ctl_cmd_table.c @@ -255,7 +255,7 @@ const struct ctl_cmd_entry ctl_cmd_table_83[32] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 10 POPULATE TOKEN */ -{ctl_populate_token, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_populate_token, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_NONE, @@ -263,7 +263,7 @@ const struct ctl_cmd_entry ctl_cmd_table_83[32] = 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, /* 11 WRITE USING TOKEN */ -{ctl_write_using_token, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_write_using_token, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 16, { 0x11, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, @@ -422,7 +422,7 @@ const struct ctl_cmd_entry ctl_cmd_table_9e[32] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 10 READ CAPACITY(16) */ -{ctl_read_capacity_16, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_read_capacity_16, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_CMD_FLAG_OK_ON_STOPPED | CTL_CMD_FLAG_OK_ON_INOPERABLE | CTL_FLAG_DATA_IN | @@ -434,7 +434,7 @@ const struct ctl_cmd_entry ctl_cmd_table_9e[32] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 12 GET LBA STATUS */ -{ctl_get_lba_status, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_get_lba_status, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, @@ -559,7 +559,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = CTL_LUN_PAT_NONE, 6, {0x01, 0, 0, 0xff, 0x07}}, /* 04 FORMAT UNIT */ -{ctl_format, CTL_SERIDX_FORMAT, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_format, CTL_SERIDX_FORMAT, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_CMD_FLAG_OK_ON_INOPERABLE | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 6, {0xff, 0, 0, 0, 0x07}}, @@ -574,7 +574,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 08 READ(6) */ -{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, 6, {0x1f, 0xff, 0xff, 0xff, 0x07}}, @@ -583,7 +583,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 0A WRITE(6) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 6, {0x1f, 0xff, 0xff, 0xff, 0x07}}, @@ -669,7 +669,8 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = CTL_LUN_PAT_NONE, 6, {0x08, 0xff, 0xff, 0xff, 0x07}}, /* 1B START STOP UNIT */ -{ctl_start_stop, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_start_stop, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_DIRECT | + CTL_CMD_FLAG_OK_ON_CDROM | CTL_CMD_FLAG_OK_ON_STOPPED | CTL_CMD_FLAG_OK_ON_INOPERABLE | CTL_FLAG_DATA_NONE | @@ -683,7 +684,12 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 1E PREVENT ALLOW MEDIUM REMOVAL */ -{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, +{ctl_prevent_allow, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_DIRECT | + CTL_CMD_FLAG_OK_ON_CDROM | + CTL_CMD_FLAG_OK_ON_STOPPED | + CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_FLAG_DATA_NONE, + CTL_LUN_PAT_NONE, 6, {0x01, 0, 0, 0x03, 0x07}}, /* 1F */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, @@ -704,7 +710,8 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 25 READ CAPACITY(10) */ -{ctl_read_capacity, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_SLUN| +{ctl_read_capacity, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_DIRECT | + CTL_CMD_FLAG_OK_ON_CDROM | CTL_CMD_FLAG_OK_ON_STOPPED | CTL_CMD_FLAG_OK_ON_INOPERABLE | CTL_FLAG_DATA_IN | @@ -718,7 +725,8 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 28 READ(10) */ -{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | + CTL_CMD_FLAG_OK_ON_CDROM | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, @@ -728,7 +736,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 2A WRITE(10) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 10, {0x1a, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}}, @@ -742,12 +750,12 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 2E WRITE AND VERIFY(10) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 10, {0x12, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}}, /* 2F VERIFY(10) */ -{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, @@ -769,7 +777,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 35 SYNCHRONIZE CACHE(10) */ -{ctl_sync_cache, CTL_SERIDX_SYNC, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_sync_cache, CTL_SERIDX_SYNC, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_NONE, CTL_LUN_PAT_WRITE, 10, {0x02, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}}, @@ -778,7 +786,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 37 READ DEFECT DATA(10) */ -{ctl_read_defect, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_read_defect, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_NONE, @@ -825,18 +833,22 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 41 WRITE SAME(10) */ -{ctl_write_same, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_write_same, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 10, {0x1a, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}}, /* 42 READ SUB-CHANNEL / UNMAP */ -{ctl_unmap, CTL_SERIDX_UNMAP, CTL_CMD_FLAG_OK_ON_SLUN | CTL_FLAG_DATA_OUT, +{ctl_unmap, CTL_SERIDX_UNMAP, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE, 10, {1, 0, 0, 0, 0, 0, 0xff, 0xff, 0x07}}, /* 43 READ TOC/PMA/ATIP */ -{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, +{ctl_read_toc, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_CDROM | + CTL_CMD_FLAG_ALLOW_ON_PR_WRESV | + CTL_FLAG_DATA_IN, + CTL_LUN_PAT_NONE, + 10, {0x02, 0x01, 0, 0, 0, 0xff, 0xff, 0xff, 0x07}}, /* 44 REPORT DENSITY SUPPORT */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, @@ -845,7 +857,12 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 46 GET CONFIGURATION */ -{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, +{ctl_get_config, CTL_SERIDX_INQ, CTL_CMD_FLAG_OK_ON_CDROM | + CTL_CMD_FLAG_OK_ON_STOPPED | + CTL_CMD_FLAG_ALLOW_ON_PR_RESV | + CTL_FLAG_DATA_IN, + CTL_LUN_PAT_NONE, + 10, {0x03, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0x07}}, /* 47 PLAY AUDIO MSF */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, @@ -857,7 +874,13 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 4A GET EVENT STATUS NOTIFICATION */ -{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, +{ctl_get_event_status, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_CDROM | + CTL_CMD_FLAG_OK_ON_STOPPED | + CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_ALLOW_ON_PR_RESV | + CTL_FLAG_DATA_IN, + CTL_LUN_PAT_NONE, + 10, {0x02, 0x01, 0, 0, 0, 0xff, 0xff, 0xff, 0x07}}, /* 4B PAUSE/RESUME */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, @@ -1076,20 +1099,20 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 88 READ(16) */ -{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | CTL_FLAG_DATA_IN | +{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, 16, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, /* 89 COMPARE AND WRITE */ -{ctl_cnw, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_cnw, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 16, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0, 0x07}}, /* 8A WRITE(16) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 16, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, @@ -1104,13 +1127,13 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 8E WRITE AND VERIFY(16) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 16, {0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, /* 8F VERIFY(16) */ -{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, @@ -1121,7 +1144,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 91 SYNCHRONIZE CACHE(16) */ -{ctl_sync_cache, CTL_SERIDX_SYNC, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_sync_cache, CTL_SERIDX_SYNC, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_NONE, CTL_LUN_PAT_WRITE, 16, {0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -1131,7 +1154,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 93 WRITE SAME(16) */ -{ctl_write_same, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_write_same, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 16, {0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -1170,7 +1193,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, /* 9C WRITE ATOMIC (16) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 16, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0xff, 0xff, 0, 0x07}}, @@ -1223,8 +1246,10 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* A8 READ(12) */ -{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | CTL_FLAG_DATA_IN | - CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, +{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | + CTL_CMD_FLAG_OK_ON_CDROM | + CTL_FLAG_DATA_IN | + CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, 12, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, @@ -1232,7 +1257,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* AA WRITE(12) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 12, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, @@ -1246,12 +1271,12 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* AE WRITE AND VERIFY(12) */ -{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT, +{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_DIRECT| CTL_FLAG_DATA_OUT, CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE, 12, {0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, /* AF VERIFY(12) */ -{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE, @@ -1279,7 +1304,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* B7 READ DEFECT DATA(12) */ -{ctl_read_defect, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_SLUN | +{ctl_read_defect, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, CTL_LUN_PAT_NONE, @@ -1300,8 +1325,14 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* BC SPARE IN */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, -/* BD SPARE OUT */ -{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, +/* BD SPARE OUT / MECHANISM STATUS */ +{ctl_mechanism_status, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_CDROM | + CTL_CMD_FLAG_OK_ON_STOPPED | + CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_ALLOW_ON_PR_RESV | + CTL_FLAG_DATA_IN, + CTL_LUN_PAT_NONE, + 12, {0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0x07}}, /* BE VOLUME SET IN */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index 03b9787..ad5fbcd 100644 --- a/sys/cam/ctl/ctl_private.h +++ b/sys/cam/ctl/ctl_private.h @@ -45,6 +45,7 @@ #define CTL_VENDOR "FREEBSD " #define CTL_DIRECT_PRODUCT "CTLDISK " #define CTL_PROCESSOR_PRODUCT "CTLPROCESSOR " +#define CTL_CDROM_PRODUCT "CTLCDROM " #define CTL_UNKNOWN_PRODUCT "CTLDEVICE " #define CTL_POOL_ENTRIES_OTHER_SC 200 @@ -90,15 +91,16 @@ typedef enum { CTL_CMD_FLAG_ALLOW_ON_RESV = 0x0040, CTL_CMD_FLAG_ALLOW_ON_PR_WRESV = 0x0080, CTL_CMD_FLAG_OK_ON_PROC = 0x0100, - CTL_CMD_FLAG_OK_ON_SLUN = 0x0200, - CTL_CMD_FLAG_OK_ON_BOTH = 0x0300, - CTL_CMD_FLAG_OK_ON_STOPPED = 0x0400, + CTL_CMD_FLAG_OK_ON_DIRECT = 0x0200, + CTL_CMD_FLAG_OK_ON_CDROM = 0x0400, + CTL_CMD_FLAG_OK_ON_BOTH = 0x0700, CTL_CMD_FLAG_OK_ON_INOPERABLE = 0x0800, CTL_CMD_FLAG_OK_ON_STANDBY = 0x1000, CTL_CMD_FLAG_OK_ON_UNAVAIL = 0x2000, CTL_CMD_FLAG_ALLOW_ON_PR_RESV = 0x4000, CTL_CMD_FLAG_SA5 = 0x8000, - CTL_CMD_FLAG_RUN_HERE = 0x10000 + CTL_CMD_FLAG_RUN_HERE = 0x10000, + CTL_CMD_FLAG_OK_ON_STOPPED = 0x20000 } ctl_cmd_flags; typedef enum { @@ -147,7 +149,8 @@ typedef enum { CTL_LUN_PRIMARY_SC = 0x200, CTL_LUN_SENSE_DESC = 0x400, CTL_LUN_READONLY = 0x800, - CTL_LUN_PEER_SC_PRIMARY = 0x1000 + CTL_LUN_PEER_SC_PRIMARY = 0x1000, + CTL_LUN_REMOVABLE = 0x2000 } ctl_lun_flags; typedef enum { @@ -231,7 +234,10 @@ typedef int ctl_modesel_handler(struct ctl_scsiio *ctsio, typedef enum { CTL_PAGE_FLAG_NONE = 0x00, - CTL_PAGE_FLAG_DISK_ONLY = 0x01 + CTL_PAGE_FLAG_DIRECT = 0x01, + CTL_PAGE_FLAG_PROC = 0x02, + CTL_PAGE_FLAG_CDROM = 0x04, + CTL_PAGE_FLAG_ALL = 0x07 } ctl_page_flags; struct ctl_page_index { @@ -262,25 +268,26 @@ struct ctl_logical_block_provisioning_page { static const struct ctl_page_index page_index_template[] = { {SMS_RW_ERROR_RECOVERY_PAGE, 0, sizeof(struct scsi_da_rw_recovery_page), NULL, - CTL_PAGE_FLAG_DISK_ONLY, NULL, NULL}, + CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, NULL, NULL}, {SMS_FORMAT_DEVICE_PAGE, 0, sizeof(struct scsi_format_page), NULL, - CTL_PAGE_FLAG_DISK_ONLY, NULL, NULL}, + CTL_PAGE_FLAG_DIRECT, NULL, NULL}, {SMS_RIGID_DISK_PAGE, 0, sizeof(struct scsi_rigid_disk_page), NULL, - CTL_PAGE_FLAG_DISK_ONLY, NULL, NULL}, + CTL_PAGE_FLAG_DIRECT, NULL, NULL}, {SMS_CACHING_PAGE, 0, sizeof(struct scsi_caching_page), NULL, - CTL_PAGE_FLAG_DISK_ONLY, NULL, ctl_caching_sp_handler}, + CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, + NULL, ctl_caching_sp_handler}, {SMS_CONTROL_MODE_PAGE, 0, sizeof(struct scsi_control_page), NULL, - CTL_PAGE_FLAG_NONE, NULL, ctl_control_page_handler}, + CTL_PAGE_FLAG_ALL, NULL, ctl_control_page_handler}, {SMS_CONTROL_MODE_PAGE | SMPH_SPF, 0x01, sizeof(struct scsi_control_ext_page), NULL, - CTL_PAGE_FLAG_NONE, NULL, NULL}, + CTL_PAGE_FLAG_ALL, NULL, NULL}, {SMS_INFO_EXCEPTIONS_PAGE, 0, sizeof(struct scsi_info_exceptions_page), NULL, - CTL_PAGE_FLAG_NONE, NULL, NULL}, + CTL_PAGE_FLAG_ALL, NULL, NULL}, {SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF, 0x02, sizeof(struct ctl_logical_block_provisioning_page), NULL, - CTL_PAGE_FLAG_DISK_ONLY, NULL, NULL}, + CTL_PAGE_FLAG_DIRECT, NULL, NULL}, {SMS_VENDOR_SPECIFIC_PAGE | SMPH_SPF, DBGCNF_SUBPAGE_CODE, - sizeof(struct copan_debugconf_subpage), NULL, CTL_PAGE_FLAG_NONE, + sizeof(struct copan_debugconf_subpage), NULL, CTL_PAGE_FLAG_ALL, ctl_debugconf_sp_sense_handler, ctl_debugconf_sp_select_handler}, }; @@ -302,13 +309,13 @@ struct ctl_mode_pages { static const struct ctl_page_index log_page_index_template[] = { {SLS_SUPPORTED_PAGES_PAGE, 0, 0, NULL, - CTL_PAGE_FLAG_NONE, NULL, NULL}, + CTL_PAGE_FLAG_ALL, NULL, NULL}, {SLS_SUPPORTED_PAGES_PAGE, SLS_SUPPORTED_SUBPAGES_SUBPAGE, 0, NULL, - CTL_PAGE_FLAG_NONE, NULL, NULL}, + CTL_PAGE_FLAG_ALL, NULL, NULL}, {SLS_LOGICAL_BLOCK_PROVISIONING, 0, 0, NULL, - CTL_PAGE_FLAG_DISK_ONLY, ctl_lbp_log_sense_handler, NULL}, + CTL_PAGE_FLAG_DIRECT, ctl_lbp_log_sense_handler, NULL}, {SLS_STAT_AND_PERF, 0, 0, NULL, - CTL_PAGE_FLAG_NONE, ctl_sap_log_sense_handler, NULL}, + CTL_PAGE_FLAG_ALL, ctl_sap_log_sense_handler, NULL}, }; #define CTL_NUM_LOG_PAGES sizeof(log_page_index_template)/ \ @@ -459,6 +466,7 @@ void ctl_pool_free(struct ctl_io_pool *pool); int ctl_scsi_release(struct ctl_scsiio *ctsio); int ctl_scsi_reserve(struct ctl_scsiio *ctsio); int ctl_start_stop(struct ctl_scsiio *ctsio); +int ctl_prevent_allow(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); @@ -471,6 +479,7 @@ int ctl_log_sense(struct ctl_scsiio *ctsio); int ctl_read_capacity(struct ctl_scsiio *ctsio); int ctl_read_capacity_16(struct ctl_scsiio *ctsio); int ctl_read_defect(struct ctl_scsiio *ctsio); +int ctl_read_toc(struct ctl_scsiio *ctsio); int ctl_read_write(struct ctl_scsiio *ctsio); int ctl_cnw(struct ctl_scsiio *ctsio); int ctl_report_luns(struct ctl_scsiio *ctsio); @@ -478,6 +487,9 @@ int ctl_request_sense(struct ctl_scsiio *ctsio); int ctl_tur(struct ctl_scsiio *ctsio); int ctl_verify(struct ctl_scsiio *ctsio); int ctl_inquiry(struct ctl_scsiio *ctsio); +int ctl_get_config(struct ctl_scsiio *ctsio); +int ctl_get_event_status(struct ctl_scsiio *ctsio); +int ctl_mechanism_status(struct ctl_scsiio *ctsio); int ctl_persistent_reserve_in(struct ctl_scsiio *ctsio); int ctl_persistent_reserve_out(struct ctl_scsiio *ctsio); int ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio); diff --git a/sys/cam/scsi/scsi_cd.h b/sys/cam/scsi/scsi_cd.h index f502d66..e141404 100644 --- a/sys/cam/scsi/scsi_cd.h +++ b/sys/cam/scsi/scsi_cd.h @@ -56,6 +56,83 @@ * SCSI command format */ +struct scsi_get_config +{ + uint8_t opcode; + uint8_t rt; +#define SGC_RT_ALL 0x00 +#define SGC_RT_CURRENT 0x01 +#define SGC_RT_SPECIFIC 0x02 +#define SGC_RT_MASK 0x03 + uint8_t starting_feature[2]; + uint8_t reserved[3]; + uint8_t length[2]; + uint8_t control; +}; + +struct scsi_get_config_header +{ + uint8_t data_length[4]; + uint8_t reserved[2]; + uint8_t current_profile[2]; +}; + +struct scsi_get_config_feature +{ + uint8_t feature_code[2]; + uint8_t flags; +#define SGC_F_CURRENT 0x01 +#define SGC_F_PERSISTENT 0x02 +#define SGC_F_VERSION_MASK 0x2C +#define SGC_F_VERSION_SHIFT 2 + uint8_t add_length; + uint8_t feature_data[]; +}; + +struct scsi_get_event_status +{ + uint8_t opcode; + uint8_t byte2; +#define SGESN_POLLED 1 + uint8_t reserved[2]; + uint8_t notif_class; + uint8_t reserved2[2]; + uint8_t length[2]; + uint8_t control; +}; + +struct scsi_get_event_status_header +{ + uint8_t descr_length[4]; + uint8_t nea_class; +#define SGESN_NEA 0x80 + uint8_t supported_class; +}; + +struct scsi_get_event_status_descr +{ + uint8_t event_code; + uint8_t event_info[]; +}; + +struct scsi_mechanism_status +{ + uint8_t opcode; + uint8_t reserved[7]; + uint8_t length[2]; + uint8_t reserved2; + uint8_t control; +}; + +struct scsi_mechanism_status_header +{ + uint8_t state1; + uint8_t state2; + uint8_t lba[3]; + uint8_t slots_num; + uint8_t slots_length[2]; +}; + struct scsi_pause { u_int8_t op_code; @@ -151,12 +228,29 @@ struct scsi_read_toc { u_int8_t op_code; u_int8_t byte2; - u_int8_t unused[4]; + u_int8_t format; + u_int8_t unused[3]; u_int8_t from_track; u_int8_t data_len[2]; u_int8_t control; }; +struct scsi_read_toc_hdr +{ + uint8_t data_length[2]; + uint8_t first; + uint8_t last; +}; + +struct scsi_read_toc_type01_descr +{ + uint8_t reserved; + uint8_t addr_ctl; + uint8_t track_number; + uint8_t reserved2; + uint8_t track_start[4]; +}; + struct scsi_read_cd_capacity { u_int8_t op_code; @@ -252,9 +346,11 @@ struct scsi_read_dvd_structure #define READ_TOC 0x43 /* cdrom read TOC */ #define READ_HEADER 0x44 /* cdrom read header */ #define PLAY_10 0x45 /* cdrom play 'play audio' mode */ +#define GET_CONFIGURATION 0x46 /* Get device configuration */ #define PLAY_MSF 0x47 /* cdrom play Min,Sec,Frames mode */ #define PLAY_TRACK 0x48 /* cdrom play track/index mode */ #define PLAY_TRACK_REL 0x49 /* cdrom play track/index mode */ +#define GET_EVENT_STATUS 0x4a /* Get event status notification */ #define PAUSE 0x4b /* cdrom pause in 'play audio' mode */ #define SEND_KEY 0xa3 /* dvd send key command */ #define REPORT_KEY 0xa4 /* dvd report key command */ @@ -262,6 +358,7 @@ struct scsi_read_dvd_structure #define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */ #define READ_DVD_STRUCTURE 0xad /* read dvd structure */ #define SET_CD_SPEED 0xbb /* set c/dvd speed */ +#define MECHANISM_STATUS 0xbd /* get status of c/dvd mechanics */ struct scsi_report_key_data_header { diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8 index ba582b7..7ff0c8d 100644 --- a/usr.sbin/ctladm/ctladm.8 +++ b/usr.sbin/ctladm/ctladm.8 @@ -717,11 +717,10 @@ Specify the serial number to be used in the INQUIRY VPD page 0x80 data. .It Fl t Ar device_type Specify the numeric SCSI device type to use when creating the LUN. -For example, the Direct Access type is 0. If this flag is not used, the type of LUN created is backend-specific. Not all LUN types are supported. -Currently CTL only supports Direct Access (type 0) and Processor (type 3) -LUNs. +Currently CTL supports Direct Access (type 0), Processor (type 3) +and CD/DVD (type 5) LUNs. The backend requested may or may not support all of the LUN types that CTL supports. .El @@ -876,6 +875,8 @@ Set to "off", disables read caching for the LUN, if supported by the backend. .It Va readonly Set to "on", blocks all media write operations to the LUN, reporting it as write protected. +.It Va removable +Set to "on", makes LUN removable. .It Va reordering Set to "unrestricted", allows target to process commands with SIMPLE task attribute in arbitrary order. Any data integrity exposures related to diff --git a/usr.sbin/ctld/ctl.conf.5 b/usr.sbin/ctld/ctl.conf.5 index a05f89d..ce8df67a 100644 --- a/usr.sbin/ctld/ctl.conf.5 +++ b/usr.sbin/ctld/ctl.conf.5 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 15, 2015 +.Dd September 27, 2015 .Dt CTL.CONF 5 .Os .Sh NAME @@ -371,6 +371,10 @@ By default CTL allocates those IDs dynamically, but explicit specification may be needed for consistency in HA configurations. .It Ic device-id Ar string The SCSI Device Identification string presented to the initiator. +.It Ic device-type Ar type +Specify the SCSI device type to use when creating the LUN. +Currently CTL supports Direct Access (type 0), Processor (type 3) +and CD/DVD (type 5) LUNs. .It Ic option Ar name Ar value The CTL-specific options passed to the kernel. All CTL-specific options are documented in the diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c index 8b13bce..741a713 100644 --- a/usr.sbin/ctld/ctld.c +++ b/usr.sbin/ctld/ctld.c @@ -1439,6 +1439,13 @@ lun_set_blocksize(struct lun *lun, size_t value) } void +lun_set_device_type(struct lun *lun, uint8_t value) +{ + + lun->l_device_type = value; +} + +void lun_set_device_id(struct lun *lun, const char *value) { free(lun->l_device_id); diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h index 8faa556..3e26237 100644 --- a/usr.sbin/ctld/ctld.h +++ b/usr.sbin/ctld/ctld.h @@ -163,6 +163,7 @@ struct lun { TAILQ_HEAD(, lun_option) l_options; char *l_name; char *l_backend; + uint8_t l_device_type; int l_blocksize; char *l_device_id; char *l_path; @@ -371,6 +372,7 @@ struct lun *lun_new(struct conf *conf, const char *name); void lun_delete(struct lun *lun); struct lun *lun_find(const struct conf *conf, const char *name); void lun_set_backend(struct lun *lun, const char *value); +void lun_set_device_type(struct lun *lun, uint8_t value); void lun_set_blocksize(struct lun *lun, size_t value); void lun_set_device_id(struct lun *lun, const char *value); void lun_set_path(struct lun *lun, const char *value); diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c index d9cf54f..dea1917 100644 --- a/usr.sbin/ctld/kernel.c +++ b/usr.sbin/ctld/kernel.c @@ -108,6 +108,7 @@ struct cctl_lun_nv { struct cctl_lun { uint64_t lun_id; char *backend_type; + uint8_t device_type; uint64_t size_blocks; uint32_t blocksize; char *serial_number; @@ -221,6 +222,8 @@ cctl_end_element(void *user_data, const char *name) if (strcmp(name, "backend_type") == 0) { cur_lun->backend_type = str; str = NULL; + } else if (strcmp(name, "lun_type") == 0) { + cur_lun->device_type = strtoull(str, NULL, 0); } else if (strcmp(name, "size") == 0) { cur_lun->size_blocks = strtoull(str, NULL, 0); } else if (strcmp(name, "blocksize") == 0) { @@ -610,6 +613,7 @@ retry_port: continue; } lun_set_backend(cl, lun->backend_type); + lun_set_device_type(cl, lun->device_type); lun_set_blocksize(cl, lun->blocksize); lun_set_device_id(cl, lun->device_id); lun_set_serial(cl, lun->serial_number); @@ -668,7 +672,7 @@ kernel_lun_add(struct lun *lun) } req.reqdata.create.flags |= CTL_LUN_FLAG_DEV_TYPE; - req.reqdata.create.device_type = T_DIRECT; + req.reqdata.create.device_type = lun->l_device_type; if (lun->l_serial != NULL) { strncpy(req.reqdata.create.serial_num, lun->l_serial, diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y index 92d4d3e..1e40dd8 100644 --- a/usr.sbin/ctld/parse.y +++ b/usr.sbin/ctld/parse.y @@ -57,8 +57,8 @@ extern void yyrestart(FILE *); %} %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL -%token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP -%token DISCOVERY_FILTER FOREIGN +%token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE +%token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER FOREIGN %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT %token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR @@ -842,6 +842,8 @@ lun_entry: | lun_device_id | + lun_device_type + | lun_ctl_lun | lun_option @@ -901,6 +903,31 @@ lun_device_id: DEVICE_ID STR } ; +lun_device_type: DEVICE_TYPE STR + { + uint64_t tmp; + + if (strcasecmp($2, "disk") == 0 || + strcasecmp($2, "direct") == 0) + tmp = 0; + else if (strcasecmp($2, "processor") == 0) + tmp = 3; + else if (strcasecmp($2, "cd") == 0 || + strcasecmp($2, "cdrom") == 0 || + strcasecmp($2, "dvd") == 0 || + strcasecmp($2, "dvdrom") == 0) + tmp = 5; + else if (expand_number($2, &tmp) != 0 || + tmp > 15) { + yyerror("invalid numeric value"); + free($2); + return (1); + } + + lun_set_device_type(lun, tmp); + } + ; + lun_ctl_lun: CTL_LUN STR { uint64_t tmp; diff --git a/usr.sbin/ctld/token.l b/usr.sbin/ctld/token.l index ce95e62..e23385f 100644 --- a/usr.sbin/ctld/token.l +++ b/usr.sbin/ctld/token.l @@ -57,6 +57,7 @@ chap-mutual { return CHAP_MUTUAL; } ctl-lun { return CTL_LUN; } debug { return DEBUG; } device-id { return DEVICE_ID; } +device-type { return DEVICE_TYPE; } discovery-auth-group { return DISCOVERY_AUTH_GROUP; } discovery-filter { return DISCOVERY_FILTER; } foreign { return FOREIGN; } |