diff options
Diffstat (limited to 'sbin/camcontrol/camcontrol.c')
-rw-r--r-- | sbin/camcontrol/camcontrol.c | 508 |
1 files changed, 318 insertions, 190 deletions
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 489c3026537a..15a5d42a2ba5 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -27,8 +27,6 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/ioctl.h> #include <sys/stdint.h> #include <sys/types.h> @@ -36,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/endian.h> #include <sys/sbuf.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -45,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <fcntl.h> #include <ctype.h> #include <err.h> +#include <libnvmf.h> #include <libutil.h> #include <limits.h> #include <inttypes.h> @@ -61,9 +61,7 @@ __FBSDID("$FreeBSD$"); #include <cam/mmc/mmc_all.h> #include <camlib.h> #include "camcontrol.h" -#ifdef WITH_NVME #include "nvmecontrol_ext.h" -#endif typedef enum { CAM_CMD_NONE, @@ -112,6 +110,7 @@ typedef enum { CAM_CMD_DEVTYPE, CAM_CMD_AMA, CAM_CMD_DEPOP, + CAM_CMD_REQSENSE } cam_cmd; typedef enum { @@ -123,18 +122,21 @@ typedef enum { CAM_ARG_LUN = 0x00000010, CAM_ARG_EJECT = 0x00000020, CAM_ARG_UNIT = 0x00000040, - CAM_ARG_FORMAT_BLOCK = 0x00000080, - CAM_ARG_FORMAT_BFI = 0x00000100, - CAM_ARG_FORMAT_PHYS = 0x00000200, - CAM_ARG_PLIST = 0x00000400, - CAM_ARG_GLIST = 0x00000800, + /* unused 0x00000080 */ + /* unused 0x00000100 */ + /* unused 0x00000200 */ + /* unused 0x00000400 */ + /* unused 0x00000800 */ CAM_ARG_GET_SERIAL = 0x00001000, CAM_ARG_GET_STDINQ = 0x00002000, CAM_ARG_GET_XFERRATE = 0x00004000, CAM_ARG_INQ_MASK = 0x00007000, + /* unused 0x00008000 */ + /* unused 0x00010000 */ CAM_ARG_TIMEOUT = 0x00020000, CAM_ARG_CMD_IN = 0x00040000, CAM_ARG_CMD_OUT = 0x00080000, + /* unused 0x00100000 */ CAM_ARG_ERR_RECOVER = 0x00200000, CAM_ARG_RETRIES = 0x00400000, CAM_ARG_START_UNIT = 0x00800000, @@ -145,6 +147,7 @@ typedef enum { CAM_ARG_DEBUG_XPT = 0x10000000, CAM_ARG_DEBUG_PERIPH = 0x20000000, CAM_ARG_DEBUG_PROBE = 0x40000000, + /* unused 0x80000000 */ } cam_argmask; struct camcontrol_opts { @@ -156,9 +159,9 @@ struct camcontrol_opts { struct ata_set_max_pwd { - u_int16_t reserved1; - u_int8_t password[32]; - u_int16_t reserved2[239]; + uint16_t reserved1; + uint8_t password[32]; + uint16_t reserved2[239]; }; static struct scsi_nv task_attrs[] = { @@ -230,6 +233,7 @@ static struct camcontrol_opts option_table[] = { {"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}, @@ -273,9 +277,10 @@ 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); static int print_dev_mmcsd(struct device_match_result *dev_result, char *tmpstr); -#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, @@ -592,14 +597,12 @@ getdevtree(int argc, char **argv, char *combinedopt) skip_device = 1; break; } -#ifdef WITH_NVME } else if (dev_result->protocol == PROTO_NVME) { if (print_dev_nvme(dev_result, &tmpstr[0]) != 0) { skip_device = 1; break; } -#endif } else { sprintf(tmpstr, "<>"); } @@ -650,6 +653,7 @@ getdevtree(int argc, char **argv, char *combinedopt) if (need_close) fprintf(stdout, ")\n"); + free(ccb.cdm.matches); close(fd); return (error); @@ -773,7 +777,6 @@ print_dev_mmcsd(struct device_match_result *dev_result, char *tmpstr) return (0); } -#ifdef WITH_NVME static int nvme_get_cdata(struct cam_device *dev, struct nvme_controller_data *cdata) { @@ -835,7 +838,114 @@ print_dev_nvme(struct device_match_result *dev_result, char *tmpstr) cam_close_device(dev); return (0); } -#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, @@ -1042,7 +1152,7 @@ scsiinquiry(struct cam_device *device, int task_attr, int retry_count, * - The SCSI spec says that when a length field is only 1 byte, * a value of 0 will be interpreted as 256. Therefore * scsi_inquiry() will convert an inq_len (which is passed in as - * a u_int32_t, but the field in the CDB is only 1 byte) of 256 + * a uint32_t, but the field in the CDB is only 1 byte) of 256 * to 0. Evidently, very few devices meet the spec in that * regard. Some devices, like many Seagate disks, take the 0 as * 0, and don't return any data. One Pioneer DVD-R drive @@ -1070,7 +1180,7 @@ scsiinquiry(struct cam_device *device, int task_attr, int retry_count, /* retries */ retry_count, /* cbfcnp */ NULL, /* tag_action */ task_attr, - /* inq_buf */ (u_int8_t *)inq_buf, + /* inq_buf */ (uint8_t *)inq_buf, /* inq_len */ SHORT_INQUIRY_LENGTH, /* evpd */ 0, /* page_code */ 0, @@ -1143,7 +1253,7 @@ scsiserial(struct cam_device *device, int task_attr, int retry_count, /*retries*/ retry_count, /*cbfcnp*/ NULL, /* tag_action */ task_attr, - /* inq_buf */ (u_int8_t *)serial_buf, + /* inq_buf */ (uint8_t *)serial_buf, /* inq_len */ sizeof(*serial_buf), /* evpd */ 1, /* page_code */ SVPD_UNIT_SERIAL_NUMBER, @@ -1198,8 +1308,8 @@ int camxferrate(struct cam_device *device) { struct ccb_pathinq cpi; - u_int32_t freq = 0; - u_int32_t speed = 0; + uint32_t freq = 0; + uint32_t speed = 0; union ccb *ccb; u_int mb; int retval = 0; @@ -1360,8 +1470,8 @@ xferrate_bailout: static void atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header) { - u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | - ((u_int32_t)parm->lba_size_2 << 16); + uint32_t lbasize = (uint32_t)parm->lba_size_1 | + ((uint32_t)parm->lba_size_2 << 16); u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) | ((u_int64_t)parm->lba_size48_2 << 16) | @@ -1393,8 +1503,8 @@ atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header) static void ataama_print(struct ata_params *parm, u_int64_t nativesize, int header) { - u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | - ((u_int32_t)parm->lba_size_2 << 16); + uint32_t lbasize = (uint32_t)parm->lba_size_1 | + ((uint32_t)parm->lba_size_2 << 16); u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) | ((u_int64_t)parm->lba_size48_2 << 16) | @@ -1432,8 +1542,8 @@ static void atacapprint(struct ata_params *parm) { const char *proto; - u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | - ((u_int32_t)parm->lba_size_2 << 16); + uint32_t lbasize = (uint32_t)parm->lba_size_1 | + ((uint32_t)parm->lba_size_2 << 16); u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) | ((u_int64_t)parm->lba_size48_2 << 16) | @@ -1750,7 +1860,7 @@ scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb) /* * Consider any non-CAM_REQ_CMP status as error and report it here, - * unless caller set AP_FLAG_CHK_COND, in which case it is reponsible. + * unless caller set AP_FLAG_CHK_COND, in which case it is responsible. */ if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) && (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { @@ -1788,7 +1898,7 @@ ata_cam_send(struct cam_device *device, union ccb *ccb) /* * Consider any non-CAM_REQ_CMP status as error and report it here, - * unless caller set AP_FLAG_CHK_COND, in which case it is reponsible. + * unless caller set AP_FLAG_CHK_COND, in which case it is responsible. */ if (!(ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT) && (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { @@ -1805,10 +1915,10 @@ ata_cam_send(struct cam_device *device, union ccb *ccb) static int ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries, - u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags, - u_int8_t tag_action, u_int8_t command, u_int16_t features, - u_int64_t lba, u_int16_t sector_count, u_int8_t *data_ptr, - u_int16_t dxfer_len, int timeout) + uint32_t flags, uint8_t protocol, uint8_t ata_flags, + uint8_t tag_action, uint8_t command, uint16_t features, + u_int64_t lba, uint16_t sector_count, uint8_t *data_ptr, + uint16_t dxfer_len, int timeout) { if (data_ptr != NULL) { if (flags & CAM_DIR_OUT) @@ -1862,10 +1972,10 @@ ata_try_pass_16(struct cam_device *device) static int ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries, - u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags, - u_int8_t tag_action, u_int8_t command, u_int16_t features, - u_int64_t lba, u_int16_t sector_count, u_int8_t *data_ptr, - u_int16_t dxfer_len, int timeout, int force48bit) + uint32_t flags, uint8_t protocol, uint8_t ata_flags, + uint8_t tag_action, uint8_t command, uint16_t features, + u_int64_t lba, uint16_t sector_count, uint8_t *data_ptr, + uint16_t dxfer_len, int timeout, int force48bit) { int retval; @@ -1962,12 +2072,12 @@ atahpa_proc_resp(struct cam_device *device, union ccb *ccb, u_int64_t *hpasize) static int ata_read_native_max(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, + uint32_t timeout, union ccb *ccb, struct ata_params *parm, u_int64_t *hpasize) { int error; u_int cmd, is48bit; - u_int8_t protocol; + uint8_t protocol; is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48; protocol = AP_PROTO_NON_DATA; @@ -1992,7 +2102,7 @@ ata_read_native_max(struct cam_device *device, int retry_count, /*sector_count*/0, /*data_ptr*/NULL, /*dxfer_len*/0, - timeout ? timeout : 5000, + timeout ? timeout : 10 * 1000, is48bit); if (error) @@ -2003,12 +2113,12 @@ ata_read_native_max(struct cam_device *device, int retry_count, static int atahpa_set_max(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, + uint32_t timeout, union ccb *ccb, int is48bit, u_int64_t maxsize, int persist) { int error; u_int cmd; - u_int8_t protocol; + uint8_t protocol; protocol = AP_PROTO_NON_DATA; @@ -2047,11 +2157,11 @@ atahpa_set_max(struct cam_device *device, int retry_count, static int atahpa_password(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, + uint32_t timeout, union ccb *ccb, int is48bit, struct ata_set_max_pwd *pwd) { u_int cmd; - u_int8_t protocol; + uint8_t protocol; protocol = AP_PROTO_PIO_OUT; cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; @@ -2068,7 +2178,7 @@ atahpa_password(struct cam_device *device, int retry_count, /*features*/ATA_HPA_FEAT_SET_PWD, /*lba*/0, /*sector_count*/sizeof(*pwd) / 512, - /*data_ptr*/(u_int8_t*)pwd, + /*data_ptr*/(uint8_t*)pwd, /*dxfer_len*/sizeof(*pwd), timeout ? timeout : 1000, is48bit)); @@ -2076,10 +2186,10 @@ atahpa_password(struct cam_device *device, int retry_count, static int atahpa_lock(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, int is48bit) + uint32_t timeout, union ccb *ccb, int is48bit) { u_int cmd; - u_int8_t protocol; + uint8_t protocol; protocol = AP_PROTO_NON_DATA; cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; @@ -2103,11 +2213,11 @@ atahpa_lock(struct cam_device *device, int retry_count, static int atahpa_unlock(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, + uint32_t timeout, union ccb *ccb, int is48bit, struct ata_set_max_pwd *pwd) { u_int cmd; - u_int8_t protocol; + uint8_t protocol; protocol = AP_PROTO_PIO_OUT; cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; @@ -2124,7 +2234,7 @@ atahpa_unlock(struct cam_device *device, int retry_count, /*features*/ATA_HPA_FEAT_UNLOCK, /*lba*/0, /*sector_count*/sizeof(*pwd) / 512, - /*data_ptr*/(u_int8_t*)pwd, + /*data_ptr*/(uint8_t*)pwd, /*dxfer_len*/sizeof(*pwd), timeout ? timeout : 1000, is48bit)); @@ -2132,10 +2242,10 @@ atahpa_unlock(struct cam_device *device, int retry_count, static int atahpa_freeze_lock(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, int is48bit) + uint32_t timeout, union ccb *ccb, int is48bit) { u_int cmd; - u_int8_t protocol; + uint8_t protocol; protocol = AP_PROTO_NON_DATA; cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; @@ -2159,7 +2269,7 @@ atahpa_freeze_lock(struct cam_device *device, int retry_count, static int ata_get_native_max(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, + uint32_t timeout, union ccb *ccb, u_int64_t *nativesize) { int error; @@ -2188,7 +2298,7 @@ ata_get_native_max(struct cam_device *device, int retry_count, static int ataama_set(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb, u_int64_t maxsize) + uint32_t timeout, union ccb *ccb, u_int64_t maxsize) { int error; @@ -2220,7 +2330,7 @@ ataama_set(struct cam_device *device, int retry_count, static int ataama_freeze(struct cam_device *device, int retry_count, - u_int32_t timeout, union ccb *ccb) + uint32_t timeout, union ccb *ccb) { return (ata_do_cmd(device, @@ -2249,7 +2359,7 @@ ata_do_identify(struct cam_device *device, int retry_count, int timeout, struct ccb_getdev cgd; u_int i, error; int16_t *ptr; - u_int8_t command, retry_command; + uint8_t command, retry_command; if (get_cpi(device, &cpi) != 0) { warnx("couldn't get CPI"); @@ -2291,7 +2401,7 @@ retry: /*features*/0, /*lba*/0, /*sector_count*/sizeof(struct ata_params) / 512, - /*data_ptr*/(u_int8_t *)ptr, + /*data_ptr*/(uint8_t *)ptr, /*dxfer_len*/sizeof(struct ata_params), /*timeout*/timeout ? timeout : 30 * 1000, /*force48bit*/0); @@ -2373,7 +2483,6 @@ ataidentify(struct cam_device *device, int retry_count, int timeout) return (0); } -#ifdef WITH_NVME static int nvmeidentify(struct cam_device *device, int retry_count __unused, int timeout __unused) { @@ -2385,12 +2494,10 @@ nvmeidentify(struct cam_device *device, int retry_count __unused, int timeout __ return (0); } -#endif static int identify(struct cam_device *device, int retry_count, int timeout) { -#ifdef WITH_NVME struct ccb_pathinq cpi; if (get_cpi(device, &cpi) != 0) { @@ -2401,7 +2508,6 @@ identify(struct cam_device *device, int retry_count, int timeout) if (cpi.protocol == PROTO_NVME) { return (nvmeidentify(device, retry_count, timeout)); } -#endif return (ataidentify(device, retry_count, timeout)); } @@ -2417,7 +2523,7 @@ enum { }; static void -atasecurity_print_time(u_int16_t tw) +atasecurity_print_time(uint16_t tw) { if (tw == 0) @@ -2428,8 +2534,8 @@ atasecurity_print_time(u_int16_t tw) printf("%i min", 2 * tw); } -static u_int32_t -atasecurity_erase_timeout_msecs(u_int16_t timeout) +static uint32_t +atasecurity_erase_timeout_msecs(uint16_t timeout) { if (timeout == 0) @@ -2442,7 +2548,7 @@ atasecurity_erase_timeout_msecs(u_int16_t timeout) static void -atasecurity_notify(u_int8_t command, struct ata_security_password *pwd) +atasecurity_notify(uint8_t command, struct ata_security_password *pwd) { struct ata_cmd cmd; @@ -2472,7 +2578,7 @@ atasecurity_notify(u_int8_t command, struct ata_security_password *pwd) static int atasecurity_freeze(struct cam_device *device, union ccb *ccb, - int retry_count, u_int32_t timeout, int quiet) + int retry_count, uint32_t timeout, int quiet) { if (quiet == 0) @@ -2497,7 +2603,7 @@ atasecurity_freeze(struct cam_device *device, union ccb *ccb, static int atasecurity_unlock(struct cam_device *device, union ccb *ccb, - int retry_count, u_int32_t timeout, + int retry_count, uint32_t timeout, struct ata_security_password *pwd, int quiet) { @@ -2516,7 +2622,7 @@ atasecurity_unlock(struct cam_device *device, union ccb *ccb, /*features*/0, /*lba*/0, /*sector_count*/sizeof(*pwd) / 512, - /*data_ptr*/(u_int8_t *)pwd, + /*data_ptr*/(uint8_t *)pwd, /*dxfer_len*/sizeof(*pwd), /*timeout*/timeout, /*force48bit*/0); @@ -2524,7 +2630,7 @@ atasecurity_unlock(struct cam_device *device, union ccb *ccb, static int atasecurity_disable(struct cam_device *device, union ccb *ccb, - int retry_count, u_int32_t timeout, + int retry_count, uint32_t timeout, struct ata_security_password *pwd, int quiet) { @@ -2542,7 +2648,7 @@ atasecurity_disable(struct cam_device *device, union ccb *ccb, /*features*/0, /*lba*/0, /*sector_count*/sizeof(*pwd) / 512, - /*data_ptr*/(u_int8_t *)pwd, + /*data_ptr*/(uint8_t *)pwd, /*dxfer_len*/sizeof(*pwd), /*timeout*/timeout, /*force48bit*/0); @@ -2582,8 +2688,8 @@ atasecurity_erase_confirm(struct cam_device *device, static int atasecurity_erase(struct cam_device *device, union ccb *ccb, - int retry_count, u_int32_t timeout, - u_int32_t erase_timeout, + int retry_count, uint32_t timeout, + uint32_t erase_timeout, struct ata_security_password *pwd, int quiet) { int error; @@ -2625,7 +2731,7 @@ atasecurity_erase(struct cam_device *device, union ccb *ccb, /*features*/0, /*lba*/0, /*sector_count*/sizeof(*pwd) / 512, - /*data_ptr*/(u_int8_t *)pwd, + /*data_ptr*/(uint8_t *)pwd, /*dxfer_len*/sizeof(*pwd), /*timeout*/erase_timeout, /*force48bit*/0); @@ -2638,7 +2744,7 @@ atasecurity_erase(struct cam_device *device, union ccb *ccb, static int atasecurity_set_password(struct cam_device *device, union ccb *ccb, - int retry_count, u_int32_t timeout, + int retry_count, uint32_t timeout, struct ata_security_password *pwd, int quiet) { @@ -2657,7 +2763,7 @@ atasecurity_set_password(struct cam_device *device, union ccb *ccb, /*features*/0, /*lba*/0, /*sector_count*/sizeof(*pwd) / 512, - /*data_ptr*/(u_int8_t *)pwd, + /*data_ptr*/(uint8_t *)pwd, /*dxfer_len*/sizeof(*pwd), /*timeout*/timeout, /*force48bit*/0); @@ -2706,7 +2812,7 @@ atasecurity_print(struct ata_params *parm) * the data will still be copied but no null termination will occur. */ static int -ata_getpwd(u_int8_t *passwd, int max, char opt) +ata_getpwd(uint8_t *passwd, int max, char opt) { int len; @@ -3823,23 +3929,20 @@ readdefects(struct cam_device *device, int argc, char **argv, struct scsi_read_defect_data_hdr_10 *hdr10 = NULL; struct scsi_read_defect_data_hdr_12 *hdr12 = NULL; size_t hdr_size = 0, entry_size = 0; - int use_12byte = 0; - int hex_format = 0; - u_int8_t *defect_list = NULL; - u_int8_t list_format = 0; - int list_type_set = 0; - u_int32_t dlist_length = 0; - u_int32_t returned_length = 0, valid_len = 0; - u_int32_t num_returned = 0, num_valid = 0; - u_int32_t max_possible_size = 0, hdr_max = 0; - u_int32_t starting_offset = 0; - u_int8_t returned_format, returned_type; + uint8_t *defect_list = NULL; + uint8_t list_format = 0; + uint32_t dlist_length = 0; + uint32_t returned_length = 0, valid_len = 0; + uint32_t num_returned = 0, num_valid = 0; + uint32_t max_possible_size = 0, hdr_max = 0; + uint32_t starting_offset = 0; + uint8_t returned_format, returned_type; unsigned int i; - int summary = 0, quiet = 0; int c, error = 0; - int lists_specified = 0; - int get_length = 1, first_pass = 1; int mads = 0; + bool summary = false, quiet = false, list_type_set = false; + bool get_length = true, use_12byte = false, first_pass = true; + bool hex_format = false; while ((c = getopt(argc, argv, combinedopt)) != -1) { switch(c){ @@ -3848,15 +3951,21 @@ readdefects(struct cam_device *device, int argc, char **argv, scsi_nv_status status; int entry_num = 0; + if (list_type_set) { + warnx("%s: -f specified twice", __func__); + error = 1; + goto defect_bailout; + } + status = scsi_get_nv(defect_list_type_map, sizeof(defect_list_type_map) / sizeof(defect_list_type_map[0]), optarg, &entry_num, SCSI_NV_FLAG_IG_CASE); if (status == SCSI_NV_FOUND) { - list_format = defect_list_type_map[ + list_format |= defect_list_type_map[ entry_num].value; - list_type_set = 1; + list_type_set = true; } else { warnx("%s: %s %s option %s", __func__, (status == SCSI_NV_AMBIGUOUS) ? @@ -3868,16 +3977,16 @@ readdefects(struct cam_device *device, int argc, char **argv, break; } case 'G': - arglist |= CAM_ARG_GLIST; + list_format |= SRDD10_GLIST; break; case 'P': - arglist |= CAM_ARG_PLIST; + list_format |= SRDD10_PLIST; break; case 'q': - quiet = 1; + quiet = true; break; case 's': - summary = 1; + summary = true; break; case 'S': { char *endptr; @@ -3888,52 +3997,48 @@ readdefects(struct cam_device *device, int argc, char **argv, warnx("invalid starting offset %s", optarg); goto defect_bailout; } + use_12byte = true; break; } case 'X': - hex_format = 1; + hex_format = true; break; default: break; } } - if (list_type_set == 0) { + if (!list_type_set) { error = 1; warnx("no defect list format specified"); goto defect_bailout; } - if (arglist & CAM_ARG_PLIST) { - list_format |= SRDD10_PLIST; - lists_specified++; - } - - if (arglist & CAM_ARG_GLIST) { - list_format |= SRDD10_GLIST; - lists_specified++; - } - /* * This implies a summary, and was the previous behavior. */ - if (lists_specified == 0) - summary = 1; + if ((list_format & ~SRDD10_DLIST_FORMAT_MASK) == 0) + summary = true; ccb = cam_getccb(device); -retry_12byte: - /* - * We start off asking for just the header to determine how much - * defect data is available. Some Hitachi drives return an error - * if you ask for more data than the drive has. Once we know the - * length, we retry the command with the returned length. + * We start off asking for just the header to determine how much defect + * data is available. Some Hitachi drives return an error if you ask + * for more data than the drive has. Once we know the length, we retry + * the command with the returned length. When we're retrying the with + * 12-byte command, we're always changing to the 12-byte command and + * need to get the length. Simplify the logic below by always setting + * use_12byte in this case with this slightly more complex logic here. */ - if (use_12byte == 0) + if (!use_12byte) { dlist_length = sizeof(*hdr10); - else + } else { +retry_12byte: + get_length = true; + use_12byte = true; dlist_length = sizeof(*hdr12); + } retry: if (defect_list != NULL) { @@ -3979,7 +4084,7 @@ next_batch: valid_len = ccb->csio.dxfer_len - ccb->csio.resid; - if (use_12byte == 0) { + if (!use_12byte) { hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list; hdr_size = sizeof(*hdr10); hdr_max = SRDDH10_MAX_LENGTH; @@ -4033,8 +4138,8 @@ next_batch: num_valid = min(returned_length, valid_len - hdr_size); num_valid /= entry_size; - if (get_length != 0) { - get_length = 0; + if (get_length) { + get_length = false; if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) { @@ -4055,10 +4160,8 @@ next_batch: if ((sense_key == SSD_KEY_RECOVERED_ERROR) && (asc == 0x1c) && (ascq == 0x00) && (returned_length > 0)) { - if ((use_12byte == 0) + if (!use_12byte && (returned_length >= max_possible_size)) { - get_length = 1; - use_12byte = 1; goto retry_12byte; } dlist_length = returned_length + hdr_size; @@ -4073,9 +4176,7 @@ next_batch: * command can support. Retry with the 12 * byte command. */ - if (use_12byte == 0) { - get_length = 1; - use_12byte = 1; + if (!use_12byte) { goto retry_12byte; } dlist_length = returned_length + hdr_size; @@ -4089,9 +4190,7 @@ next_batch: * error and no data. Retry with the 12 * byte command. */ - if (use_12byte == 0) { - get_length = 1; - use_12byte = 1; + if (!use_12byte) { goto retry_12byte; } dlist_length = returned_length + hdr_size; @@ -4104,11 +4203,9 @@ next_batch: if (returned_length == 0) dlist_length = SRDD10_MAX_LENGTH; else { - if ((use_12byte == 0) + if (!use_12byte && (returned_length >= max_possible_size)) { - get_length = 1; - use_12byte = 1; goto retry_12byte; } dlist_length = returned_length + @@ -4124,17 +4221,15 @@ next_batch: CAM_EPF_ALL, stderr); goto defect_bailout; } else { - if ((use_12byte == 0) + if (!use_12byte && (returned_length >= max_possible_size)) { - get_length = 1; - use_12byte = 1; goto retry_12byte; } dlist_length = returned_length + hdr_size; } - if (summary != 0) { + if (summary) { fprintf(stdout, "%u", num_returned); - if (quiet == 0) { + if (!quiet) { fprintf(stdout, " defect%s", (num_returned != 1) ? "s" : ""); } @@ -4218,10 +4313,10 @@ next_batch: goto defect_bailout; } - if (first_pass != 0) { + if (first_pass) { fprintf(stderr, "Got %d defect", num_returned); - if ((lists_specified == 0) || (num_returned == 0)) { + if (!summary || (num_returned == 0)) { fprintf(stderr, "s.\n"); goto defect_bailout; } else if (num_returned == 1) @@ -4229,7 +4324,7 @@ next_batch: else fprintf(stderr, "s:\n"); - first_pass = 0; + first_pass = false; } /* @@ -4254,7 +4349,7 @@ next_batch: 0 : 1; sector &= ~SDD_EXT_PHYS_FLAG_MASK; } - if (hex_format == 0) + if (!hex_format) fprintf(stdout, "%d:%d:%d%s", scsi_3btoul(dlist[i].cylinder), dlist[i].head, @@ -4290,7 +4385,7 @@ next_batch: mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0; bfi &= ~SDD_EXT_BFI_FLAG_MASK; } - if (hex_format == 0) + if (!hex_format) fprintf(stdout, "%d:%d:%d%s", scsi_3btoul(dlist[i].cylinder), dlist[i].head, @@ -4319,7 +4414,7 @@ next_batch: (defect_list + hdr_size); for (i = 0; i < num_valid; i++) { - if (hex_format == 0) + if (!hex_format) fprintf(stdout, "%u\n", scsi_4btoul(dlist[i].address)); else @@ -4342,7 +4437,7 @@ next_batch: (defect_list + hdr_size); for (i = 0; i < num_valid; i++) { - if (hex_format == 0) + if (!hex_format) fprintf(stdout, "%ju\n", (uintmax_t)scsi_8btou64( dlist[i].address)); @@ -4377,7 +4472,7 @@ defect_bailout: #if 0 void -reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks) +reassignblocks(struct cam_device *device, uint32_t *blocks, int num_blocks) { union ccb *ccb; @@ -4390,7 +4485,7 @@ reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks) void mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa, int pc, int page, int subpage, int task_attr, int retry_count, int timeout, - u_int8_t *data, int datalen) + uint8_t *data, int datalen) { union ccb *ccb; int error_code, sense_key, asc, ascq; @@ -4402,7 +4497,7 @@ mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa, int pc, retry: /* * MODE SENSE(6) can't handle more then 255 bytes. If there are more, - * device must return error, so we should not get trucated data. + * device must return error, so we should not get truncated data. */ if (*cdb_len == 6 && datalen > 255) datalen = 255; @@ -4464,7 +4559,7 @@ retry: void mode_select(struct cam_device *device, int cdb_len, int save_pages, - int task_attr, int retry_count, int timeout, u_int8_t *data, int datalen) + int task_attr, int retry_count, int timeout, uint8_t *data, int datalen) { union ccb *ccb; int retval; @@ -4589,10 +4684,10 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, int task_attr, int retry_count, int timeout) { union ccb *ccb; - u_int32_t flags = CAM_DIR_NONE; - u_int8_t *data_ptr = NULL; - u_int8_t cdb[20]; - u_int8_t atacmd[12]; + uint32_t flags = CAM_DIR_NONE; + uint8_t *data_ptr = NULL; + uint8_t cdb[20]; + uint8_t atacmd[12]; struct get_hook hook; int c, data_bytes = 0, valid_bytes; int cdb_len = 0; @@ -4693,7 +4788,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, && (datastr[0] == '-')) fd_data = 1; - data_ptr = (u_int8_t *)malloc(data_bytes); + data_ptr = (uint8_t *)malloc(data_bytes); if (data_ptr == NULL) { warnx("can't malloc memory for data_ptr"); error = 1; @@ -4720,7 +4815,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, hook.argv = argv + optind; hook.got = 0; datastr = cget(&hook, NULL); - data_ptr = (u_int8_t *)malloc(data_bytes); + data_ptr = (uint8_t *)malloc(data_bytes); if (data_ptr == NULL) { warnx("can't malloc memory for data_ptr"); error = 1; @@ -4761,7 +4856,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) { ssize_t amt_read; int amt_to_read = data_bytes; - u_int8_t *buf_ptr = data_ptr; + uint8_t *buf_ptr = data_ptr; for (amt_read = 0; amt_to_read > 0; amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) { @@ -4910,7 +5005,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, } else { ssize_t amt_written; int amt_to_write = valid_bytes; - u_int8_t *buf_ptr = data_ptr; + uint8_t *buf_ptr = data_ptr; for (amt_written = 0; (amt_to_write > 0) && (amt_written =write(1, buf_ptr,amt_to_write))> 0;){ @@ -5285,6 +5380,39 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts) sata->caps); } } + if (cts->transport == XPORT_NVME) { + struct ccb_trans_settings_nvme *nvme = + &cts->xport_specific.nvme; + + if (nvme->valid & CTS_NVME_VALID_LINK) { + fprintf(stdout, "%sPCIe lanes: %d (%d max)\n", pathstr, + nvme->lanes, nvme->max_lanes); + fprintf(stdout, "%sPCIe Generation: %d (%d max)\n", pathstr, + nvme->speed, nvme->max_speed); + } + } + if (cts->transport == XPORT_NVMF) { + struct ccb_trans_settings_nvmf *nvmf = + &cts->xport_specific.nvmf; + + if (nvmf->valid & CTS_NVMF_VALID_TRTYPE) { + fprintf(stdout, "%sTransport: %s\n", pathstr, + nvmf_transport_type(nvmf->trtype)); + } + } + if (cts->transport == XPORT_UFSHCI) { + struct ccb_trans_settings_ufshci *ufshci = + &cts->xport_specific.ufshci; + + if (ufshci->valid & CTS_UFSHCI_VALID_LINK) { + fprintf(stdout, "%sHigh Speed Gear: %d (%d max)\n", + pathstr, ufshci->hs_gear, ufshci->max_hs_gear); + fprintf(stdout, "%sUnipro TX lanes: %d (%d max)\n", pathstr, + ufshci->tx_lanes, ufshci->max_tx_lanes); + fprintf(stdout, "%sUnipro RX lanes: %d (%d max)\n", pathstr, + ufshci->rx_lanes, ufshci->max_rx_lanes); + } + } if (cts->protocol == PROTO_ATA) { struct ccb_trans_settings_ata *ata= &cts->proto_specific.ata; @@ -5305,24 +5433,16 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts) "enabled" : "disabled"); } } -#ifdef WITH_NVME if (cts->protocol == PROTO_NVME) { - struct ccb_trans_settings_nvme *nvmex = - &cts->xport_specific.nvme; + struct ccb_trans_settings_nvme *nvme = + &cts->proto_specific.nvme; - if (nvmex->valid & CTS_NVME_VALID_SPEC) { + if (nvme->valid & CTS_NVME_VALID_SPEC) { fprintf(stdout, "%sNVMe Spec: %d.%d\n", pathstr, - NVME_MAJOR(nvmex->spec), - NVME_MINOR(nvmex->spec)); - } - if (nvmex->valid & CTS_NVME_VALID_LINK) { - fprintf(stdout, "%sPCIe lanes: %d (%d max)\n", pathstr, - nvmex->lanes, nvmex->max_lanes); - fprintf(stdout, "%sPCIe Generation: %d (%d max)\n", pathstr, - nvmex->speed, nvmex->max_speed); + NVME_MAJOR(nvme->spec), + NVME_MINOR(nvme->spec)); } } -#endif } /* @@ -5419,7 +5539,7 @@ dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count, /*retries*/ retry_count, /*cbfcnp*/ NULL, /* tag_action */ MSG_SIMPLE_Q_TAG, - /* inq_buf */ (u_int8_t *)&sup_pages, + /* inq_buf */ (uint8_t *)&sup_pages, /* inq_len */ sizeof(sup_pages), /* evpd */ 1, /* page_code */ SVPD_SUPPORTED_PAGE_LIST, @@ -6324,9 +6444,9 @@ scsiformat(struct cam_device *device, int argc, char **argv, int use_timeout = 10800 * 1000; int immediate = 1; struct format_defect_list_header fh; - u_int8_t *data_ptr = NULL; - u_int32_t dxfer_len = 0; - u_int8_t byte2 = 0; + uint8_t *data_ptr = NULL; + uint32_t dxfer_len = 0; + uint8_t byte2 = 0; int num_warnings = 0; int reportonly = 0; @@ -6423,7 +6543,7 @@ scsiformat(struct cam_device *device, int argc, char **argv, */ if (immediate != 0) { fh.byte2 = FU_DLH_IMMED; - data_ptr = (u_int8_t *)&fh; + data_ptr = (uint8_t *)&fh; dxfer_len = sizeof(fh); byte2 = FU_FMT_DATA; } else if (quiet == 0) { @@ -6795,7 +6915,7 @@ sanitize(struct cam_device *device, int argc, char **argv, char *combinedopt, int task_attr, int retry_count, int timeout) { union ccb *ccb; - u_int8_t action = 0; + uint8_t action = 0; int c; int ycount = 0, quiet = 0; int error = 0; @@ -6806,8 +6926,8 @@ sanitize(struct cam_device *device, int argc, char **argv, int ause = 0; int fd = -1; const char *pattern = NULL; - u_int8_t *data_ptr = NULL; - u_int32_t dxfer_len = 0; + uint8_t *data_ptr = NULL; + uint32_t dxfer_len = 0; uint8_t byte2; uint16_t feature, count; uint64_t lba; @@ -7651,7 +7771,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt, && (datastr[0] == '-')) fd_response = 1; - smp_response = (u_int8_t *)malloc(response_size); + smp_response = (uint8_t *)malloc(response_size); if (smp_response == NULL) { warn("can't malloc memory for SMP response"); error = 1; @@ -7671,7 +7791,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt, hook.argv = argv + optind; hook.got = 0; datastr = cget(&hook, NULL); - smp_request = (u_int8_t *)malloc(request_size); + smp_request = (uint8_t *)malloc(request_size); if (smp_request == NULL) { warn("can't malloc memory for SMP request"); error = 1; @@ -7703,7 +7823,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt, if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) { ssize_t amt_read; int amt_to_read = request_size; - u_int8_t *buf_ptr = smp_request; + uint8_t *buf_ptr = smp_request; for (amt_read = 0; amt_to_read > 0; amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) { @@ -7763,7 +7883,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt, } else { ssize_t amt_written; int amt_to_write = response_size; - u_int8_t *buf_ptr = smp_response; + uint8_t *buf_ptr = smp_response; for (amt_written = 0; (amt_to_write > 0) && (amt_written = write(STDOUT_FILENO, buf_ptr, @@ -9246,7 +9366,7 @@ atapm(struct cam_device *device, int argc, char **argv, int retval = 0; int t = -1; int c; - u_int8_t ata_flags = 0; + uint8_t ata_flags = 0; u_char cmd, sc; ccb = cam_getccb(device); @@ -9312,12 +9432,11 @@ atapm(struct cam_device *device, int argc, char **argv, /*timeout*/timeout ? timeout : 30 * 1000, /*force48bit*/0); - cam_freeccb(ccb); - - if (retval || cmd != ATA_CHECK_POWER_MODE) - return (retval); + if (retval == 0 && cmd == ATA_CHECK_POWER_MODE) + retval = atapm_proc_resp(device, ccb); - return (atapm_proc_resp(device, ccb)); + cam_freeccb(ccb); + return (retval); } static int @@ -9878,6 +9997,7 @@ usage(int printlong) " 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" @@ -9966,6 +10086,7 @@ usage(int printlong) "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" @@ -10030,6 +10151,9 @@ usage(int printlong) "-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" @@ -10500,6 +10624,10 @@ main(int argc, char **argv) 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); |