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