2 * Copyright (c) 2015, 2016 Spectra Logic Corporation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * substantially similar to the "NO WARRANTY" disclaimer below
13 * ("Disclaimer") and any redistribution must be conditioned upon
14 * including a substantially similar Disclaimer requirement for further
15 * binary redistribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGES.
30 * Authors: Ken Merry (Spectra Logic Corporation)
33 * SCSI and ATA Shingled Media Recording (SMR) support for camcontrol(8).
34 * This is an implementation of the SCSI ZBC and ATA ZAC specs.
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
40 #include <sys/ioctl.h>
41 #include <sys/stdint.h>
42 #include <sys/types.h>
43 #include <sys/endian.h>
45 #include <sys/queue.h>
61 #include <cam/cam_debug.h>
62 #include <cam/cam_ccb.h>
63 #include <cam/scsi/scsi_all.h>
64 #include <cam/scsi/scsi_da.h>
65 #include <cam/scsi/scsi_pass.h>
66 #include <cam/scsi/scsi_ch.h>
67 #include <cam/scsi/scsi_message.h>
69 #include "camcontrol.h"
71 static struct scsi_nv zone_cmd_map[] = {
72 { "rz", ZBC_IN_SA_REPORT_ZONES },
73 { "reportzones", ZBC_IN_SA_REPORT_ZONES },
74 { "close", ZBC_OUT_SA_CLOSE },
75 { "finish", ZBC_OUT_SA_FINISH },
76 { "open", ZBC_OUT_SA_OPEN },
77 { "rwp", ZBC_OUT_SA_RWP }
80 static struct scsi_nv zone_rep_opts[] = {
81 { "all", ZBC_IN_REP_ALL_ZONES },
82 { "empty", ZBC_IN_REP_EMPTY },
83 { "imp_open", ZBC_IN_REP_IMP_OPEN },
84 { "exp_open", ZBC_IN_REP_EXP_OPEN },
85 { "closed", ZBC_IN_REP_CLOSED },
86 { "full", ZBC_IN_REP_FULL },
87 { "readonly", ZBC_IN_REP_READONLY },
88 { "ro", ZBC_IN_REP_READONLY },
89 { "offline", ZBC_IN_REP_OFFLINE },
90 { "rwp", ZBC_IN_REP_RESET },
91 { "reset", ZBC_IN_REP_RESET },
92 { "nonseq", ZBC_IN_REP_NON_SEQ },
93 { "nonwp", ZBC_IN_REP_NON_WP }
97 ZONE_OF_NORMAL = 0x00,
98 ZONE_OF_SUMMARY = 0x01,
102 static struct scsi_nv zone_print_opts[] = {
103 { "normal", ZONE_OF_NORMAL },
104 { "summary", ZONE_OF_SUMMARY },
105 { "script", ZONE_OF_SCRIPT }
108 #define ZAC_ATA_SECTOR_COUNT(bcount) (((bcount) / 512) & 0xffff)
112 ZONE_PRINT_MORE_DATA,
127 zone_print_status zone_rz_print(uint8_t *data_ptr, uint32_t valid_len,
128 int ata_format, zone_output_flags out_flags,
129 int first_pass, uint64_t *next_start_lba);
133 zone_rz_print(uint8_t *data_ptr, uint32_t valid_len, int ata_format,
134 zone_output_flags out_flags, int first_pass,
135 uint64_t *next_start_lba)
137 struct scsi_report_zones_hdr *hdr = NULL;
138 struct scsi_report_zones_desc *desc = NULL;
139 uint32_t hdr_len, len;
140 uint64_t max_lba, next_lba = 0;
141 zone_print_status status = ZONE_PRINT_OK;
143 int field_widths[ZONE_NUM_FIELDS];
146 if (valid_len < sizeof(*hdr)) {
147 status = ZONE_PRINT_ERROR;
151 hdr = (struct scsi_report_zones_hdr *)data_ptr;
153 field_widths[ZONE_FW_START] = 11;
154 field_widths[ZONE_FW_LEN] = 6;
155 field_widths[ZONE_FW_WP] = 11;
156 field_widths[ZONE_FW_TYPE] = 13;
157 field_widths[ZONE_FW_COND] = 13;
158 field_widths[ZONE_FW_SEQ] = 14;
159 field_widths[ZONE_FW_RESET] = 16;
161 if (ata_format == 0) {
162 hdr_len = scsi_4btoul(hdr->length);
163 max_lba = scsi_8btou64(hdr->maximum_lba);
165 hdr_len = le32dec(hdr->length);
166 max_lba = le64dec(hdr->maximum_lba);
169 if (hdr_len > (valid_len + sizeof(*hdr))) {
170 status = ZONE_PRINT_MORE_DATA;
173 len = MIN(valid_len - sizeof(*hdr), hdr_len);
175 if (out_flags == ZONE_OF_SCRIPT)
180 if ((out_flags != ZONE_OF_SCRIPT)
181 && (first_pass != 0)) {
182 printf("%zu zones, Maximum LBA %#jx (%ju)\n",
183 hdr_len / sizeof(*desc), (uintmax_t)max_lba,
186 switch (hdr->byte4 & SRZ_SAME_MASK) {
187 case SRZ_SAME_ALL_DIFFERENT:
188 printf("Zone lengths and types may vary\n");
190 case SRZ_SAME_ALL_SAME:
191 printf("Zone lengths and types are all the same\n");
193 case SRZ_SAME_LAST_DIFFERENT:
194 printf("Zone types are the same, last zone length "
197 case SRZ_SAME_TYPES_DIFFERENT:
198 printf("Zone lengths are the same, types vary\n");
201 printf("Unknown SAME field value %#x\n",
202 hdr->byte4 & SRZ_SAME_MASK);
206 if (out_flags == ZONE_OF_SUMMARY) {
207 status = ZONE_PRINT_OK;
211 if ((out_flags == ZONE_OF_NORMAL)
212 && (first_pass != 0)) {
213 printf("%*s %*s %*s %*s %*s %*s %*s\n",
214 field_widths[ZONE_FW_START], "Start LBA",
215 field_widths[ZONE_FW_LEN], "Length",
216 field_widths[ZONE_FW_WP], "WP LBA",
217 field_widths[ZONE_FW_TYPE], "Zone Type",
218 field_widths[ZONE_FW_COND], "Condition",
219 field_widths[ZONE_FW_SEQ], "Sequential",
220 field_widths[ZONE_FW_RESET], "Reset");
223 for (desc = &hdr->desc_list[0]; len >= sizeof(*desc);
224 len -= sizeof(*desc), desc++) {
225 uint64_t length, start_lba, wp_lba;
227 if (ata_format == 0) {
228 length = scsi_8btou64(desc->zone_length);
229 start_lba = scsi_8btou64(desc->zone_start_lba);
230 wp_lba = scsi_8btou64(desc->write_pointer_lba);
232 length = le64dec(desc->zone_length);
233 start_lba = le64dec(desc->zone_start_lba);
234 wp_lba = le64dec(desc->write_pointer_lba);
237 printf("%#*jx, %*ju, %#*jx, ", field_widths[ZONE_FW_START],
238 (uintmax_t)start_lba, field_widths[ZONE_FW_LEN],
239 (uintmax_t)length, field_widths[ZONE_FW_WP],
242 switch (desc->zone_type & SRZ_TYPE_MASK) {
243 case SRZ_TYPE_CONVENTIONAL:
244 snprintf(tmpstr, sizeof(tmpstr), "Conventional");
246 case SRZ_TYPE_SEQ_PREFERRED:
247 case SRZ_TYPE_SEQ_REQUIRED:
248 snprintf(tmpstr, sizeof(tmpstr), "Seq%c%s",
249 word_sep, ((desc->zone_type & SRZ_TYPE_MASK) ==
250 SRZ_TYPE_SEQ_PREFERRED) ? "Preferred" :
254 snprintf(tmpstr, sizeof(tmpstr), "Zone%ctype%c%#x",
255 word_sep, word_sep,desc->zone_type &
259 printf("%*s, ", field_widths[ZONE_FW_TYPE], tmpstr);
261 switch (desc->zone_flags & SRZ_ZONE_COND_MASK) {
262 case SRZ_ZONE_COND_NWP:
263 snprintf(tmpstr, sizeof(tmpstr), "NWP");
265 case SRZ_ZONE_COND_EMPTY:
266 snprintf(tmpstr, sizeof(tmpstr), "Empty");
268 case SRZ_ZONE_COND_IMP_OPEN:
269 snprintf(tmpstr, sizeof(tmpstr), "Implicit%cOpen",
272 case SRZ_ZONE_COND_EXP_OPEN:
273 snprintf(tmpstr, sizeof(tmpstr), "Explicit%cOpen",
276 case SRZ_ZONE_COND_CLOSED:
277 snprintf(tmpstr, sizeof(tmpstr), "Closed");
279 case SRZ_ZONE_COND_READONLY:
280 snprintf(tmpstr, sizeof(tmpstr), "Readonly");
282 case SRZ_ZONE_COND_FULL:
283 snprintf(tmpstr, sizeof(tmpstr), "Full");
285 case SRZ_ZONE_COND_OFFLINE:
286 snprintf(tmpstr, sizeof(tmpstr), "Offline");
289 snprintf(tmpstr, sizeof(tmpstr), "%#x",
290 desc->zone_flags & SRZ_ZONE_COND_MASK);
294 printf("%*s, ", field_widths[ZONE_FW_COND], tmpstr);
296 if (desc->zone_flags & SRZ_ZONE_NON_SEQ)
297 snprintf(tmpstr, sizeof(tmpstr), "Non%cSequential",
300 snprintf(tmpstr, sizeof(tmpstr), "Sequential");
302 printf("%*s, ", field_widths[ZONE_FW_SEQ], tmpstr);
304 if (desc->zone_flags & SRZ_ZONE_RESET)
305 snprintf(tmpstr, sizeof(tmpstr), "Reset%cNeeded",
308 snprintf(tmpstr, sizeof(tmpstr), "No%cReset%cNeeded",
311 printf("%*s\n", field_widths[ZONE_FW_RESET], tmpstr);
313 next_lba = start_lba + length;
316 *next_start_lba = next_lba;
322 zone(struct cam_device *device, int argc, char **argv, char *combinedopt,
323 int task_attr, int retry_count, int timeout, int verbosemode __unused)
325 union ccb *ccb = NULL;
326 int action = -1, rep_option = -1;
330 uint8_t *data_ptr = NULL;
331 uint32_t alloc_len = 65536, valid_len = 0;
332 camcontrol_devtype devtype;
333 int ata_format = 0, use_ncq = 0;
335 zone_print_status zp_status;
336 zone_output_flags out_flags = ZONE_OF_NORMAL;
337 uint8_t *cdb_storage = NULL;
338 int cdb_storage_len = 32;
341 ccb = cam_getccb(device);
343 warnx("%s: error allocating CCB", __func__);
348 while ((c = getopt(argc, argv, combinedopt)) != -1) {
354 scsi_nv_status status;
357 status = scsi_get_nv(zone_cmd_map,
358 (sizeof(zone_cmd_map) / sizeof(zone_cmd_map[0])),
359 optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
360 if (status == SCSI_NV_FOUND)
361 action = zone_cmd_map[entry_num].value;
363 warnx("%s: %s: %s option %s", __func__,
364 (status == SCSI_NV_AMBIGUOUS) ?
365 "ambiguous" : "invalid", "zone command",
375 lba = strtoull(optarg, &endptr, 0);
376 if (*endptr != '\0') {
377 warnx("%s: invalid lba argument %s", __func__,
388 scsi_nv_status status;
391 status = scsi_get_nv(zone_rep_opts,
392 (sizeof(zone_rep_opts) /sizeof(zone_rep_opts[0])),
393 optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
394 if (status == SCSI_NV_FOUND)
395 rep_option = zone_rep_opts[entry_num].value;
397 warnx("%s: %s: %s option %s", __func__,
398 (status == SCSI_NV_AMBIGUOUS) ?
399 "ambiguous" : "invalid", "report zones",
407 scsi_nv_status status;
410 status = scsi_get_nv(zone_print_opts,
411 (sizeof(zone_print_opts) /
412 sizeof(zone_print_opts[0])), optarg, &entry_num,
413 SCSI_NV_FLAG_IG_CASE);
414 if (status == SCSI_NV_FOUND)
415 out_flags = zone_print_opts[entry_num].value;
417 warnx("%s: %s: %s option %s", __func__,
418 (status == SCSI_NV_AMBIGUOUS) ?
419 "ambiguous" : "invalid", "print",
431 warnx("%s: must specify -c <zone_cmd>", __func__);
435 error = get_device_type(device, retry_count, timeout,
436 /*printerrors*/ 1, &devtype);
438 errx(1, "Unable to determine device type");
440 if (action == ZBC_IN_SA_REPORT_ZONES) {
442 data_ptr = malloc(alloc_len);
443 if (data_ptr == NULL)
444 err(1, "unable to allocate %u bytes", alloc_len);
447 bzero(data_ptr, alloc_len);
451 scsi_zbc_in(&ccb->csio,
452 /*retries*/ retry_count,
454 /*tag_action*/ task_attr,
455 /*service_action*/ action,
456 /*zone_start_lba*/ lba,
457 /*zone_options*/ (rep_option != -1) ?
459 /*data_ptr*/ data_ptr,
460 /*dxfer_len*/ alloc_len,
461 /*sense_len*/ SSD_FULL_SIZE,
462 /*timeout*/ timeout ? timeout : 60000);
467 uint8_t protocol = 0;
468 uint16_t features = 0, sector_count = 0;
469 uint32_t auxiliary = 0;
472 * XXX KDM support the partial bit?
475 command = ATA_ZAC_MANAGEMENT_IN;
477 if (rep_option != -1)
478 features |= (rep_option << 8);
479 sector_count = ZAC_ATA_SECTOR_COUNT(alloc_len);
480 protocol = AP_PROTO_DMA;
482 if (cdb_storage == NULL)
483 cdb_storage = calloc(cdb_storage_len, 1);
484 if (cdb_storage == NULL)
485 err(1, "couldn't allocate memory");
487 command = ATA_RECV_FPDMA_QUEUED;
488 features = ZAC_ATA_SECTOR_COUNT(alloc_len);
489 sector_count = ATA_RFPDMA_ZAC_MGMT_IN << 8;
490 auxiliary = action & 0xf;
491 if (rep_option != -1)
492 auxiliary |= rep_option << 8;
493 protocol = AP_PROTO_FPDMA;
496 error = build_ata_cmd(ccb,
497 /*retry_count*/ retry_count,
498 /*flags*/ CAM_DIR_IN | CAM_DEV_QFRZDIS,
499 /*tag_action*/ task_attr,
500 /*protocol*/ protocol,
501 /*ata_flags*/ AP_FLAG_BYT_BLOK_BLOCKS |
502 AP_FLAG_TLEN_SECT_CNT |
503 AP_FLAG_TDIR_FROM_DEV,
504 /*features*/ features,
505 /*sector_count*/ sector_count,
508 /*auxiliary*/ auxiliary,
509 /*data_ptr*/ data_ptr,
510 /*dxfer_len*/ ZAC_ATA_SECTOR_COUNT(alloc_len)*512,
511 /*cdb_storage*/ cdb_storage,
512 /*cdb_storage_len*/ cdb_storage_len,
513 /*sense_len*/ SSD_FULL_SIZE,
514 /*timeout*/ timeout ? timeout : 60000,
516 /*devtype*/ devtype);
519 warnx("%s: build_ata_cmd() failed, likely "
520 "programmer error", __func__);
529 warnx("%s: Unknown device type %d", __func__,devtype);
532 break; /*NOTREACHED*/
536 * XXX KDM the current methodology is to always send ATA
537 * commands to ATA devices. Need to figure out how to
538 * detect whether a SCSI to ATA translation layer will
539 * translate ZBC IN/OUT commands to the appropriate ZAC
544 scsi_zbc_out(&ccb->csio,
545 /*retries*/ retry_count,
547 /*tag_action*/ task_attr,
548 /*service_action*/ action,
550 /*zone_flags*/ (all_zones != 0) ? ZBC_OUT_ALL : 0,
553 /*sense_len*/ SSD_FULL_SIZE,
554 /*timeout*/ timeout ? timeout : 60000);
559 uint8_t protocol = 0;
560 uint16_t features = 0, sector_count = 0;
561 uint32_t auxiliary = 0;
564 * Note that we're taking advantage of the fact
565 * that the action numbers are the same between the
570 protocol = AP_PROTO_NON_DATA;
571 command = ATA_ZAC_MANAGEMENT_OUT;
572 features = action & 0xf;
574 features |= (ZBC_OUT_ALL << 8);
576 cdb_storage = calloc(cdb_storage_len, 1);
577 if (cdb_storage == NULL)
578 err(1, "couldn't allocate memory");
580 protocol = AP_PROTO_FPDMA;
581 command = ATA_NCQ_NON_DATA;
582 features = ATA_NCQ_ZAC_MGMT_OUT;
583 auxiliary = action & 0xf;
585 auxiliary |= (ZBC_OUT_ALL << 8);
589 error = build_ata_cmd(ccb,
590 /*retry_count*/ retry_count,
591 /*flags*/ CAM_DIR_NONE | CAM_DEV_QFRZDIS,
592 /*tag_action*/ task_attr,
593 /*protocol*/ protocol,
594 /*ata_flags*/ AP_FLAG_BYT_BLOK_BYTES |
595 AP_FLAG_TLEN_NO_DATA,
596 /*features*/ features,
597 /*sector_count*/ sector_count,
600 /*auxiliary*/ auxiliary,
603 /*cdb_storage*/ cdb_storage,
604 /*cdb_storage_len*/ cdb_storage_len,
605 /*sense_len*/ SSD_FULL_SIZE,
606 /*timeout*/ timeout ? timeout : 60000,
608 /*devtype*/ devtype);
610 warnx("%s: build_ata_cmd() failed, likely "
611 "programmer error", __func__);
618 warnx("%s: Unknown device type %d", __func__,devtype);
621 break; /*NOTREACHED*/
625 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
627 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
629 error = cam_send_ccb(device, ccb);
631 warn("error sending %s %s CCB", (devtype == CC_DT_SCSI) ?
632 "ZBC" : "ZAC Management",
633 (action == ZBC_IN_SA_REPORT_ZONES) ? "In" : "Out");
638 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
639 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL,stderr);
645 * If we aren't reading the list of zones, we're done.
647 if (action != ZBC_IN_SA_REPORT_ZONES)
650 if (ccb->ccb_h.func_code == XPT_SCSI_IO)
651 valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
653 valid_len = ccb->ataio.dxfer_len - ccb->ataio.resid;
655 zp_status = zone_rz_print(data_ptr, valid_len, ata_format, out_flags,
658 if (zp_status == ZONE_PRINT_MORE_DATA) {
659 bzero(ccb, sizeof(*ccb));
661 if (cdb_storage != NULL)
662 bzero(cdb_storage, cdb_storage_len);
664 } else if (zp_status == ZONE_PRINT_ERROR)