1 /*- 2 * Copyright (c) 2015, 2016 Spectra Logic Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 16 * 17 * NO WARRANTY 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. 29 * 30 * Authors: Ken Merry (Spectra Logic Corporation) 31 */ 32 /* 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. 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include <sys/ioctl.h> 41 #include <sys/stdint.h> 42 #include <sys/types.h> 43 #include <sys/endian.h> 44 #include <sys/sbuf.h> 45 #include <sys/queue.h> 46 #include <sys/chio.h> 47 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <inttypes.h> 51 #include <unistd.h> 52 #include <string.h> 53 #include <strings.h> 54 #include <fcntl.h> 55 #include <ctype.h> 56 #include <limits.h> 57 #include <err.h> 58 #include <locale.h> 59 60 #include <cam/cam.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> 68 #include <camlib.h> 69 #include "camcontrol.h" 70 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 } 78 }; 79 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 } 94 }; 95 96 typedef enum { 97 ZONE_OF_NORMAL = 0x00, 98 ZONE_OF_SUMMARY = 0x01, 99 ZONE_OF_SCRIPT = 0x02 100 } zone_output_flags; 101 102 static struct scsi_nv zone_print_opts[] = { 103 { "normal", ZONE_OF_NORMAL }, 104 { "summary", ZONE_OF_SUMMARY }, 105 { "script", ZONE_OF_SCRIPT } 106 }; 107 108 #define ZAC_ATA_SECTOR_COUNT(bcount) (((bcount) / 512) & 0xffff) 109 110 typedef enum { 111 ZONE_PRINT_OK, 112 ZONE_PRINT_MORE_DATA, 113 ZONE_PRINT_ERROR 114 } zone_print_status; 115 116 typedef enum { 117 ZONE_FW_START, 118 ZONE_FW_LEN, 119 ZONE_FW_WP, 120 ZONE_FW_TYPE, 121 ZONE_FW_COND, 122 ZONE_FW_SEQ, 123 ZONE_FW_RESET, 124 ZONE_NUM_FIELDS 125 } zone_field_widths; 126 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); 130 131 132 zone_print_status 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) 136 { 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 int more_data = 0; 142 zone_print_status status = ZONE_PRINT_OK; 143 char tmpstr[80]; 144 int field_widths[ZONE_NUM_FIELDS]; 145 char word_sep; 146 147 if (valid_len < sizeof(*hdr)) { 148 status = ZONE_PRINT_ERROR; 149 goto bailout; 150 } 151 152 hdr = (struct scsi_report_zones_hdr *)data_ptr; 153 154 field_widths[ZONE_FW_START] = 11; 155 field_widths[ZONE_FW_LEN] = 6; 156 field_widths[ZONE_FW_WP] = 11; 157 field_widths[ZONE_FW_TYPE] = 13; 158 field_widths[ZONE_FW_COND] = 13; 159 field_widths[ZONE_FW_SEQ] = 14; 160 field_widths[ZONE_FW_RESET] = 16; 161 162 if (ata_format == 0) { 163 hdr_len = scsi_4btoul(hdr->length); 164 max_lba = scsi_8btou64(hdr->maximum_lba); 165 } else { 166 hdr_len = le32dec(hdr->length); 167 max_lba = le64dec(hdr->maximum_lba); 168 } 169 170 if (hdr_len > (valid_len + sizeof(*hdr))) { 171 more_data = 1; 172 status = ZONE_PRINT_MORE_DATA; 173 } 174 175 len = MIN(valid_len - sizeof(*hdr), hdr_len); 176 177 if (out_flags == ZONE_OF_SCRIPT) 178 word_sep = '_'; 179 else 180 word_sep = ' '; 181 182 if ((out_flags != ZONE_OF_SCRIPT) 183 && (first_pass != 0)) { 184 printf("%zu zones, Maximum LBA %#jx (%ju)\n", 185 hdr_len / sizeof(*desc), (uintmax_t)max_lba, 186 (uintmax_t)max_lba); 187 188 switch (hdr->byte4 & SRZ_SAME_MASK) { 189 case SRZ_SAME_ALL_DIFFERENT: 190 printf("Zone lengths and types may vary\n"); 191 break; 192 case SRZ_SAME_ALL_SAME: 193 printf("Zone lengths and types are all the same\n"); 194 break; 195 case SRZ_SAME_LAST_DIFFERENT: 196 printf("Zone types are the same, last zone length " 197 "differs\n"); 198 break; 199 case SRZ_SAME_TYPES_DIFFERENT: 200 printf("Zone lengths are the same, types vary\n"); 201 break; 202 default: 203 printf("Unknown SAME field value %#x\n", 204 hdr->byte4 & SRZ_SAME_MASK); 205 break; 206 } 207 } 208 if (out_flags == ZONE_OF_SUMMARY) { 209 status = ZONE_PRINT_OK; 210 goto bailout; 211 } 212 213 if ((out_flags == ZONE_OF_NORMAL) 214 && (first_pass != 0)) { 215 printf("%*s %*s %*s %*s %*s %*s %*s\n", 216 field_widths[ZONE_FW_START], "Start LBA", 217 field_widths[ZONE_FW_LEN], "Length", 218 field_widths[ZONE_FW_WP], "WP LBA", 219 field_widths[ZONE_FW_TYPE], "Zone Type", 220 field_widths[ZONE_FW_COND], "Condition", 221 field_widths[ZONE_FW_SEQ], "Sequential", 222 field_widths[ZONE_FW_RESET], "Reset"); 223 } 224 225 for (desc = &hdr->desc_list[0]; len >= sizeof(*desc); 226 len -= sizeof(*desc), desc++) { 227 uint64_t length, start_lba, wp_lba; 228 229 if (ata_format == 0) { 230 length = scsi_8btou64(desc->zone_length); 231 start_lba = scsi_8btou64(desc->zone_start_lba); 232 wp_lba = scsi_8btou64(desc->write_pointer_lba); 233 } else { 234 length = le64dec(desc->zone_length); 235 start_lba = le64dec(desc->zone_start_lba); 236 wp_lba = le64dec(desc->write_pointer_lba); 237 } 238 239 printf("%#*jx, %*ju, %#*jx, ", field_widths[ZONE_FW_START], 240 (uintmax_t)start_lba, field_widths[ZONE_FW_LEN], 241 (uintmax_t)length, field_widths[ZONE_FW_WP], 242 (uintmax_t)wp_lba); 243 244 switch (desc->zone_type & SRZ_TYPE_MASK) { 245 case SRZ_TYPE_CONVENTIONAL: 246 snprintf(tmpstr, sizeof(tmpstr), "Conventional"); 247 break; 248 case SRZ_TYPE_SEQ_PREFERRED: 249 case SRZ_TYPE_SEQ_REQUIRED: 250 snprintf(tmpstr, sizeof(tmpstr), "Seq%c%s", 251 word_sep, ((desc->zone_type & SRZ_TYPE_MASK) == 252 SRZ_TYPE_SEQ_PREFERRED) ? "Preferred" : 253 "Required"); 254 break; 255 default: 256 snprintf(tmpstr, sizeof(tmpstr), "Zone%ctype%c%#x", 257 word_sep, word_sep,desc->zone_type & 258 SRZ_TYPE_MASK); 259 break; 260 } 261 printf("%*s, ", field_widths[ZONE_FW_TYPE], tmpstr); 262 263 switch (desc->zone_flags & SRZ_ZONE_COND_MASK) { 264 case SRZ_ZONE_COND_NWP: 265 snprintf(tmpstr, sizeof(tmpstr), "NWP"); 266 break; 267 case SRZ_ZONE_COND_EMPTY: 268 snprintf(tmpstr, sizeof(tmpstr), "Empty"); 269 break; 270 case SRZ_ZONE_COND_IMP_OPEN: 271 snprintf(tmpstr, sizeof(tmpstr), "Implicit%cOpen", 272 word_sep); 273 break; 274 case SRZ_ZONE_COND_EXP_OPEN: 275 snprintf(tmpstr, sizeof(tmpstr), "Explicit%cOpen", 276 word_sep); 277 break; 278 case SRZ_ZONE_COND_CLOSED: 279 snprintf(tmpstr, sizeof(tmpstr), "Closed"); 280 break; 281 case SRZ_ZONE_COND_READONLY: 282 snprintf(tmpstr, sizeof(tmpstr), "Readonly"); 283 break; 284 case SRZ_ZONE_COND_FULL: 285 snprintf(tmpstr, sizeof(tmpstr), "Full"); 286 break; 287 case SRZ_ZONE_COND_OFFLINE: 288 snprintf(tmpstr, sizeof(tmpstr), "Offline"); 289 break; 290 default: 291 snprintf(tmpstr, sizeof(tmpstr), "%#x", 292 desc->zone_flags & SRZ_ZONE_COND_MASK); 293 break; 294 } 295 296 printf("%*s, ", field_widths[ZONE_FW_COND], tmpstr); 297 298 if (desc->zone_flags & SRZ_ZONE_NON_SEQ) 299 snprintf(tmpstr, sizeof(tmpstr), "Non%cSequential", 300 word_sep); 301 else 302 snprintf(tmpstr, sizeof(tmpstr), "Sequential"); 303 304 printf("%*s, ", field_widths[ZONE_FW_SEQ], tmpstr); 305 306 if (desc->zone_flags & SRZ_ZONE_RESET) 307 snprintf(tmpstr, sizeof(tmpstr), "Reset%cNeeded", 308 word_sep); 309 else 310 snprintf(tmpstr, sizeof(tmpstr), "No%cReset%cNeeded", 311 word_sep, word_sep); 312 313 printf("%*s\n", field_widths[ZONE_FW_RESET], tmpstr); 314 315 next_lba = start_lba + length; 316 } 317 bailout: 318 *next_start_lba = next_lba; 319 320 return (status); 321 } 322 323 int 324 zone(struct cam_device *device, int argc, char **argv, char *combinedopt, 325 int task_attr, int retry_count, int timeout, int verbosemode __unused) 326 { 327 union ccb *ccb = NULL; 328 int action = -1, rep_option = -1; 329 int all_zones = 0; 330 uint64_t lba = 0; 331 int error = 0; 332 uint8_t *data_ptr = NULL; 333 uint32_t alloc_len = 65536, valid_len = 0; 334 camcontrol_devtype devtype; 335 int ata_format = 0, use_ncq = 0; 336 int first_pass = 1; 337 zone_print_status zp_status; 338 zone_output_flags out_flags = ZONE_OF_NORMAL; 339 uint8_t *cdb_storage = NULL; 340 int cdb_storage_len = 32; 341 int c; 342 343 ccb = cam_getccb(device); 344 if (ccb == NULL) { 345 warnx("%s: error allocating CCB", __func__); 346 error = 1; 347 goto bailout; 348 } 349 350 while ((c = getopt(argc, argv, combinedopt)) != -1) { 351 switch (c) { 352 case 'a': 353 all_zones = 1; 354 break; 355 case 'c': { 356 scsi_nv_status status; 357 int entry_num; 358 359 status = scsi_get_nv(zone_cmd_map, 360 (sizeof(zone_cmd_map) / sizeof(zone_cmd_map[0])), 361 optarg, &entry_num, SCSI_NV_FLAG_IG_CASE); 362 if (status == SCSI_NV_FOUND) 363 action = zone_cmd_map[entry_num].value; 364 else { 365 warnx("%s: %s: %s option %s", __func__, 366 (status == SCSI_NV_AMBIGUOUS) ? 367 "ambiguous" : "invalid", "zone command", 368 optarg); 369 error = 1; 370 goto bailout; 371 } 372 break; 373 } 374 case 'l': { 375 char *endptr; 376 377 lba = strtoull(optarg, &endptr, 0); 378 if (*endptr != '\0') { 379 warnx("%s: invalid lba argument %s", __func__, 380 optarg); 381 error = 1; 382 goto bailout; 383 } 384 break; 385 } 386 case 'N': 387 use_ncq = 1; 388 break; 389 case 'o': { 390 scsi_nv_status status; 391 int entry_num; 392 393 status = scsi_get_nv(zone_rep_opts, 394 (sizeof(zone_rep_opts) /sizeof(zone_rep_opts[0])), 395 optarg, &entry_num, SCSI_NV_FLAG_IG_CASE); 396 if (status == SCSI_NV_FOUND) 397 rep_option = zone_rep_opts[entry_num].value; 398 else { 399 warnx("%s: %s: %s option %s", __func__, 400 (status == SCSI_NV_AMBIGUOUS) ? 401 "ambiguous" : "invalid", "report zones", 402 optarg); 403 error = 1; 404 goto bailout; 405 } 406 break; 407 } 408 case 'P': { 409 scsi_nv_status status; 410 int entry_num; 411 412 status = scsi_get_nv(zone_print_opts, 413 (sizeof(zone_print_opts) / 414 sizeof(zone_print_opts[0])), optarg, &entry_num, 415 SCSI_NV_FLAG_IG_CASE); 416 if (status == SCSI_NV_FOUND) 417 out_flags = zone_print_opts[entry_num].value; 418 else { 419 warnx("%s: %s: %s option %s", __func__, 420 (status == SCSI_NV_AMBIGUOUS) ? 421 "ambiguous" : "invalid", "print", 422 optarg); 423 error = 1; 424 goto bailout; 425 } 426 break; 427 } 428 default: 429 break; 430 } 431 } 432 if (action == -1) { 433 warnx("%s: must specify -c <zone_cmd>", __func__); 434 error = 1; 435 goto bailout; 436 } 437 error = get_device_type(device, retry_count, timeout, 438 /*printerrors*/ 1, &devtype); 439 if (error != 0) 440 errx(1, "Unable to determine device type"); 441 442 if (action == ZBC_IN_SA_REPORT_ZONES) { 443 444 data_ptr = malloc(alloc_len); 445 if (data_ptr == NULL) 446 err(1, "unable to allocate %u bytes", alloc_len); 447 448 restart_report: 449 bzero(data_ptr, alloc_len); 450 451 switch (devtype) { 452 case CC_DT_SCSI: 453 scsi_zbc_in(&ccb->csio, 454 /*retries*/ retry_count, 455 /*cbfcnp*/ NULL, 456 /*tag_action*/ task_attr, 457 /*service_action*/ action, 458 /*zone_start_lba*/ lba, 459 /*zone_options*/ (rep_option != -1) ? 460 rep_option : 0, 461 /*data_ptr*/ data_ptr, 462 /*dxfer_len*/ alloc_len, 463 /*sense_len*/ SSD_FULL_SIZE, 464 /*timeout*/ timeout ? timeout : 60000); 465 break; 466 case CC_DT_ATA: 467 case CC_DT_SATL: { 468 uint8_t command = 0; 469 uint8_t protocol = 0; 470 uint16_t features = 0, sector_count = 0; 471 uint32_t auxiliary = 0; 472 473 /* 474 * XXX KDM support the partial bit? 475 */ 476 if (use_ncq == 0) { 477 command = ATA_ZAC_MANAGEMENT_IN; 478 features = action; 479 if (rep_option != -1) 480 features |= (rep_option << 8); 481 sector_count = ZAC_ATA_SECTOR_COUNT(alloc_len); 482 protocol = AP_PROTO_DMA; 483 } else { 484 if (cdb_storage == NULL) 485 cdb_storage = calloc(cdb_storage_len, 1); 486 if (cdb_storage == NULL) 487 err(1, "couldn't allocate memory"); 488 489 command = ATA_RECV_FPDMA_QUEUED; 490 features = ZAC_ATA_SECTOR_COUNT(alloc_len); 491 sector_count = ATA_RFPDMA_ZAC_MGMT_IN << 8; 492 auxiliary = action & 0xf; 493 if (rep_option != -1) 494 auxiliary |= rep_option << 8; 495 protocol = AP_PROTO_FPDMA; 496 } 497 498 error = build_ata_cmd(ccb, 499 /*retry_count*/ retry_count, 500 /*flags*/ CAM_DIR_IN | CAM_DEV_QFRZDIS, 501 /*tag_action*/ task_attr, 502 /*protocol*/ protocol, 503 /*ata_flags*/ AP_FLAG_BYT_BLOK_BLOCKS | 504 AP_FLAG_TLEN_SECT_CNT | 505 AP_FLAG_TDIR_FROM_DEV, 506 /*features*/ features, 507 /*sector_count*/ sector_count, 508 /*lba*/ lba, 509 /*command*/ command, 510 /*auxiliary*/ auxiliary, 511 /*data_ptr*/ data_ptr, 512 /*dxfer_len*/ ZAC_ATA_SECTOR_COUNT(alloc_len)*512, 513 /*cdb_storage*/ cdb_storage, 514 /*cdb_storage_len*/ cdb_storage_len, 515 /*sense_len*/ SSD_FULL_SIZE, 516 /*timeout*/ timeout ? timeout : 60000, 517 /*is48bit*/ 1, 518 /*devtype*/ devtype); 519 520 if (error != 0) { 521 warnx("%s: build_ata_cmd() failed, likely " 522 "programmer error", __func__); 523 goto bailout; 524 } 525 526 ata_format = 1; 527 528 break; 529 } 530 default: 531 warnx("%s: Unknown device type %d", __func__,devtype); 532 error = 1; 533 goto bailout; 534 break; /*NOTREACHED*/ 535 } 536 } else { 537 /* 538 * XXX KDM the current methodology is to always send ATA 539 * commands to ATA devices. Need to figure out how to 540 * detect whether a SCSI to ATA translation layer will 541 * translate ZBC IN/OUT commands to the appropriate ZAC 542 * command. 543 */ 544 switch (devtype) { 545 case CC_DT_SCSI: 546 scsi_zbc_out(&ccb->csio, 547 /*retries*/ retry_count, 548 /*cbfcnp*/ NULL, 549 /*tag_action*/ task_attr, 550 /*service_action*/ action, 551 /*zone_id*/ lba, 552 /*zone_flags*/ (all_zones != 0) ? ZBC_OUT_ALL : 0, 553 /*data_ptr*/ NULL, 554 /*dxfer_len*/ 0, 555 /*sense_len*/ SSD_FULL_SIZE, 556 /*timeout*/ timeout ? timeout : 60000); 557 break; 558 case CC_DT_ATA: 559 case CC_DT_SATL: { 560 uint8_t command = 0; 561 uint8_t protocol = 0; 562 uint16_t features = 0, sector_count = 0; 563 uint32_t auxiliary = 0; 564 565 /* 566 * Note that we're taking advantage of the fact 567 * that the action numbers are the same between the 568 * ZBC and ZAC specs. 569 */ 570 571 if (use_ncq == 0) { 572 protocol = AP_PROTO_NON_DATA; 573 command = ATA_ZAC_MANAGEMENT_OUT; 574 features = action & 0xf; 575 if (all_zones != 0) 576 features |= (ZBC_OUT_ALL << 8); 577 } else { 578 cdb_storage = calloc(cdb_storage_len, 1); 579 if (cdb_storage == NULL) 580 err(1, "couldn't allocate memory"); 581 582 protocol = AP_PROTO_FPDMA; 583 command = ATA_NCQ_NON_DATA; 584 features = ATA_NCQ_ZAC_MGMT_OUT; 585 auxiliary = action & 0xf; 586 if (all_zones != 0) 587 auxiliary |= (ZBC_OUT_ALL << 8); 588 } 589 590 591 error = build_ata_cmd(ccb, 592 /*retry_count*/ retry_count, 593 /*flags*/ CAM_DIR_NONE | CAM_DEV_QFRZDIS, 594 /*tag_action*/ task_attr, 595 /*protocol*/ AP_PROTO_NON_DATA, 596 /*ata_flags*/ AP_FLAG_BYT_BLOK_BYTES | 597 AP_FLAG_TLEN_NO_DATA, 598 /*features*/ features, 599 /*sector_count*/ sector_count, 600 /*lba*/ lba, 601 /*command*/ command, 602 /*auxiliary*/ auxiliary, 603 /*data_ptr*/ NULL, 604 /*dxfer_len*/ 0, 605 /*cdb_storage*/ cdb_storage, 606 /*cdb_storage_len*/ cdb_storage_len, 607 /*sense_len*/ SSD_FULL_SIZE, 608 /*timeout*/ timeout ? timeout : 60000, 609 /*is48bit*/ 1, 610 /*devtype*/ devtype); 611 if (error != 0) { 612 warnx("%s: build_ata_cmd() failed, likely " 613 "programmer error", __func__); 614 goto bailout; 615 } 616 ata_format = 1; 617 break; 618 } 619 default: 620 warnx("%s: Unknown device type %d", __func__,devtype); 621 error = 1; 622 goto bailout; 623 break; /*NOTREACHED*/ 624 } 625 } 626 627 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 628 if (retry_count > 0) 629 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 630 631 error = cam_send_ccb(device, ccb); 632 if (error != 0) { 633 warn("error sending %s %s CCB", (devtype == CC_DT_SCSI) ? 634 "ZBC" : "ZAC Management", 635 (action == ZBC_IN_SA_REPORT_ZONES) ? "In" : "Out"); 636 error = -1; 637 goto bailout; 638 } 639 640 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 641 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL,stderr); 642 error = 1; 643 goto bailout; 644 } 645 646 /* 647 * If we aren't reading the list of zones, we're done. 648 */ 649 if (action != ZBC_IN_SA_REPORT_ZONES) 650 goto bailout; 651 652 if (ccb->ccb_h.func_code == XPT_SCSI_IO) 653 valid_len = ccb->csio.dxfer_len - ccb->csio.resid; 654 else 655 valid_len = ccb->ataio.dxfer_len - ccb->ataio.resid; 656 657 zp_status = zone_rz_print(data_ptr, valid_len, ata_format, out_flags, 658 first_pass, &lba); 659 660 if (zp_status == ZONE_PRINT_MORE_DATA) { 661 bzero(ccb, sizeof(*ccb)); 662 first_pass = 0; 663 if (cdb_storage != NULL) 664 bzero(cdb_storage, cdb_storage_len); 665 goto restart_report; 666 } else if (zp_status == ZONE_PRINT_ERROR) 667 error = 1; 668 bailout: 669 if (ccb != NULL) 670 cam_freeccb(ccb); 671 672 free(data_ptr); 673 free(cdb_storage); 674 675 return (error); 676 } 677