Changeset View
Changeset View
Standalone View
Standalone View
sbin/camcontrol/camcontrol.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | typedef enum { | ||||
CAM_CMD_REPROBE, | CAM_CMD_REPROBE, | ||||
CAM_CMD_ZONE, | CAM_CMD_ZONE, | ||||
CAM_CMD_EPC, | CAM_CMD_EPC, | ||||
CAM_CMD_TIMESTAMP, | CAM_CMD_TIMESTAMP, | ||||
CAM_CMD_MMCSD_CMD, | CAM_CMD_MMCSD_CMD, | ||||
CAM_CMD_POWER_MODE, | CAM_CMD_POWER_MODE, | ||||
CAM_CMD_DEVTYPE, | CAM_CMD_DEVTYPE, | ||||
CAM_CMD_AMA, | CAM_CMD_AMA, | ||||
CAM_CMD_SMART_STATUS, | |||||
} cam_cmd; | } cam_cmd; | ||||
typedef enum { | typedef enum { | ||||
CAM_ARG_NONE = 0x00000000, | CAM_ARG_NONE = 0x00000000, | ||||
CAM_ARG_VERBOSE = 0x00000001, | CAM_ARG_VERBOSE = 0x00000001, | ||||
CAM_ARG_DEVICE = 0x00000002, | CAM_ARG_DEVICE = 0x00000002, | ||||
CAM_ARG_BUS = 0x00000004, | CAM_ARG_BUS = 0x00000004, | ||||
CAM_ARG_TARGET = 0x00000008, | CAM_ARG_TARGET = 0x00000008, | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | static struct camcontrol_opts option_table[] = { | ||||
{"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"}, | {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"}, | ||||
{"ama", CAM_CMD_AMA, CAM_ARG_NONE, "fqs:"}, | {"ama", CAM_CMD_AMA, CAM_ARG_NONE, "fqs:"}, | ||||
{"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"}, | {"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"}, | ||||
{"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"}, | {"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"}, | ||||
{"opcodes", CAM_CMD_OPCODES, CAM_ARG_NONE, "No:s:T"}, | {"opcodes", CAM_CMD_OPCODES, CAM_ARG_NONE, "No:s:T"}, | ||||
{"zone", CAM_CMD_ZONE, CAM_ARG_NONE, "ac:l:No:P:"}, | {"zone", CAM_CMD_ZONE, CAM_ARG_NONE, "ac:l:No:P:"}, | ||||
{"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"}, | {"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"}, | ||||
{"timestamp", CAM_CMD_TIMESTAMP, CAM_ARG_NONE, "f:mrsUT:"}, | {"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}, | {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, | ||||
{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, | {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, | ||||
{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, | {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, | ||||
{NULL, 0, 0, NULL} | {NULL, 0, 0, NULL} | ||||
}; | }; | ||||
struct cam_devitem { | struct cam_devitem { | ||||
struct device_match_result dev_match; | struct device_match_result dev_match; | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | |||||
static int scsiprintoneopcode(struct cam_device *device, int req_opcode, | static int scsiprintoneopcode(struct cam_device *device, int req_opcode, | ||||
int sa_set, int req_sa, uint8_t *buf, | int sa_set, int req_sa, uint8_t *buf, | ||||
uint32_t valid_len); | uint32_t valid_len); | ||||
static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf, | static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf, | ||||
uint32_t valid_len); | uint32_t valid_len); | ||||
static int scsiopcodes(struct cam_device *device, int argc, char **argv, | static int scsiopcodes(struct cam_device *device, int argc, char **argv, | ||||
char *combinedopt, int task_attr, int retry_count, | char *combinedopt, int task_attr, int retry_count, | ||||
int timeout, int verbose); | int timeout, int verbose); | ||||
static int atasmartstatus(struct cam_device *device); | |||||
#ifndef min | #ifndef min | ||||
#define min(a,b) (((a)<(b))?(a):(b)) | #define min(a,b) (((a)<(b))?(a):(b)) | ||||
#endif | #endif | ||||
#ifndef max | #ifndef max | ||||
#define max(a,b) (((a)>(b))?(a):(b)) | #define max(a,b) (((a)>(b))?(a):(b)) | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 9,494 Lines • ▼ Show 20 Lines | reprobe(struct cam_device *device) | ||||
} | } | ||||
bailout: | bailout: | ||||
cam_freeccb(ccb); | cam_freeccb(ccb); | ||||
return (retval); | 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) { | |||||
mav: It would be really good to support at very least SATL too. May be also SCSI and NVMe, even… | |||||
Not Done Inline ActionsAs mav@ points out, SATL device work just fine too. imp: As mav@ points out, SATL device work just fine too.
| |||||
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"); | |||||
mavUnsubmitted Not Done Inline ActionsWhy shutdown these days? mav: Why shutdown these days? | |||||
} else if (((ccb->ataio.res.lba_high << 8) | (ccb->ataio.res.lba_mid)) | |||||
== ATA_SMART_DEAD_STATUS) { | |||||
Not Done Inline ActionsI've been hacking on ATA-related code for ages, and this is the first time I've seen a reference to this value. Which version of the standard introduced it? rpokala: I've been hacking on ATA-related code for ages, and this is the first time I've seen a… | |||||
printf("camcontrol: *Dead* Device cannot be accessed.\n"); | |||||
} else { | |||||
printf("camcontrol: *Warning* Device status unknown.\n"); | |||||
} | |||||
return (retval); | |||||
} | |||||
void | void | ||||
usage(int printlong) | usage(int printlong) | ||||
{ | { | ||||
fprintf(printlong ? stdout : stderr, | fprintf(printlong ? stdout : stderr, | ||||
"usage: camcontrol <command> [device id][generic args][command args]\n" | "usage: camcontrol <command> [device id][generic args][command args]\n" | ||||
" camcontrol devlist [-b] [-v]\n" | " camcontrol devlist [-b] [-v]\n" | ||||
" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n" | " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n" | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
" camcontrol devtype [dev_id]\n" | " camcontrol devtype [dev_id]\n" | ||||
" camcontrol mmcsdcmd [dev_id] [[-c mmc_opcode] [-a mmc_arg]\n" | " camcontrol mmcsdcmd [dev_id] [[-c mmc_opcode] [-a mmc_arg]\n" | ||||
" [-f mmc_flags] [-l data_len]\n" | " [-f mmc_flags] [-l data_len]\n" | ||||
" [-W [-b data_byte]]] |\n" | " [-W [-b data_byte]]] |\n" | ||||
" [-F frequency] |\n" | " [-F frequency] |\n" | ||||
" [-I]\n" | " [-I]\n" | ||||
" [-1 | -4]\n" | " [-1 | -4]\n" | ||||
" [-S high|normal]\n" | " [-S high|normal]\n" | ||||
" \n" | " camcontrol smart [dev_id]\n" | ||||
" camcontrol help\n"); | " camcontrol help\n"); | ||||
if (!printlong) | if (!printlong) | ||||
return; | return; | ||||
fprintf(stdout, | fprintf(stdout, | ||||
"Specify one of the following options:\n" | "Specify one of the following options:\n" | ||||
"devlist list all CAM devices\n" | "devlist list all CAM devices\n" | ||||
"periphlist list all CAM peripheral drivers attached to a device\n" | "periphlist list all CAM peripheral drivers attached to a device\n" | ||||
"tur send a test unit ready to the named device\n" | "tur send a test unit ready to the named device\n" | ||||
Show All 30 Lines | |||||
"persist send the SCSI PERSISTENT RESERVE IN or OUT commands\n" | "persist send the SCSI PERSISTENT RESERVE IN or OUT commands\n" | ||||
"attrib send the SCSI READ or WRITE ATTRIBUTE commands\n" | "attrib send the SCSI READ or WRITE ATTRIBUTE commands\n" | ||||
"opcodes send the SCSI REPORT SUPPORTED OPCODES command\n" | "opcodes send the SCSI REPORT SUPPORTED OPCODES command\n" | ||||
"zone manage Zoned Block (Shingled) devices\n" | "zone manage Zoned Block (Shingled) devices\n" | ||||
"epc send ATA Extended Power Conditions commands\n" | "epc send ATA Extended Power Conditions commands\n" | ||||
"timestamp report or set the device's timestamp\n" | "timestamp report or set the device's timestamp\n" | ||||
"devtype report the type of device\n" | "devtype report the type of device\n" | ||||
"mmcsdcmd send the given MMC command, needs -c and -a as well\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" | "help this message\n" | ||||
"Device Identifiers:\n" | "Device Identifiers:\n" | ||||
"bus:target specify the bus and target, lun defaults to 0\n" | "bus:target specify the bus and target, lun defaults to 0\n" | ||||
"bus:target:lun specify the bus, target and lun\n" | "bus:target:lun specify the bus, target and lun\n" | ||||
"deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n" | "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n" | ||||
"Generic arguments:\n" | "Generic arguments:\n" | ||||
"-v be verbose, print out sense information\n" | "-v be verbose, print out sense information\n" | ||||
"-t timeout command timeout in seconds, overrides default timeout\n" | "-t timeout command timeout in seconds, overrides default timeout\n" | ||||
▲ Show 20 Lines • Show All 614 Lines • ▼ Show 20 Lines | main(int argc, char **argv) | ||||
case CAM_CMD_EPC: | case CAM_CMD_EPC: | ||||
error = epc(cam_dev, argc, argv, combinedopt, | error = epc(cam_dev, argc, argv, combinedopt, | ||||
retry_count, timeout, arglist & CAM_ARG_VERBOSE); | retry_count, timeout, arglist & CAM_ARG_VERBOSE); | ||||
break; | break; | ||||
case CAM_CMD_TIMESTAMP: | case CAM_CMD_TIMESTAMP: | ||||
error = timestamp(cam_dev, argc, argv, combinedopt, | error = timestamp(cam_dev, argc, argv, combinedopt, | ||||
task_attr, retry_count, timeout, | task_attr, retry_count, timeout, | ||||
arglist & CAM_ARG_VERBOSE); | arglist & CAM_ARG_VERBOSE); | ||||
break; | |||||
case CAM_CMD_SMART_STATUS: | |||||
error = atasmartstatus(cam_dev); | |||||
break; | break; | ||||
case CAM_CMD_USAGE: | case CAM_CMD_USAGE: | ||||
usage(1); | usage(1); | ||||
break; | break; | ||||
default: | default: | ||||
usage(0); | usage(0); | ||||
error = 1; | error = 1; | ||||
break; | break; | ||||
} | } | ||||
if (cam_dev != NULL) | if (cam_dev != NULL) | ||||
cam_close_device(cam_dev); | cam_close_device(cam_dev); | ||||
exit(error); | exit(error); | ||||
} | } |
It would be really good to support at very least SATL too. May be also SCSI and NVMe, even though SMART is very different there.