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 zone_print_status status = ZONE_PRINT_OK; 142 char tmpstr[80]; 143 int field_widths[ZONE_NUM_FIELDS]; 144 char word_sep; 145 146 if (valid_len < sizeof(*hdr)) { 147 status = ZONE_PRINT_ERROR; 148 goto bailout; 149 } 150 151 hdr = (struct scsi_report_zones_hdr *)data_ptr; 152 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; 160 161 if (ata_format == 0) { 162 hdr_len = scsi_4btoul(hdr->length); 163 max_lba = scsi_8btou64(hdr->maximum_lba); 164 } else { 165 hdr_len = le32dec(hdr->length); 166 max_lba = le64dec(hdr->maximum_lba); 167 } 168 169 if (hdr_len > (valid_len + sizeof(*hdr))) { 170 status = ZONE_PRINT_MORE_DATA; 171 } 172 173 len = MIN(valid_len - sizeof(*hdr), hdr_len); 174 175 if (out_flags == ZONE_OF_SCRIPT) 176 word_sep = '_'; 177 else 178 word_sep = ' '; 179 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, 184 (uintmax_t)max_lba); 185 186 switch (hdr->byte4 & SRZ_SAME_MASK) { 187 case SRZ_SAME_ALL_DIFFERENT: 188 printf("Zone lengths and types may vary\n"); 189 break; 190 case SRZ_SAME_ALL_SAME: 191 printf("Zone lengths and types are all the same\n"); 192 break; 193 case SRZ_SAME_LAST_DIFFERENT: 194 printf("Zone types are the same, last zone length " 195 "differs\n"); 196 break; 197 case SRZ_SAME_TYPES_DIFFERENT: 198 printf("Zone lengths are the same, types vary\n"); 199 break; 200 default: 201 printf("Unknown SAME field value %#x\n", 202 hdr->byte4 & SRZ_SAME_MASK); 203 break; 204 } 205 } 206 if (out_flags == ZONE_OF_SUMMARY) { 207 status = ZONE_PRINT_OK; 208 goto bailout; 209 } 210 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"); 221 } 222 223 for (desc = &hdr->desc_list[0]; len >= sizeof(*desc); 224 len -= sizeof(*desc), desc++) { 225 uint64_t length, start_lba, wp_lba; 226 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); 231 } else { 232 length = le64dec(desc->zone_length); 233 start_lba = le64dec(desc->zone_start_lba); 234 wp_lba = le64dec(desc->write_pointer_lba); 235 } 236 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], 240 (uintmax_t)wp_lba); 241 242 switch (desc->zone_type & SRZ_TYPE_MASK) { 243 case SRZ_TYPE_CONVENTIONAL: 244 snprintf(tmpstr, sizeof(tmpstr), "Conventional"); 245 break; 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" : 251 "Required"); 252 break; 253 default: 254 snprintf(tmpstr, sizeof(tmpstr), "Zone%ctype%c%#x", 255 word_sep, word_sep,desc->zone_type & 256 SRZ_TYPE_MASK); 257 break; 258 } 259 printf("%*s, ", field_widths[ZONE_FW_TYPE], tmpstr); 260 261 switch (desc->zone_flags & SRZ_ZONE_COND_MASK) { 262 case SRZ_ZONE_COND_NWP: 263 snprintf(tmpstr, sizeof(tmpstr), "NWP"); 264 break; 265 case SRZ_ZONE_COND_EMPTY: 266 snprintf(tmpstr, sizeof(tmpstr), "Empty"); 267 break; 268 case SRZ_ZONE_COND_IMP_OPEN: 269 snprintf(tmpstr, sizeof(tmpstr), "Implicit%cOpen", 270 word_sep); 271 break; 272 case SRZ_ZONE_COND_EXP_OPEN: 273 snprintf(tmpstr, sizeof(tmpstr), "Explicit%cOpen", 274 word_sep); 275 break; 276 case SRZ_ZONE_COND_CLOSED: 277 snprintf(tmpstr, sizeof(tmpstr), "Closed"); 278 break; 279 case SRZ_ZONE_COND_READONLY: 280 snprintf(tmpstr, sizeof(tmpstr), "Readonly"); 281 break; 282 case SRZ_ZONE_COND_FULL: 283 snprintf(tmpstr, sizeof(tmpstr), "Full"); 284 break; 285 case SRZ_ZONE_COND_OFFLINE: 286 snprintf(tmpstr, sizeof(tmpstr), "Offline"); 287 break; 288 default: 289 snprintf(tmpstr, sizeof(tmpstr), "%#x", 290 desc->zone_flags & SRZ_ZONE_COND_MASK); 291 break; 292 } 293 294 printf("%*s, ", field_widths[ZONE_FW_COND], tmpstr); 295 296 if (desc->zone_flags & SRZ_ZONE_NON_SEQ) 297 snprintf(tmpstr, sizeof(tmpstr), "Non%cSequential", 298 word_sep); 299 else 300 snprintf(tmpstr, sizeof(tmpstr), "Sequential"); 301 302 printf("%*s, ", field_widths[ZONE_FW_SEQ], tmpstr); 303 304 if (desc->zone_flags & SRZ_ZONE_RESET) 305 snprintf(tmpstr, sizeof(tmpstr), "Reset%cNeeded", 306 word_sep); 307 else 308 snprintf(tmpstr, sizeof(tmpstr), "No%cReset%cNeeded", 309 word_sep, word_sep); 310 311 printf("%*s\n", field_widths[ZONE_FW_RESET], tmpstr); 312 313 next_lba = start_lba + length; 314 } 315 bailout: 316 *next_start_lba = next_lba; 317 318 return (status); 319 } 320 321 int 322 zone(struct cam_device *device, int argc, char **argv, char *combinedopt, 323 int task_attr, int retry_count, int timeout, int verbosemode __unused) 324 { 325 union ccb *ccb = NULL; 326 int action = -1, rep_option = -1; 327 int all_zones = 0; 328 uint64_t lba = 0; 329 int error = 0; 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; 334 int first_pass = 1; 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; 339 int c; 340 341 ccb = cam_getccb(device); 342 if (ccb == NULL) { 343 warnx("%s: error allocating CCB", __func__); 344 error = 1; 345 goto bailout; 346 } 347 348 while ((c = getopt(argc, argv, combinedopt)) != -1) { 349 switch (c) { 350 case 'a': 351 all_zones = 1; 352 break; 353 case 'c': { 354 scsi_nv_status status; 355 int entry_num; 356 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; 362 else { 363 warnx("%s: %s: %s option %s", __func__, 364 (status == SCSI_NV_AMBIGUOUS) ? 365 "ambiguous" : "invalid", "zone command", 366 optarg); 367 error = 1; 368 goto bailout; 369 } 370 break; 371 } 372 case 'l': { 373 char *endptr; 374 375 lba = strtoull(optarg, &endptr, 0); 376 if (*endptr != '\0') { 377 warnx("%s: invalid lba argument %s", __func__, 378 optarg); 379 error = 1; 380 goto bailout; 381 } 382 break; 383 } 384 case 'N': 385 use_ncq = 1; 386 break; 387 case 'o': { 388 scsi_nv_status status; 389 int entry_num; 390 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; 396 else { 397 warnx("%s: %s: %s option %s", __func__, 398 (status == SCSI_NV_AMBIGUOUS) ? 399 "ambiguous" : "invalid", "report zones", 400 optarg); 401 error = 1; 402 goto bailout; 403 } 404 break; 405 } 406 case 'P': { 407 scsi_nv_status status; 408 int entry_num; 409 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; 416 else { 417 warnx("%s: %s: %s option %s", __func__, 418 (status == SCSI_NV_AMBIGUOUS) ? 419 "ambiguous" : "invalid", "print", 420 optarg); 421 error = 1; 422 goto bailout; 423 } 424 break; 425 } 426 default: 427 break; 428 } 429 } 430 if (action == -1) { 431 warnx("%s: must specify -c <zone_cmd>", __func__); 432 error = 1; 433 goto bailout; 434 } 435 error = get_device_type(device, retry_count, timeout, 436 /*printerrors*/ 1, &devtype); 437 if (error != 0) 438 errx(1, "Unable to determine device type"); 439 440 if (action == ZBC_IN_SA_REPORT_ZONES) { 441 442 data_ptr = malloc(alloc_len); 443 if (data_ptr == NULL) 444 err(1, "unable to allocate %u bytes", alloc_len); 445 446 restart_report: 447 bzero(data_ptr, alloc_len); 448 449 switch (devtype) { 450 case CC_DT_SCSI: 451 scsi_zbc_in(&ccb->csio, 452 /*retries*/ retry_count, 453 /*cbfcnp*/ NULL, 454 /*tag_action*/ task_attr, 455 /*service_action*/ action, 456 /*zone_start_lba*/ lba, 457 /*zone_options*/ (rep_option != -1) ? 458 rep_option : 0, 459 /*data_ptr*/ data_ptr, 460 /*dxfer_len*/ alloc_len, 461 /*sense_len*/ SSD_FULL_SIZE, 462 /*timeout*/ timeout ? timeout : 60000); 463 break; 464 case CC_DT_ATA: 465 case CC_DT_SATL: { 466 uint8_t command = 0; 467 uint8_t protocol = 0; 468 uint16_t features = 0, sector_count = 0; 469 uint32_t auxiliary = 0; 470 471 /* 472 * XXX KDM support the partial bit? 473 */ 474 if (use_ncq == 0) { 475 command = ATA_ZAC_MANAGEMENT_IN; 476 features = action; 477 if (rep_option != -1) 478 features |= (rep_option << 8); 479 sector_count = ZAC_ATA_SECTOR_COUNT(alloc_len); 480 protocol = AP_PROTO_DMA; 481 } else { 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"); 486 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; 494 } 495 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, 506 /*lba*/ lba, 507 /*command*/ command, 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, 515 /*is48bit*/ 1, 516 /*devtype*/ devtype); 517 518 if (error != 0) { 519 warnx("%s: build_ata_cmd() failed, likely " 520 "programmer error", __func__); 521 goto bailout; 522 } 523 524 ata_format = 1; 525 526 break; 527 } 528 default: 529 warnx("%s: Unknown device type %d", __func__,devtype); 530 error = 1; 531 goto bailout; 532 break; /*NOTREACHED*/ 533 } 534 } else { 535 /* 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 540 * command. 541 */ 542 switch (devtype) { 543 case CC_DT_SCSI: 544 scsi_zbc_out(&ccb->csio, 545 /*retries*/ retry_count, 546 /*cbfcnp*/ NULL, 547 /*tag_action*/ task_attr, 548 /*service_action*/ action, 549 /*zone_id*/ lba, 550 /*zone_flags*/ (all_zones != 0) ? ZBC_OUT_ALL : 0, 551 /*data_ptr*/ NULL, 552 /*dxfer_len*/ 0, 553 /*sense_len*/ SSD_FULL_SIZE, 554 /*timeout*/ timeout ? timeout : 60000); 555 break; 556 case CC_DT_ATA: 557 case CC_DT_SATL: { 558 uint8_t command = 0; 559 uint8_t protocol = 0; 560 uint16_t features = 0, sector_count = 0; 561 uint32_t auxiliary = 0; 562 563 /* 564 * Note that we're taking advantage of the fact 565 * that the action numbers are the same between the 566 * ZBC and ZAC specs. 567 */ 568 569 if (use_ncq == 0) { 570 protocol = AP_PROTO_NON_DATA; 571 command = ATA_ZAC_MANAGEMENT_OUT; 572 features = action & 0xf; 573 if (all_zones != 0) 574 features |= (ZBC_OUT_ALL << 8); 575 } else { 576 cdb_storage = calloc(cdb_storage_len, 1); 577 if (cdb_storage == NULL) 578 err(1, "couldn't allocate memory"); 579 580 protocol = AP_PROTO_FPDMA; 581 command = ATA_NCQ_NON_DATA; 582 features = ATA_NCQ_ZAC_MGMT_OUT; 583 auxiliary = action & 0xf; 584 if (all_zones != 0) 585 auxiliary |= (ZBC_OUT_ALL << 8); 586 } 587 588 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, 598 /*lba*/ lba, 599 /*command*/ command, 600 /*auxiliary*/ auxiliary, 601 /*data_ptr*/ NULL, 602 /*dxfer_len*/ 0, 603 /*cdb_storage*/ cdb_storage, 604 /*cdb_storage_len*/ cdb_storage_len, 605 /*sense_len*/ SSD_FULL_SIZE, 606 /*timeout*/ timeout ? timeout : 60000, 607 /*is48bit*/ 1, 608 /*devtype*/ devtype); 609 if (error != 0) { 610 warnx("%s: build_ata_cmd() failed, likely " 611 "programmer error", __func__); 612 goto bailout; 613 } 614 ata_format = 1; 615 break; 616 } 617 default: 618 warnx("%s: Unknown device type %d", __func__,devtype); 619 error = 1; 620 goto bailout; 621 break; /*NOTREACHED*/ 622 } 623 } 624 625 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 626 if (retry_count > 0) 627 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 628 629 error = cam_send_ccb(device, ccb); 630 if (error != 0) { 631 warn("error sending %s %s CCB", (devtype == CC_DT_SCSI) ? 632 "ZBC" : "ZAC Management", 633 (action == ZBC_IN_SA_REPORT_ZONES) ? "In" : "Out"); 634 error = -1; 635 goto bailout; 636 } 637 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); 640 error = 1; 641 goto bailout; 642 } 643 644 /* 645 * If we aren't reading the list of zones, we're done. 646 */ 647 if (action != ZBC_IN_SA_REPORT_ZONES) 648 goto bailout; 649 650 if (ccb->ccb_h.func_code == XPT_SCSI_IO) 651 valid_len = ccb->csio.dxfer_len - ccb->csio.resid; 652 else 653 valid_len = ccb->ataio.dxfer_len - ccb->ataio.resid; 654 655 zp_status = zone_rz_print(data_ptr, valid_len, ata_format, out_flags, 656 first_pass, &lba); 657 658 if (zp_status == ZONE_PRINT_MORE_DATA) { 659 bzero(ccb, sizeof(*ccb)); 660 first_pass = 0; 661 if (cdb_storage != NULL) 662 bzero(cdb_storage, cdb_storage_len); 663 goto restart_report; 664 } else if (zp_status == ZONE_PRINT_ERROR) 665 error = 1; 666 bailout: 667 if (ccb != NULL) 668 cam_freeccb(ccb); 669 670 free(data_ptr); 671 free(cdb_storage); 672 673 return (error); 674 } 675