diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -115,6 +115,7 @@ .Op Fl P .Op Fl G .Op Fl q +.Op Fl r Ar value .Op Fl s .Op Fl S Ar offset .Op Fl X @@ -645,7 +646,8 @@ .Tn SCSI READ DEFECT DATA (12) command (0xB7) to the given device, and print out any combination of: the total number of defects, the primary -defect list (PLIST), and the grown defect list (GLIST). +defect list (PLIST), the grown defect list (GLIST) and any vendor specific +defect list(s) that setting the reserve bits generate. .Bl -tag -width 11n .It Fl f Ar format Specify the requested format of the defect list. @@ -698,6 +700,12 @@ When printing status information with .Fl s , only print the number of defects. +.It Fl r Ar value +Sets the reserved bits of byte 2 of the READ DEFECT DATA command to +.Ar value +This causes vendor specific behavior, such as returning other types of +defects. +The value is ORed into byte 2 and may only specify bits in the mask 0xe0. .It Fl s Just print the number of defects, not the list of defects. .It Fl S Ar offset diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -175,7 +175,7 @@ }; static const char scsicmd_opts[] = "a:c:dfi:o:r"; -static const char readdefect_opts[] = "f:GPqsS:X"; +static const char readdefect_opts[] = "f:GPqr:sS:X"; static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; static const char smprg_opts[] = "l"; static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:"; @@ -3878,6 +3878,22 @@ case 'q': quiet = true; break; + case 'r': { + char *endptr; + unsigned long reserved; + const unsigned long byte2_defined = SRDD10_PLIST | + SRDD10_GLIST | SRDD10_DLIST_FORMAT_MASK; + + reserved = strtoul(optarg, &endptr, 0); + if (*endptr != '\0' || + (reserved & byte2_defined) || + reserved > 0xff) { + error = 1; + warnx("invalid reserved bits %s", optarg); + } + list_format |= reserved; + break; + } case 's': summary = true; break;