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