Page MenuHomeFreeBSD

D29992.diff
No OneTemporary

D29992.diff

Index: sbin/camcontrol/camcontrol.8
===================================================================
--- sbin/camcontrol/camcontrol.8
+++ sbin/camcontrol/camcontrol.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 6, 2019
+.Dd April 26, 2021
.Dt CAMCONTROL 8
.Os
.Sh NAME
@@ -366,6 +366,9 @@
.Ic devtype
.Op device id
.Nm
+.Ic smart
+.Op device id
+.Nm
.Ic help
.Sh DESCRIPTION
The
@@ -2594,6 +2597,8 @@
.It illegal
A programming error occurred
.El
+.It Ic smart
+Print out the SMART status for specified device.
.It Ic help
Print out verbose usage information.
.El
Index: sbin/camcontrol/camcontrol.c
===================================================================
--- sbin/camcontrol/camcontrol.c
+++ sbin/camcontrol/camcontrol.c
@@ -111,6 +111,7 @@
CAM_CMD_POWER_MODE,
CAM_CMD_DEVTYPE,
CAM_CMD_AMA,
+ CAM_CMD_SMART_STATUS,
} cam_cmd;
typedef enum {
@@ -228,6 +229,7 @@
{"zone", CAM_CMD_ZONE, CAM_ARG_NONE, "ac:l:No:P:"},
{"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"},
{"timestamp", CAM_CMD_TIMESTAMP, CAM_ARG_NONE, "f:mrsUT:"},
+ {"smart", CAM_CMD_SMART_STATUS, CAM_ARG_NONE, NULL},
{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
@@ -355,6 +357,7 @@
static int scsiopcodes(struct cam_device *device, int argc, char **argv,
char *combinedopt, int task_attr, int retry_count,
int timeout, int verbose);
+static int atasmartstatus(struct cam_device *device);
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
@@ -9865,6 +9868,72 @@
return (retval);
}
+static int
+atasmartstatus(struct cam_device *device)
+{
+ union ccb *ccb;
+ camcontrol_devtype devtype;
+ uint32_t flags = CAM_DIR_NONE;
+ int retry_count = 1, timeout = 0, retval = 0;
+
+ if (get_device_type(device, retry_count, timeout, 0, &devtype) != 0) {
+ warnx("atasmartstatus: Error getting device type.\n");
+ return(1);
+ }
+
+ if (devtype != CC_DT_ATA) {
+ warnx("atasmartstatus: %s is not an ATA device.\n", device->given_dev_name);
+ return(1);
+ }
+ ccb = cam_getccb(device);
+ if (ccb == NULL) {
+ warnx("atasmartstatus: Error allocating CCB.\n");
+ return(1);
+ }
+
+ ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
+ ccb->ataio.cmd.command = ATA_SMART_CMD;
+ ccb->ataio.cmd.features = ATA_SMART_RETURN_STATUS_FEATURE;
+ ccb->ataio.cmd.lba_mid = (ATA_SMART_GOOD_STATUS & 0xFF);
+ ccb->ataio.cmd.lba_high = (ATA_SMART_GOOD_STATUS >> 8);
+ cam_fill_ataio(&ccb->ataio,
+ /*retries*/ retry_count,
+ /*cbfcnp*/ NULL,
+ /*flags*/ flags,
+ /*tag_action*/ 0,
+ /*data_ptr*/ NULL,
+ /*dxfer_len*/ 0,
+ /*timeout*/ timeout ? timeout : 5000);
+
+ if (((retval = cam_send_ccb(device, ccb)) < 0)
+ || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
+ const char warnstr[] =
+ "atasmartstatus: error sending ATA smart status command";
+
+ if (retval < 0)
+ warn(warnstr);
+ else
+ warnx(warnstr);
+ return (1);
+ }
+
+ if (((ccb->ataio.res.lba_high << 8) | (ccb->ataio.res.lba_mid)) ==
+ ATA_SMART_GOOD_STATUS) {
+ printf("camcontrol: *Good* The device hasn't detected a threshold exceeding condition.\n");
+ } else if (((ccb->ataio.res.lba_high << 8) | (ccb->ataio.res.lba_mid))
+ == ATA_SMART_BAD_STATUS) {
+ printf("camcontrol: *FAILURE* : The device has detected a threshold exceeding condition.\n" \
+ "Please shutdown the system and replace the device ASAP\n");
+ } else if (((ccb->ataio.res.lba_high << 8) | (ccb->ataio.res.lba_mid))
+ == ATA_SMART_DEAD_STATUS) {
+ printf("camcontrol: *Dead* Device cannot be accessed.\n");
+ } else {
+ printf("camcontrol: *Warning* Device status unknown.\n");
+ }
+
+ return (retval);
+}
+
void
usage(int printlong)
{
@@ -9953,7 +10022,7 @@
" [-I]\n"
" [-1 | -4]\n"
" [-S high|normal]\n"
-" \n"
+" camcontrol smart [dev_id]\n"
" camcontrol help\n");
if (!printlong)
return;
@@ -10000,6 +10069,7 @@
"timestamp report or set the device's timestamp\n"
"devtype report the type of device\n"
"mmcsdcmd send the given MMC command, needs -c and -a as well\n"
+"smart display the smart status of the ATA device\n"
"help this message\n"
"Device Identifiers:\n"
"bus:target specify the bus and target, lun defaults to 0\n"
@@ -10631,6 +10701,9 @@
task_attr, retry_count, timeout,
arglist & CAM_ARG_VERBOSE);
break;
+ case CAM_CMD_SMART_STATUS:
+ error = atasmartstatus(cam_dev);
+ break;
case CAM_CMD_USAGE:
usage(1);
break;
Index: sys/sys/ata.h
===================================================================
--- sys/sys/ata.h
+++ sys/sys/ata.h
@@ -459,6 +459,10 @@
#define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
#define ATA_SERVICE 0xa2 /* service command */
#define ATA_SMART_CMD 0xb0 /* SMART command */
+#define ATA_SMART_RETURN_STATUS_FEATURE 0xDA
+#define ATA_SMART_GOOD_STATUS 0xC24F
+#define ATA_SMART_BAD_STATUS 0x2CF4
+#define ATA_SMART_DEAD_STATUS 0xDEAD
#define ATA_SANITIZE 0xb4 /* sanitize device */
#define ATA_CFA_ERASE 0xc0 /* CFA erase */
#define ATA_READ_MUL 0xc4 /* read multi */

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 15, 6:57 PM (7 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29728510
Default Alt Text
D29992.diff (5 KB)

Event Timeline