Implement a devtype command.

List the device's protocol. The returned value is one of the following:
	ata	direct attach ATA or SATA device
	satl	a SATA device attached via SAS
	scsi	A parallel SCSI or SAS
	nvme	A direct attached NVMe device
	mmcsd	A MMC or SD attached device

Reviewed by: scottl@, rpokala@
Differential Revision: https://reviews.freebsd.org/D20950
This commit is contained in:
Warner Losh 2019-07-15 22:33:37 +00:00
parent 32451fb9fc
commit d455c0d04a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=350018
2 changed files with 88 additions and 16 deletions

View File

@ -353,6 +353,9 @@
.Op generic args
.Ao Fl r Oo Ns Fl f Ar format | Fl m | Fl U Oc | Fl s Ao Fl f Ar format Fl T Ar time | Fl U Ac Ac
.Nm
.Ic devtype
.Op device id
.Nm
.Ic help
.Sh DESCRIPTION
The
@ -2516,6 +2519,26 @@ option.
Set the timestamp to the host system's time in UTC.
.El
.El
.It Ic devtype
Print out the device type for specified device.
.Bl -tag -width 10n
.It ata
An ATA device attached directly to an ATA controller
.It satl
An SATA device attached behind a SAS controller via SCSI-ATA Translation Layer (SATL)
.It scsi
A SCSI device
.It nvme
An directly attached NVMe device
.It mmcsd
An MMC or SD device attached via a mmcsd bus
.It none
No device type reported
.It unknown
Device type is unknown
.It illegal
A programming error occurred
.El
.It Ic help
Print out verbose usage information.
.El

View File

@ -109,6 +109,7 @@ typedef enum {
CAM_CMD_TIMESTAMP = 0x00000028,
CAM_CMD_MMCSD_CMD = 0x00000029,
CAM_CMD_POWER_MODE = 0x0000002a,
CAM_CMD_DEVTYPE = 0x0000002b,
} cam_cmdmask;
typedef enum {
@ -217,6 +218,7 @@ static struct camcontrol_opts option_table[] = {
{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
{"devtype", CAM_CMD_DEVTYPE, CAM_ARG_NONE, ""},
{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
@ -263,11 +265,22 @@ struct cam_devlist {
static cam_cmdmask cmdlist;
static cam_argmask arglist;
static const char *devtype_names[] = {
"none",
"scsi",
"satl",
"ata",
"nvme",
"mmcsd",
"unknown",
};
camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
uint32_t *cmdnum, cam_argmask *argnum,
const char **subopt);
static int getdevlist(struct cam_device *device);
static int getdevtree(int argc, char **argv, char *combinedopt);
static int getdevtype(struct cam_device *device);
static int print_dev_scsi(struct device_match_result *dev_result, char *tmpstr);
static int print_dev_ata(struct device_match_result *dev_result, char *tmpstr);
static int print_dev_semb(struct device_match_result *dev_result, char *tmpstr);
@ -653,6 +666,24 @@ getdevtree(int argc, char **argv, char *combinedopt)
return (error);
}
static int
getdevtype(struct cam_device *cam_dev)
{
camcontrol_devtype dt;
int error;
/*
* Get the device type and report it, request no I/O be done to do this.
*/
error = get_device_type(cam_dev, -1, 0, 0, &dt);
if (error != 0 || dt < CC_DT_NONE || dt > CC_DT_UNKNOWN) {
fprintf(stdout, "illegal\n");
return (1);
}
fprintf(stdout, "%s\n", devtype_names[dt]);
return (0);
}
static int
print_dev_scsi(struct device_match_result *dev_result, char *tmpstr)
{
@ -5351,7 +5382,7 @@ get_device_type(struct cam_device *dev, int retry_count, int timeout,
int verbosemode, camcontrol_devtype *devtype)
{
struct ccb_getdev cgd;
int retval = 0;
int retval;
retval = get_cgd(dev, &cgd);
if (retval != 0)
@ -5380,21 +5411,34 @@ get_device_type(struct cam_device *dev, int retry_count, int timeout,
break; /*NOTREACHED*/
}
/*
* Check for the ATA Information VPD page (0x89). If this is an
* ATA device behind a SCSI to ATA translation layer, this VPD page
* should be present.
*
* If that VPD page isn't present, or we get an error back from the
* INQUIRY command, we'll just treat it as a normal SCSI device.
*/
retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
timeout, verbosemode);
if (retval == 1)
*devtype = CC_DT_SATL;
else
*devtype = CC_DT_SCSI;
if (retry_count == -1) {
/*
* For a retry count of -1, used only the cached data to avoid
* I/O to the drive. Sending the identify command to the drive
* can cause issues for SATL attachaed drives since identify is
* not an NCQ command.
*/
if (cgd.ident_data.config != 0)
*devtype = CC_DT_SATL;
else
*devtype = CC_DT_SCSI;
} else {
/*
* Check for the ATA Information VPD page (0x89). If this is an
* ATA device behind a SCSI to ATA translation layer (SATL),
* this VPD page should be present.
*
* If that VPD page isn't present, or we get an error back from
* the INQUIRY command, we'll just treat it as a normal SCSI
* device.
*/
retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
timeout, verbosemode);
if (retval == 1)
*devtype = CC_DT_SATL;
else
*devtype = CC_DT_SCSI;
}
retval = 0;
bailout:
@ -9620,6 +9664,7 @@ usage(int printlong)
" [-S power_src] [-T timer]\n"
" camcontrol timestamp [dev_id][generic_args] <-r [-f format|-m|-U]>|\n"
" <-s <-f format -T time | -U >>\n"
" camcontrol devtype [dev_id]\n"
" \n"
" camcontrol help\n");
if (!printlong)
@ -9665,6 +9710,7 @@ usage(int printlong)
"zone manage Zoned Block (Shingled) devices\n"
"epc send ATA Extended Power Conditions commands\n"
"timestamp report or set the device's timestamp\n"
"devtype report the type of device\n"
"help this message\n"
"Device Identifiers:\n"
"bus:target specify the bus and target, lun defaults to 0\n"
@ -10128,6 +10174,9 @@ main(int argc, char **argv)
case CAM_CMD_DEVTREE:
error = getdevtree(argc, argv, combinedopt);
break;
case CAM_CMD_DEVTYPE:
error = getdevtype(cam_dev);
break;
case CAM_CMD_TUR:
error = testunitready(cam_dev, task_attr, retry_count,
timeout, 0);