Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110227620
D43225.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D43225.diff
View Options
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 1, 2023
+.Dd December 28, 2023
.Dt CAMCONTROL 8
.Os
.Sh NAME
@@ -51,6 +51,12 @@
.Op device id
.Op generic args
.Nm
+.Ic sense
+.Op device id
+.Op generic args
+.Op Fl D
+.Op Fl x
+.Nm
.Ic inquiry
.Op device id
.Op generic args
@@ -488,6 +494,15 @@
The
.Nm
utility will report whether the device is ready or not.
+.It Ic sense
+Send a SCSI REQUEST SENSE command (0x03) to a device.
+The decoded sense (or hexdump) is printed to stdout.
+.Bl -tag -width 4n
+.It Fl D
+Request descriptor sense instead of fixed sense.
+.It Fl x
+Do a hexdump of the returned sense data.
+.El
.It Ic inquiry
Send a SCSI inquiry command (0x12) to a device.
By default,
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -111,6 +111,7 @@
CAM_CMD_DEVTYPE,
CAM_CMD_AMA,
CAM_CMD_DEPOP,
+ CAM_CMD_REQSENSE
} cam_cmd;
typedef enum {
@@ -233,6 +234,7 @@
{"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"},
{"timestamp", CAM_CMD_TIMESTAMP, CAM_ARG_NONE, "f:mrsUT:"},
{"depop", CAM_CMD_DEPOP, CAM_ARG_NONE, "ac:de:ls"},
+ {"sense", CAM_CMD_REQSENSE, CAM_ARG_NONE, "Dx"},
{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
@@ -279,6 +281,9 @@
#ifdef WITH_NVME
static int print_dev_nvme(struct device_match_result *dev_result, char *tmpstr);
#endif
+static int requestsense(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int task_attr, int retry_count,
+ int timeout);
static int testunitready(struct cam_device *device, int task_attr,
int retry_count, int timeout, int quiet);
static int scsistart(struct cam_device *device, int startstop, int loadeject,
@@ -840,6 +845,114 @@
}
#endif
+static int
+requestsense(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int task_attr, int retry_count, int timeout)
+{
+ int c;
+ int descriptor_sense = 0;
+ int do_hexdump = 0;
+ struct scsi_sense_data sense;
+ union ccb *ccb = NULL;
+ int error = 0;
+ size_t returned_bytes;
+
+ while ((c = getopt(argc, argv, combinedopt)) != -1) {
+ switch (c) {
+ case 'D':
+ descriptor_sense = 1;
+ break;
+ case 'x':
+ do_hexdump = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ccb = cam_getccb(device);
+ if (ccb == NULL) {
+ warnx("couldn't allocate CCB");
+ return (1);
+ }
+
+ /* cam_getccb cleans up the header, caller has to zero the payload */
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
+
+ bzero(&sense, sizeof(sense));
+
+ scsi_request_sense(&ccb->csio,
+ /*retries*/ retry_count,
+ /*cbfcnp*/ NULL,
+ /*data_ptr*/ (void *)&sense,
+ /*dxfer_len*/ sizeof(sense),
+ /*tag_action*/ task_attr,
+ /*sense_len*/ SSD_FULL_SIZE,
+ /*timeout*/ timeout ? timeout : 60000);
+
+ if (descriptor_sense != 0) {
+ struct scsi_request_sense *cdb;
+
+ cdb = (struct scsi_request_sense *)&ccb->csio.cdb_io.cdb_bytes;
+ cdb->byte2 |= SRS_DESC;
+ }
+
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+ if (arglist & CAM_ARG_ERR_RECOVER)
+ ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ warn("error sending REQUEST SENSE command");
+ cam_freeccb(ccb);
+ error = 1;
+ goto bailout;
+ }
+
+ /*
+ * REQUEST SENSE is not generally supposed to fail. But there can
+ * be transport or other errors that might cause it to fail. It
+ * may also fail if the user asks for descriptor sense and the
+ * device doesn't support it. So we check the CCB status here to see.
+ */
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ warnx("REQUEST SENSE failed");
+ cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+ error = 1;
+ goto bailout;
+ }
+
+ returned_bytes = ccb->csio.dxfer_len - ccb->csio.resid;
+
+ if (do_hexdump != 0) {
+ hexdump(&sense, returned_bytes, NULL, 0);
+ } else {
+ char path_str[80];
+ struct sbuf *sb;
+
+ cam_path_string(device, path_str, sizeof(path_str));
+ sb = sbuf_new_auto();
+ if (sb == NULL) {
+ warnx("%s: cannot allocate sbuf", __func__);
+ error = 1;
+ goto bailout;
+ }
+
+ scsi_sense_only_sbuf(&sense, returned_bytes, sb, path_str,
+ &device->inq_data, scsiio_cdb_ptr(&ccb->csio),
+ ccb->csio.cdb_len);
+
+ sbuf_finish(sb);
+ printf("%s", sbuf_data(sb));
+ sbuf_delete(sb);
+ }
+bailout:
+ if (ccb != NULL)
+ cam_freeccb(ccb);
+
+ return (error);
+}
+
static int
testunitready(struct cam_device *device, int task_attr, int retry_count,
int timeout, int quiet)
@@ -9869,6 +9982,7 @@
" camcontrol devlist [-b] [-v]\n"
" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
" camcontrol tur [dev_id][generic args]\n"
+" camcontrol sense [dev_id][generic args][-D][-x]\n"
" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
" camcontrol identify [dev_id][generic args] [-v]\n"
" camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
@@ -9957,6 +10071,7 @@
"Specify one of the following options:\n"
"devlist list all CAM devices\n"
"periphlist list all CAM peripheral drivers attached to a device\n"
+"sense send a request sense command to the named device\n"
"tur send a test unit ready to the named device\n"
"inquiry send a SCSI inquiry command to the named device\n"
"identify send a ATA identify command to the named device\n"
@@ -10021,6 +10136,9 @@
"-f format specify defect list format (block, bfi or phys)\n"
"-G get the grown defect list\n"
"-P get the permanent defect list\n"
+"sense arguments:\n"
+"-D request descriptor sense data\n"
+"-x do a hexdump of the sense data\n"
"inquiry arguments:\n"
"-D get the standard inquiry data\n"
"-S get the serial number\n"
@@ -10491,6 +10609,10 @@
case CAM_CMD_DEVTYPE:
error = getdevtype(cam_dev);
break;
+ case CAM_CMD_REQSENSE:
+ error = requestsense(cam_dev, argc, argv, combinedopt,
+ task_attr, retry_count, timeout);
+ break;
case CAM_CMD_TUR:
error = testunitready(cam_dev, task_attr, retry_count,
timeout, 0);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 16, 10:05 AM (15 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16672393
Default Alt Text
D43225.diff (6 KB)
Attached To
Mode
D43225: Add a sense subcommand to camcontrol(8)
Attached
Detach File
Event Timeline
Log In to Comment