aboutsummaryrefslogtreecommitdiff
path: root/sbin/camcontrol
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2018-06-13 22:00:08 +0000
committerWarner Losh <imp@FreeBSD.org>2018-06-13 22:00:08 +0000
commit6ee13c54dad0b284e7882addaa892faa3aa8508d (patch)
tree48e4868861b20aabad5b6aacf0f4ca77ef6a9756 /sbin/camcontrol
parente505b7eced305ac00d082904713642baff4982df (diff)
downloadsrc-6ee13c54dad0b284e7882addaa892faa3aa8508d.tar.gz
src-6ee13c54dad0b284e7882addaa892faa3aa8508d.zip
Make camcontrol identify work with nda devices
Both ATA and NVME have an identify command. They are completely different, but to the user they are the same. Leverage nvmecontrol's print_controller code to provide that functionality to camcontrol identify. Query the path to see what kind of protocol it supports, and send the most appropriate command down. Refactor nvme_print_dev a little to make it easy to get the nvme cdata. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D15371
Notes
Notes: svn path=/head/; revision=335092
Diffstat (limited to 'sbin/camcontrol')
-rw-r--r--sbin/camcontrol/Makefile5
-rw-r--r--sbin/camcontrol/camcontrol.c67
2 files changed, 58 insertions, 14 deletions
diff --git a/sbin/camcontrol/Makefile b/sbin/camcontrol/Makefile
index a1ad69309c79..b4e81daeb0e4 100644
--- a/sbin/camcontrol/Makefile
+++ b/sbin/camcontrol/Makefile
@@ -8,6 +8,11 @@ SRCS+= attrib.c epc.c fwdownload.c modeedit.c persist.c progress.c timestamp.c z
.else
CFLAGS+= -DMINIMALISTIC
.endif
+.PATH: ${SRCTOP}/sbin/nvmecontrol
+CFLAGS+= -I${SRCTOP}/sbin/nvmecontrol
+SRCS+= identify_ext.c nc_util.c
+.PATH: ${SRCTOP}/sys/dev/nvme
+SRCS+= nvme_util.c
# This is verboten
.if ${MACHINE_CPUARCH} == "arm"
WARNS?= 3
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 1192d01cfee8..4d1811ffe71e 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <cam/mmc/mmc_all.h>
#include <camlib.h>
#include "camcontrol.h"
+#include "nvmecontrol_ext.h"
typedef enum {
CAM_CMD_NONE = 0x00000000,
@@ -763,21 +764,11 @@ print_dev_mmcsd(struct device_match_result *dev_result, char *tmpstr)
}
static int
-print_dev_nvme(struct device_match_result *dev_result, char *tmpstr)
+nvme_get_cdata(struct cam_device *dev, struct nvme_controller_data *cdata)
{
union ccb *ccb;
struct ccb_dev_advinfo *advi;
- struct cam_device *dev;
- struct nvme_controller_data cdata;
- char vendor[64], product[64];
- dev = cam_open_btl(dev_result->path_id, dev_result->target_id,
- dev_result->target_lun, O_RDWR, NULL);
- if (dev == NULL) {
- warnx("%s", cam_errbuf);
- return (1);
- }
-
ccb = cam_getccb(dev);
if (ccb == NULL) {
warnx("couldn't allocate CCB");
@@ -791,7 +782,7 @@ print_dev_nvme(struct device_match_result *dev_result, char *tmpstr)
advi->flags = CDAI_FLAG_NONE;
advi->buftype = CDAI_TYPE_NVME_CNTRL;
advi->bufsiz = sizeof(struct nvme_controller_data);
- advi->buf = (uint8_t *)&cdata;
+ advi->buf = (uint8_t *)cdata;
if (cam_send_ccb(dev, ccb) < 0) {
warn("error sending CAMIOCOMMAND ioctl");
@@ -805,11 +796,31 @@ print_dev_nvme(struct device_match_result *dev_result, char *tmpstr)
cam_close_device(dev);
return(1);
}
+ cam_freeccb(ccb);
+ return 0;
+}
+
+static int
+print_dev_nvme(struct device_match_result *dev_result, char *tmpstr)
+{
+ struct cam_device *dev;
+ struct nvme_controller_data cdata;
+ char vendor[64], product[64];
+
+ dev = cam_open_btl(dev_result->path_id, dev_result->target_id,
+ dev_result->target_lun, O_RDWR, NULL);
+ if (dev == NULL) {
+ warnx("%s", cam_errbuf);
+ return (1);
+ }
+
+ if (nvme_get_cdata(dev, &cdata))
+ return (1);
+
cam_strvis(vendor, cdata.mn, sizeof(cdata.mn), sizeof(vendor));
cam_strvis(product, cdata.fr, sizeof(cdata.fr), sizeof(product));
sprintf(tmpstr, "<%s %s>", vendor, product);
- cam_freeccb(ccb);
cam_close_device(dev);
return (0);
}
@@ -2390,6 +2401,34 @@ ataidentify(struct cam_device *device, int retry_count, int timeout)
return (0);
}
+
+static int
+nvmeidentify(struct cam_device *device, int retry_count __unused, int timeout __unused)
+{
+ struct nvme_controller_data cdata;
+
+ if (nvme_get_cdata(device, &cdata))
+ return (1);
+ nvme_print_controller(&cdata);
+
+ return (0);
+}
+
+static int
+identify(struct cam_device *device, int retry_count, int timeout)
+{
+ struct ccb_pathinq cpi;
+
+ if (get_cpi(device, &cpi) != 0) {
+ warnx("couldn't get CPI");
+ return (-1);
+ }
+
+ if (cpi.protocol == PROTO_NVME) {
+ return (nvmeidentify(device, retry_count, timeout));
+ }
+ return (ataidentify(device, retry_count, timeout));
+}
#endif /* MINIMALISTIC */
@@ -10058,7 +10097,7 @@ main(int argc, char **argv)
task_attr, retry_count, timeout);
break;
case CAM_CMD_IDENTIFY:
- error = ataidentify(cam_dev, retry_count, timeout);
+ error = identify(cam_dev, retry_count, timeout);
break;
case CAM_CMD_STARTSTOP:
error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,