150477Speter/* 228415Speter * Copyright (c) 1997-2007 Kenneth D. Merry 328415Speter * All rights reserved. 434768Speter * 528415Speter * Redistribution and use in source and binary forms, with or without 628415Speter * modification, are permitted provided that the following conditions 728415Speter * are met: 828415Speter * 1. Redistributions of source code must retain the above copyright 928415Speter * notice, this list of conditions and the following disclaimer. 1028415Speter * 2. Redistributions in binary form must reproduce the above copyright 1134768Speter * notice, this list of conditions and the following disclaimer in the 1228415Speter * documentation and/or other materials provided with the distribution. 1328415Speter * 3. The name of the author may not be used to endorse or promote products 1428415Speter * derived from this software without specific prior written permission. 1528415Speter * 1628415Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1734768Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1834768Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19139823Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20139823Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2134768Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2228415Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2334768Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2428415Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2528415Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2628415Speter * SUCH DAMAGE. 2728415Speter */ 2828415Speter 2928415Speter#include <sys/cdefs.h> 3028415Speter__FBSDID("$FreeBSD: stable/10/sbin/camcontrol/camcontrol.c 320781 2017-07-07 15:22:29Z asomers $"); 3128415Speter 3228415Speter#include <sys/ioctl.h> 3328415Speter#include <sys/stdint.h> 3428415Speter#include <sys/types.h> 3528415Speter#include <sys/stat.h> 3628415Speter#include <sys/endian.h> 3728415Speter#include <sys/sbuf.h> 3828415Speter 3928415Speter#include <stdio.h> 4028415Speter#include <stdlib.h> 4128415Speter#include <string.h> 4228415Speter#include <unistd.h> 43139823Simp#include <inttypes.h> 44139823Simp#include <limits.h> 4534768Speter#include <fcntl.h> 4634768Speter#include <ctype.h> 4734768Speter#include <err.h> 4834768Speter#include <libutil.h> 4934768Speter#ifndef MINIMALISTIC 5028415Speter#include <limits.h> 5128415Speter#include <inttypes.h> 5228415Speter#endif 5334768Speter 5434768Speter#include <cam/cam.h> 5534768Speter#include <cam/cam_debug.h> 5628415Speter#include <cam/cam_ccb.h> 5734768Speter#include <cam/scsi/scsi_all.h> 5834768Speter#include <cam/scsi/scsi_da.h> 5928415Speter#include <cam/scsi/scsi_pass.h> 6034768Speter#include <cam/scsi/scsi_message.h> 6128415Speter#include <cam/scsi/smp_all.h> 6228415Speter#include <cam/ata/ata_all.h> 6328415Speter#include <camlib.h> 6434768Speter#include "camcontrol.h" 6528415Speter 6634768Spetertypedef enum { 6734768Speter CAM_CMD_NONE = 0x00000000, 6834768Speter CAM_CMD_DEVLIST = 0x00000001, 6928415Speter CAM_CMD_TUR = 0x00000002, 7034768Speter CAM_CMD_INQUIRY = 0x00000003, 7134768Speter CAM_CMD_STARTSTOP = 0x00000004, 7228415Speter CAM_CMD_RESCAN = 0x00000005, 7334768Speter CAM_CMD_READ_DEFECTS = 0x00000006, 7434768Speter CAM_CMD_MODE_PAGE = 0x00000007, 7534768Speter CAM_CMD_SCSI_CMD = 0x00000008, 7634768Speter CAM_CMD_DEVTREE = 0x00000009, 7734768Speter CAM_CMD_USAGE = 0x0000000a, 7834768Speter CAM_CMD_DEBUG = 0x0000000b, 7934768Speter CAM_CMD_RESET = 0x0000000c, 8034768Speter CAM_CMD_FORMAT = 0x0000000d, 8134768Speter CAM_CMD_TAG = 0x0000000e, 8234768Speter CAM_CMD_RATE = 0x0000000f, 8334768Speter CAM_CMD_DETACH = 0x00000010, 8434768Speter CAM_CMD_REPORTLUNS = 0x00000011, 8534768Speter CAM_CMD_READCAP = 0x00000012, 8634768Speter CAM_CMD_IDENTIFY = 0x00000013, 8734768Speter CAM_CMD_IDLE = 0x00000014, 8834768Speter CAM_CMD_STANDBY = 0x00000015, 8934768Speter CAM_CMD_SLEEP = 0x00000016, 9034768Speter CAM_CMD_SMP_CMD = 0x00000017, 9134768Speter CAM_CMD_SMP_RG = 0x00000018, 9297512Sphk CAM_CMD_SMP_PC = 0x00000019, 9334768Speter CAM_CMD_SMP_PHYLIST = 0x0000001a, 9434768Speter CAM_CMD_SMP_MANINFO = 0x0000001b, 9597512Sphk CAM_CMD_DOWNLOAD_FW = 0x0000001c, 9628415Speter CAM_CMD_SECURITY = 0x0000001d, 9734768Speter CAM_CMD_HPA = 0x0000001e, 9834768Speter CAM_CMD_SANITIZE = 0x0000001f, 9934768Speter CAM_CMD_PERSIST = 0x00000020, 10034768Speter CAM_CMD_APM = 0x00000021, 10134768Speter CAM_CMD_AAM = 0x00000022, 10234768Speter CAM_CMD_ATTRIB = 0x00000023, 10334768Speter CAM_CMD_OPCODES = 0x00000024, 10434768Speter CAM_CMD_REPROBE = 0x00000025 10534768Speter} cam_cmdmask; 10634768Speter 10734768Spetertypedef enum { 10834768Speter CAM_ARG_NONE = 0x00000000, 10934768Speter CAM_ARG_VERBOSE = 0x00000001, 11034768Speter CAM_ARG_DEVICE = 0x00000002, 11134768Speter CAM_ARG_BUS = 0x00000004, 112231678Stijl CAM_ARG_TARGET = 0x00000008, 11334768Speter CAM_ARG_LUN = 0x00000010, 11434768Speter CAM_ARG_EJECT = 0x00000020, 11534768Speter CAM_ARG_UNIT = 0x00000040, 11634768Speter CAM_ARG_FORMAT_BLOCK = 0x00000080, 11734768Speter CAM_ARG_FORMAT_BFI = 0x00000100, 11834768Speter CAM_ARG_FORMAT_PHYS = 0x00000200, 11934768Speter CAM_ARG_PLIST = 0x00000400, 12034768Speter CAM_ARG_GLIST = 0x00000800, 12128415Speter CAM_ARG_GET_SERIAL = 0x00001000, 12228415Speter CAM_ARG_GET_STDINQ = 0x00002000, 12328415Speter CAM_ARG_GET_XFERRATE = 0x00004000, 12428415Speter CAM_ARG_INQ_MASK = 0x00007000, 12534768Speter CAM_ARG_TIMEOUT = 0x00020000, 12634768Speter CAM_ARG_CMD_IN = 0x00040000, 12734768Speter CAM_ARG_CMD_OUT = 0x00080000, 12834768Speter CAM_ARG_ERR_RECOVER = 0x00200000, 12934768Speter CAM_ARG_RETRIES = 0x00400000, 13034768Speter CAM_ARG_START_UNIT = 0x00800000, 13128415Speter CAM_ARG_DEBUG_INFO = 0x01000000, 13234768Speter CAM_ARG_DEBUG_TRACE = 0x02000000, 13334768Speter CAM_ARG_DEBUG_SUBTRACE = 0x04000000, 13434768Speter CAM_ARG_DEBUG_CDB = 0x08000000, 13534768Speter CAM_ARG_DEBUG_XPT = 0x10000000, 13634768Speter CAM_ARG_DEBUG_PERIPH = 0x20000000, 13734768Speter CAM_ARG_DEBUG_PROBE = 0x40000000, 13834768Speter} cam_argmask; 13928415Speter 14034768Speterstruct camcontrol_opts { 14134768Speter const char *optname; 14228415Speter uint32_t cmdnum; 14328415Speter cam_argmask argnum; 14428415Speter const char *subopt; 14534768Speter}; 14634768Speter 14734768Speter#ifndef MINIMALISTIC 14828415Speterstruct ata_res_pass16 { 14928415Speter u_int16_t reserved[5]; 15028415Speter u_int8_t flags; 15128415Speter u_int8_t error; 15228415Speter u_int8_t sector_count_exp; 15328415Speter u_int8_t sector_count; 15428415Speter u_int8_t lba_low_exp; 15528415Speter u_int8_t lba_low; 15628415Speter u_int8_t lba_mid_exp; 15728415Speter u_int8_t lba_mid; 15828415Speter u_int8_t lba_high_exp; 15928415Speter u_int8_t lba_high; 16028415Speter u_int8_t device; 16128415Speter u_int8_t status; 16228415Speter}; 16328415Speter 16428415Speterstruct ata_set_max_pwd 16528415Speter{ 16628415Speter u_int16_t reserved1; 16728415Speter u_int8_t password[32]; 16828415Speter u_int16_t reserved2[239]; 16928415Speter}; 17028415Speter 17128415Speterstatic struct scsi_nv task_attrs[] = { 17228415Speter { "simple", MSG_SIMPLE_Q_TAG }, 17328415Speter { "head", MSG_HEAD_OF_Q_TAG }, 17428415Speter { "ordered", MSG_ORDERED_Q_TAG }, 17528415Speter { "iwr", MSG_IGN_WIDE_RESIDUE }, 17628415Speter { "aca", MSG_ACA_TASK } 17728415Speter}; 17828415Speter 17928415Speterstatic const char scsicmd_opts[] = "a:c:dfi:o:r"; 18028415Speterstatic const char readdefect_opts[] = "f:GPqsS:X"; 18128415Speterstatic const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; 18228415Speterstatic const char smprg_opts[] = "l"; 18328415Speterstatic const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:"; 18428415Speterstatic const char smpphylist_opts[] = "lq"; 18528415Speterstatic char pwd_opt; 18628415Speter#endif 18734768Speter 18834768Speterstatic struct camcontrol_opts option_table[] = { 18934768Speter#ifndef MINIMALISTIC 19034768Speter {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL}, 19134768Speter {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"}, 19234768Speter {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL}, 19334768Speter {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL}, 19434768Speter {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL}, 19534768Speter {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL}, 19634768Speter {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL}, 19734768Speter {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"}, 19834768Speter {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"}, 19934768Speter {"reprobe", CAM_CMD_REPROBE, CAM_ARG_NONE, NULL}, 20034768Speter#endif /* MINIMALISTIC */ 20134768Speter {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL}, 20234768Speter {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL}, 20334768Speter#ifndef MINIMALISTIC 20434768Speter {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts}, 20534768Speter {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts}, 20634768Speter {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"}, 20734768Speter {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts}, 20834768Speter {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts}, 20934768Speter {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts}, 21034768Speter {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts}, 21134768Speter {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts}, 21228415Speter {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts}, 21328415Speter {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"}, 21428415Speter {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts}, 21528415Speter {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts}, 21634768Speter#endif /* MINIMALISTIC */ 21734768Speter {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"}, 21834768Speter#ifndef MINIMALISTIC 21934768Speter {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL}, 22034768Speter {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"}, 22134768Speter {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"}, 22234768Speter {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts}, 22334768Speter {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts}, 22434768Speter {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"}, 22528415Speter {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"}, 22628415Speter {"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"}, 22728415Speter {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"}, 22828415Speter {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"}, 22928415Speter {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""}, 23028415Speter {"apm", CAM_CMD_APM, CAM_ARG_NONE, "l:"}, 23128415Speter {"aam", CAM_CMD_AAM, CAM_ARG_NONE, "l:"}, 23228415Speter {"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:qsy"}, 23328415Speter {"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"}, 23428415Speter {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"}, 23528415Speter {"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"}, 23634768Speter {"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"}, 23734768Speter {"opcodes", CAM_CMD_OPCODES, CAM_ARG_NONE, "No:s:T"}, 23834768Speter#endif /* MINIMALISTIC */ 23934768Speter {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, 24034768Speter {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, 24134768Speter {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, 24234768Speter {NULL, 0, 0, NULL} 24328415Speter}; 24434768Speter 24534768Speterstruct cam_devitem { 24634768Speter struct device_match_result dev_match; 24734768Speter int num_periphs; 24834768Speter struct periph_match_result *periph_matches; 24928415Speter struct scsi_vpd_device_id *device_id; 25028415Speter int device_id_len; 25128415Speter STAILQ_ENTRY(cam_devitem) links; 25228415Speter}; 25328415Speter 25428415Speterstruct cam_devlist { 25528415Speter STAILQ_HEAD(, cam_devitem) dev_queue; 25628415Speter path_id_t path_id; 25728415Speter}; 25828415Speter 25928415Speterstatic cam_cmdmask cmdlist; 26028415Speterstatic cam_argmask arglist; 26128415Speter 26228415Spetercamcontrol_optret getoption(struct camcontrol_opts *table, char *arg, 26328415Speter uint32_t *cmdnum, cam_argmask *argnum, 26428415Speter const char **subopt); 26528415Speter#ifndef MINIMALISTIC 26634768Speterstatic int getdevlist(struct cam_device *device); 26734768Speter#endif /* MINIMALISTIC */ 26834768Speterstatic int getdevtree(int argc, char **argv, char *combinedopt); 26934768Speter#ifndef MINIMALISTIC 27034768Speterstatic int testunitready(struct cam_device *device, int task_attr, 27128415Speter int retry_count, int timeout, int quiet); 27228415Speterstatic int scsistart(struct cam_device *device, int startstop, int loadeject, 27328415Speter int task_attr, int retry_count, int timeout); 27434768Speterstatic int scsiinquiry(struct cam_device *device, int task_attr, 27528415Speter int retry_count, int timeout); 27628415Speterstatic int scsiserial(struct cam_device *device, int task_attr, 27728415Speter int retry_count, int timeout); 27828415Speter#endif /* MINIMALISTIC */ 27928415Speterstatic int parse_btl(char *tstr, path_id_t *bus, target_id_t *target, 28028415Speter lun_id_t *lun, cam_argmask *arglst); 28128415Speterstatic int dorescan_or_reset(int argc, char **argv, int rescan); 28228415Speterstatic int rescan_or_reset_bus(path_id_t bus, int rescan); 28328415Speterstatic int scanlun_or_reset_dev(path_id_t bus, target_id_t target, 28428415Speter lun_id_t lun, int scan); 28528415Speter#ifndef MINIMALISTIC 28628415Speterstatic int readdefects(struct cam_device *device, int argc, char **argv, 28743305Sdillon char *combinedopt, int task_attr, int retry_count, 28828415Speter int timeout); 28928415Speterstatic void modepage(struct cam_device *device, int argc, char **argv, 29028415Speter char *combinedopt, int task_attr, int retry_count, 29128415Speter int timeout); 29234768Speterstatic int scsicmd(struct cam_device *device, int argc, char **argv, 29328415Speter char *combinedopt, int task_attr, int retry_count, 29434768Speter int timeout); 29534768Speterstatic int smpcmd(struct cam_device *device, int argc, char **argv, 29634768Speter char *combinedopt, int retry_count, int timeout); 29728415Speterstatic int smpreportgeneral(struct cam_device *device, int argc, char **argv, 29828415Speter char *combinedopt, int retry_count, int timeout); 29934768Speterstatic int smpphycontrol(struct cam_device *device, int argc, char **argv, 30034768Speter char *combinedopt, int retry_count, int timeout); 30128415Speterstatic int smpmaninfo(struct cam_device *device, int argc, char **argv, 30228415Speter char *combinedopt, int retry_count, int timeout); 30328415Speterstatic int getdevid(struct cam_devitem *item); 30428415Speterstatic int buildbusdevlist(struct cam_devlist *devlist); 30528415Speterstatic void freebusdevlist(struct cam_devlist *devlist); 30628415Speterstatic struct cam_devitem *findsasdevice(struct cam_devlist *devlist, 30728415Speter uint64_t sasaddr); 30828415Speterstatic int smpphylist(struct cam_device *device, int argc, char **argv, 30928415Speter char *combinedopt, int retry_count, int timeout); 31028415Speterstatic int tagcontrol(struct cam_device *device, int argc, char **argv, 31128415Speter char *combinedopt); 31228415Speterstatic void cts_print(struct cam_device *device, 31328415Speter struct ccb_trans_settings *cts); 31428415Speterstatic void cpi_print(struct ccb_pathinq *cpi); 31528415Speterstatic int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi); 31628415Speterstatic int get_cgd(struct cam_device *device, struct ccb_getdev *cgd); 31728415Speterstatic int get_print_cts(struct cam_device *device, int user_settings, 31828415Speter int quiet, struct ccb_trans_settings *cts); 31928415Speterstatic int ratecontrol(struct cam_device *device, int task_attr, 32028415Speter int retry_count, int timeout, int argc, char **argv, 32128415Speter char *combinedopt); 32228415Speterstatic int scsiformat(struct cam_device *device, int argc, char **argv, 32328415Speter char *combinedopt, int task_attr, int retry_count, 32428415Speter int timeout); 32528415Speterstatic int scsisanitize(struct cam_device *device, int argc, char **argv, 32628415Speter char *combinedopt, int task_attr, int retry_count, 32728415Speter int timeout); 32828415Speterstatic int scsireportluns(struct cam_device *device, int argc, char **argv, 32928415Speter char *combinedopt, int task_attr, int retry_count, 33028415Speter int timeout); 33128415Speterstatic int scsireadcapacity(struct cam_device *device, int argc, char **argv, 33228415Speter char *combinedopt, int task_attr, int retry_count, 33328415Speter int timeout); 33434768Speterstatic int atapm(struct cam_device *device, int argc, char **argv, 33534768Speter char *combinedopt, int retry_count, int timeout); 33634768Speterstatic int atasecurity(struct cam_device *device, int retry_count, int timeout, 33734768Speter int argc, char **argv, char *combinedopt); 33834768Speterstatic int atahpa(struct cam_device *device, int retry_count, int timeout, 33928415Speter int argc, char **argv, char *combinedopt); 34028415Speterstatic int scsiprintoneopcode(struct cam_device *device, int req_opcode, 34128415Speter int sa_set, int req_sa, uint8_t *buf, 34234768Speter uint32_t valid_len); 34328415Speterstatic int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf, 34428415Speter uint32_t valid_len); 34528415Speterstatic int scsiopcodes(struct cam_device *device, int argc, char **argv, 34628415Speter char *combinedopt, int task_attr, int retry_count, 34728415Speter int timeout, int verbose); 34834768Speterstatic int scsireprobe(struct cam_device *device); 34934768Speter 35034768Speter#endif /* MINIMALISTIC */ 35134768Speter#ifndef min 35228415Speter#define min(a,b) (((a)<(b))?(a):(b)) 35334768Speter#endif 35428415Speter#ifndef max 35528415Speter#define max(a,b) (((a)>(b))?(a):(b)) 35628415Speter#endif 35728415Speter 35828415Spetercamcontrol_optret 35928415Spetergetoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum, 36028415Speter cam_argmask *argnum, const char **subopt) 36128415Speter{ 36234768Speter struct camcontrol_opts *opts; 36328415Speter int num_matches = 0; 36428415Speter 36528415Speter for (opts = table; (opts != NULL) && (opts->optname != NULL); 36628415Speter opts++) { 36734768Speter if (strncmp(opts->optname, arg, strlen(arg)) == 0) { 36828415Speter *cmdnum = opts->cmdnum; 36934768Speter *argnum = opts->argnum; 37034768Speter *subopt = opts->subopt; 37134768Speter if (++num_matches > 1) 37228415Speter return(CC_OR_AMBIGUOUS); 37328415Speter } 37434768Speter } 37534768Speter 37634768Speter if (num_matches > 0) 37734768Speter return(CC_OR_FOUND); 37834768Speter else 37934768Speter return(CC_OR_NOT_FOUND); 38034768Speter} 38128415Speter 38228415Speter#ifndef MINIMALISTIC 38334768Speterstatic int 38428415Spetergetdevlist(struct cam_device *device) 38528415Speter{ 38634768Speter union ccb *ccb; 38734768Speter char status[32]; 38828415Speter int error = 0; 38928415Speter 39028415Speter ccb = cam_getccb(device); 39128415Speter 39228415Speter ccb->ccb_h.func_code = XPT_GDEVLIST; 39328415Speter ccb->ccb_h.flags = CAM_DIR_NONE; 39434768Speter ccb->ccb_h.retry_count = 1; 39534768Speter ccb->cgdl.index = 0; 39634768Speter ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS; 39734768Speter while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) { 39834768Speter if (cam_send_ccb(device, ccb) < 0) { 39928415Speter perror("error getting device list"); 40028415Speter cam_freeccb(ccb); 40134768Speter return(1); 40234768Speter } 40334768Speter 40428415Speter status[0] = '\0'; 40528415Speter 40628415Speter switch (ccb->cgdl.status) { 40728415Speter case CAM_GDEVLIST_MORE_DEVS: 40828415Speter strcpy(status, "MORE"); 40934768Speter break; 41028415Speter case CAM_GDEVLIST_LAST_DEVICE: 41128415Speter strcpy(status, "LAST"); 41228415Speter break; 41328415Speter case CAM_GDEVLIST_LIST_CHANGED: 41428415Speter strcpy(status, "CHANGED"); 41528415Speter break; 41628415Speter case CAM_GDEVLIST_ERROR: 41728415Speter strcpy(status, "ERROR"); 41828415Speter error = 1; 41928415Speter break; 42028415Speter } 42128415Speter 42228415Speter fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n", 42328415Speter ccb->cgdl.periph_name, 42428415Speter ccb->cgdl.unit_number, 42528415Speter ccb->cgdl.generation, 42628415Speter ccb->cgdl.index, 42728415Speter status); 42828415Speter 42934768Speter /* 43034768Speter * If the list has changed, we need to start over from the 43134768Speter * beginning. 43228415Speter */ 43328415Speter if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED) 43428415Speter ccb->cgdl.index = 0; 43528415Speter } 43628415Speter 43734768Speter cam_freeccb(ccb); 43834768Speter 43934768Speter return(error); 44034768Speter} 44134768Speter#endif /* MINIMALISTIC */ 44234768Speter 44328415Speterstatic int 44428415Spetergetdevtree(int argc, char **argv, char *combinedopt) 44528415Speter{ 44628415Speter union ccb ccb; 44728415Speter int bufsize, fd; 44828415Speter unsigned int i; 44928415Speter int need_close = 0; 45028415Speter int error = 0; 45128415Speter int skip_device = 0; 45228415Speter int busonly = 0; 45328415Speter int c; 45428415Speter 45528415Speter while ((c = getopt(argc, argv, combinedopt)) != -1) { 45628415Speter switch(c) { 45728415Speter case 'b': 45834768Speter if ((arglist & CAM_ARG_VERBOSE) == 0) 45934768Speter busonly = 1; 46028415Speter break; 46128415Speter default: 46228415Speter break; 46328415Speter } 46428415Speter } 46528415Speter 46628415Speter if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { 46728415Speter warn("couldn't open %s", XPT_DEVICE); 46828415Speter return(1); 46928415Speter } 47028415Speter 47128415Speter bzero(&ccb, sizeof(union ccb)); 47228415Speter 47328415Speter ccb.ccb_h.path_id = CAM_XPT_PATH_ID; 47428415Speter ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 47528415Speter ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 47628415Speter 47728415Speter ccb.ccb_h.func_code = XPT_DEV_MATCH; 47828415Speter bufsize = sizeof(struct dev_match_result) * 100; 47928415Speter ccb.cdm.match_buf_len = bufsize; 48028415Speter ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); 48128415Speter if (ccb.cdm.matches == NULL) { 48228415Speter warnx("can't malloc memory for matches"); 48328415Speter close(fd); 48434768Speter return(1); 48528415Speter } 48628415Speter ccb.cdm.num_matches = 0; 48728415Speter 48828415Speter /* 48928415Speter * We fetch all nodes, since we display most of them in the default 49028415Speter * case, and all in the verbose case. 49134768Speter */ 49234768Speter ccb.cdm.num_patterns = 0; 49334768Speter ccb.cdm.pattern_buf_len = 0; 49434768Speter 49528415Speter /* 49628415Speter * We do the ioctl multiple times if necessary, in case there are 49728415Speter * more than 100 nodes in the EDT. 49828415Speter */ 49934768Speter do { 50034768Speter if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 50128415Speter warn("error sending CAMIOCOMMAND ioctl"); 50234768Speter error = 1; 50334768Speter break; 50434768Speter } 50528415Speter 50628415Speter if ((ccb.ccb_h.status != CAM_REQ_CMP) 50734768Speter || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) 50834768Speter && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { 50934768Speter warnx("got CAM error %#x, CDM error %d\n", 51034768Speter ccb.ccb_h.status, ccb.cdm.status); 51128415Speter error = 1; 51228415Speter break; 51355205Speter } 514245102Speter 51528415Speter for (i = 0; i < ccb.cdm.num_matches; i++) { 51628415Speter switch (ccb.cdm.matches[i].type) { 51734768Speter case DEV_MATCH_BUS: { 51828415Speter struct bus_match_result *bus_result; 51928415Speter 52028415Speter /* 52128415Speter * Only print the bus information if the 52228415Speter * user turns on the verbose flag. 52328415Speter */ 52428415Speter if ((busonly == 0) && 52528415Speter (arglist & CAM_ARG_VERBOSE) == 0) 52628415Speter break; 52734768Speter 52834768Speter bus_result = 52934768Speter &ccb.cdm.matches[i].result.bus_result; 53028415Speter 53128415Speter if (need_close) { 53228415Speter fprintf(stdout, ")\n"); 53328415Speter need_close = 0; 53428415Speter } 53528415Speter 53634768Speter fprintf(stdout, "scbus%d on %s%d bus %d%s\n", 53734768Speter bus_result->path_id, 53834768Speter bus_result->dev_name, 53928415Speter bus_result->unit_number, 54028415Speter bus_result->bus_id, 54128415Speter (busonly ? "" : ":")); 54228415Speter break; 54328415Speter } 54428415Speter case DEV_MATCH_DEVICE: { 54528415Speter struct device_match_result *dev_result; 54628415Speter char vendor[16], product[48], revision[16]; 54728415Speter char fw[5], tmpstr[256]; 54828415Speter 54928415Speter if (busonly == 1) 55028415Speter break; 55128415Speter 55228415Speter dev_result = 55328415Speter &ccb.cdm.matches[i].result.device_result; 55428415Speter 55528415Speter if ((dev_result->flags 55628415Speter & DEV_RESULT_UNCONFIGURED) 55728415Speter && ((arglist & CAM_ARG_VERBOSE) == 0)) { 55828415Speter skip_device = 1; 55928415Speter break; 56028415Speter } else 56128415Speter skip_device = 0; 56228415Speter 56334768Speter if (dev_result->protocol == PROTO_SCSI) { 56434768Speter cam_strvis(vendor, dev_result->inq_data.vendor, 56534768Speter sizeof(dev_result->inq_data.vendor), 56634768Speter sizeof(vendor)); 56734768Speter cam_strvis(product, 56834768Speter dev_result->inq_data.product, 56934768Speter sizeof(dev_result->inq_data.product), 57034768Speter sizeof(product)); 57134768Speter cam_strvis(revision, 57234768Speter dev_result->inq_data.revision, 57328415Speter sizeof(dev_result->inq_data.revision), 57428415Speter sizeof(revision)); 57534768Speter sprintf(tmpstr, "<%s %s %s>", vendor, product, 57628415Speter revision); 57728415Speter } else if (dev_result->protocol == PROTO_ATA || 57828415Speter dev_result->protocol == PROTO_SATAPM) { 57928415Speter cam_strvis(product, 58028415Speter dev_result->ident_data.model, 58128415Speter sizeof(dev_result->ident_data.model), 58228415Speter sizeof(product)); 58328415Speter cam_strvis(revision, 58428415Speter dev_result->ident_data.revision, 58528415Speter sizeof(dev_result->ident_data.revision), 58634768Speter sizeof(revision)); 58728415Speter sprintf(tmpstr, "<%s %s>", product, 58828415Speter revision); 58928415Speter } else if (dev_result->protocol == PROTO_SEMB) { 59028415Speter struct sep_identify_data *sid; 59128415Speter 59228415Speter sid = (struct sep_identify_data *) 59334768Speter &dev_result->ident_data; 59434768Speter cam_strvis(vendor, sid->vendor_id, 59534768Speter sizeof(sid->vendor_id), 59634768Speter sizeof(vendor)); 59734768Speter cam_strvis(product, sid->product_id, 59834768Speter sizeof(sid->product_id), 59934768Speter sizeof(product)); 60028415Speter cam_strvis(revision, sid->product_rev, 60134768Speter sizeof(sid->product_rev), 60234768Speter sizeof(revision)); 60328415Speter cam_strvis(fw, sid->firmware_rev, 60434768Speter sizeof(sid->firmware_rev), 60534768Speter sizeof(fw)); 60628415Speter sprintf(tmpstr, "<%s %s %s %s>", 60728415Speter vendor, product, revision, fw); 60828415Speter } else { 60928415Speter sprintf(tmpstr, "<>"); 61028415Speter } 61128415Speter if (need_close) { 61228415Speter fprintf(stdout, ")\n"); 61328415Speter need_close = 0; 61434768Speter } 61528415Speter 61628415Speter fprintf(stdout, "%-33s at scbus%d " 61728415Speter "target %d lun %jx (", 61828415Speter tmpstr, 61928415Speter dev_result->path_id, 62034768Speter dev_result->target_id, 62134768Speter (uintmax_t)dev_result->target_lun); 62234768Speter 62334768Speter need_close = 1; 62434768Speter 62534768Speter break; 62634768Speter } 62734768Speter case DEV_MATCH_PERIPH: { 62834768Speter struct periph_match_result *periph_result; 62934768Speter 63028415Speter periph_result = 63128415Speter &ccb.cdm.matches[i].result.periph_result; 63228415Speter 63328415Speter if (busonly || skip_device != 0) 63428415Speter break; 63528415Speter 63628415Speter if (need_close > 1) 63728415Speter fprintf(stdout, ","); 63828415Speter 63928415Speter fprintf(stdout, "%s%d", 64028415Speter periph_result->periph_name, 64128415Speter periph_result->unit_number); 64228415Speter 64328415Speter need_close++; 64428415Speter break; 64528415Speter } 64628415Speter default: 64728415Speter fprintf(stdout, "unknown match type\n"); 64834768Speter break; 64928415Speter } 65028415Speter } 65134768Speter 65234768Speter } while ((ccb.ccb_h.status == CAM_REQ_CMP) 65334768Speter && (ccb.cdm.status == CAM_DEV_MATCH_MORE)); 65428415Speter 65534768Speter if (need_close) 65634768Speter fprintf(stdout, ")\n"); 65734768Speter 65834768Speter close(fd); 65934768Speter 66034768Speter return(error); 66134768Speter} 66234768Speter 66334768Speter#ifndef MINIMALISTIC 66434768Speterstatic int 66534768Spetertestunitready(struct cam_device *device, int task_attr, int retry_count, 66634768Speter int timeout, int quiet) 66734768Speter{ 66834768Speter int error = 0; 66934768Speter union ccb *ccb; 67034768Speter 67134768Speter ccb = cam_getccb(device); 67234768Speter 67334768Speter scsi_test_unit_ready(&ccb->csio, 67434768Speter /* retries */ retry_count, 67534768Speter /* cbfcnp */ NULL, 67634768Speter /* tag_action */ task_attr, 67734768Speter /* sense_len */ SSD_FULL_SIZE, 67834768Speter /* timeout */ timeout ? timeout : 5000); 67934768Speter 68034768Speter /* Disable freezing the device queue */ 68134768Speter ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 68234768Speter 68328415Speter if (arglist & CAM_ARG_ERR_RECOVER) 68428415Speter ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 68528415Speter 68628415Speter if (cam_send_ccb(device, ccb) < 0) { 68728415Speter if (quiet == 0) 68828415Speter perror("error sending test unit ready"); 68928415Speter 69034768Speter if (arglist & CAM_ARG_VERBOSE) { 69128415Speter cam_error_print(device, ccb, CAM_ESF_ALL, 69228415Speter CAM_EPF_ALL, stderr); 69328415Speter } 69428415Speter 69528415Speter cam_freeccb(ccb); 69628415Speter return(1); 69734768Speter } 69828415Speter 69928415Speter if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 70028415Speter if (quiet == 0) 70128415Speter fprintf(stdout, "Unit is ready\n"); 70228415Speter } else { 70334768Speter if (quiet == 0) 70428415Speter fprintf(stdout, "Unit is not ready\n"); 70528415Speter error = 1; 70628415Speter 70728415Speter if (arglist & CAM_ARG_VERBOSE) { 70828415Speter cam_error_print(device, ccb, CAM_ESF_ALL, 70928415Speter CAM_EPF_ALL, stderr); 71028415Speter } 71128415Speter } 71228415Speter 71328415Speter cam_freeccb(ccb); 71434768Speter 71534768Speter return(error); 71634768Speter} 71734768Speter 71834768Speterstatic int 71934768Speterscsistart(struct cam_device *device, int startstop, int loadeject, 72034768Speter int task_attr, int retry_count, int timeout) 72134768Speter{ 72234768Speter union ccb *ccb; 72334768Speter int error = 0; 72434768Speter 72534768Speter ccb = cam_getccb(device); 72634768Speter 72734768Speter /* 72834768Speter * If we're stopping, send an ordered tag so the drive in question 72934768Speter * will finish any previously queued writes before stopping. If 73034768Speter * the device isn't capable of tagged queueing, or if tagged 73134768Speter * queueing is turned off, the tag action is a no-op. We override 73234768Speter * the default simple tag, although this also has the effect of 73334768Speter * overriding the user's wishes if he wanted to specify a simple 73434768Speter * tag. 73534768Speter */ 73634768Speter if ((startstop == 0) 73734768Speter && (task_attr == MSG_SIMPLE_Q_TAG)) 73834768Speter task_attr = MSG_ORDERED_Q_TAG; 73928415Speter 74034768Speter scsi_start_stop(&ccb->csio, 74134768Speter /* retries */ retry_count, 74234768Speter /* cbfcnp */ NULL, 74328415Speter /* tag_action */ task_attr, 74434768Speter /* start/stop */ startstop, 74534768Speter /* load_eject */ loadeject, 74628415Speter /* immediate */ 0, 74728415Speter /* sense_len */ SSD_FULL_SIZE, 74828415Speter /* timeout */ timeout ? timeout : 120000); 74928415Speter 75028415Speter /* Disable freezing the device queue */ 75128415Speter ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 75228415Speter 75328415Speter if (arglist & CAM_ARG_ERR_RECOVER) 75428415Speter ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 75528415Speter 75628415Speter if (cam_send_ccb(device, ccb) < 0) { 75728415Speter perror("error sending start unit"); 75828415Speter 75928415Speter if (arglist & CAM_ARG_VERBOSE) { 76028415Speter cam_error_print(device, ccb, CAM_ESF_ALL, 76128415Speter CAM_EPF_ALL, stderr); 76228415Speter } 76328415Speter 76428415Speter cam_freeccb(ccb); 76528415Speter return(1); 76628415Speter } 76728415Speter 76828415Speter if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 76928415Speter if (startstop) { 77028415Speter fprintf(stdout, "Unit started successfully"); 77128415Speter if (loadeject) 77228415Speter fprintf(stdout,", Media loaded\n"); 77328415Speter else 77434768Speter fprintf(stdout,"\n"); 77534768Speter } else { 77634768Speter fprintf(stdout, "Unit stopped successfully"); 77734768Speter if (loadeject) 77834768Speter fprintf(stdout, ", Media ejected\n"); 77934768Speter else 78034768Speter fprintf(stdout, "\n"); 78134768Speter } 78234768Speter else { 78334768Speter error = 1; 78434768Speter if (startstop) 78534768Speter fprintf(stdout, 78634768Speter "Error received from start unit command\n"); 78734768Speter else 78834768Speter fprintf(stdout, 78934768Speter "Error received from stop unit command\n"); 79034768Speter 79134768Speter if (arglist & CAM_ARG_VERBOSE) { 79234768Speter cam_error_print(device, ccb, CAM_ESF_ALL, 79334768Speter CAM_EPF_ALL, stderr); 79428415Speter } 79528415Speter } 79628415Speter 79728415Speter cam_freeccb(ccb); 79828415Speter 79928415Speter return(error); 80028415Speter} 80128415Speter 80228415Speterint 80328415Speterscsidoinquiry(struct cam_device *device, int argc, char **argv, 80428415Speter char *combinedopt, int task_attr, int retry_count, int timeout) 80528415Speter{ 80628415Speter int c; 80728415Speter int error = 0; 80834768Speter 80928415Speter while ((c = getopt(argc, argv, combinedopt)) != -1) { 81028415Speter switch(c) { 81128415Speter case 'D': 81228415Speter arglist |= CAM_ARG_GET_STDINQ; 81328415Speter break; 81428415Speter case 'R': 81528415Speter arglist |= CAM_ARG_GET_XFERRATE; 81628415Speter break; 81728415Speter case 'S': 81828415Speter arglist |= CAM_ARG_GET_SERIAL; 81928415Speter break; 82028415Speter default: 82128415Speter break; 82228415Speter } 82328415Speter } 82428415Speter 82528415Speter /* 82628415Speter * If the user didn't specify any inquiry options, he wants all of 82734768Speter * them. 82834768Speter */ 82934768Speter if ((arglist & CAM_ARG_INQ_MASK) == 0) 83034768Speter arglist |= CAM_ARG_INQ_MASK; 83134768Speter 83234768Speter if (arglist & CAM_ARG_GET_STDINQ) 83334768Speter error = scsiinquiry(device, task_attr, retry_count, timeout); 83434768Speter 83534768Speter if (error != 0) 83634768Speter return(error); 83734768Speter 83834768Speter if (arglist & CAM_ARG_GET_SERIAL) 83934768Speter scsiserial(device, task_attr, retry_count, timeout); 84034768Speter 84134768Speter if (arglist & CAM_ARG_GET_XFERRATE) 84234768Speter error = camxferrate(device); 84334768Speter 84434768Speter return(error); 84534768Speter} 84634768Speter 84734768Speterstatic int 84834768Speterscsiinquiry(struct cam_device *device, int task_attr, int retry_count, 84934768Speter int timeout) 85034768Speter{ 85134768Speter union ccb *ccb; 85234768Speter struct scsi_inquiry_data *inq_buf; 85334768Speter int error = 0; 85434768Speter 85534768Speter ccb = cam_getccb(device); 85634768Speter 85734768Speter if (ccb == NULL) { 85834768Speter warnx("couldn't allocate CCB"); 85934768Speter return(1); 86034768Speter } 86134768Speter 86234768Speter /* cam_getccb cleans up the header, caller has to zero the payload */ 86334768Speter CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 86434768Speter 86534768Speter inq_buf = (struct scsi_inquiry_data *)malloc( 86634768Speter sizeof(struct scsi_inquiry_data)); 86734768Speter 86834768Speter if (inq_buf == NULL) { 86934768Speter cam_freeccb(ccb); 87034768Speter warnx("can't malloc memory for inquiry\n"); 87134768Speter return(1); 87234768Speter } 87334768Speter bzero(inq_buf, sizeof(*inq_buf)); 87434768Speter 87534768Speter /* 87634768Speter * Note that although the size of the inquiry buffer is the full 87734768Speter * 256 bytes specified in the SCSI spec, we only tell the device 87834768Speter * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are 87934768Speter * two reasons for this: 88034768Speter * 88134768Speter * - The SCSI spec says that when a length field is only 1 byte, 88234768Speter * a value of 0 will be interpreted as 256. Therefore 88334768Speter * scsi_inquiry() will convert an inq_len (which is passed in as 88434768Speter * a u_int32_t, but the field in the CDB is only 1 byte) of 256 88534768Speter * to 0. Evidently, very few devices meet the spec in that 88634768Speter * regard. Some devices, like many Seagate disks, take the 0 as 88734768Speter * 0, and don't return any data. One Pioneer DVD-R drive 88834768Speter * returns more data than the command asked for. 88934768Speter * 89034768Speter * So, since there are numerous devices that just don't work 89134768Speter * right with the full inquiry size, we don't send the full size. 89234768Speter * 89334768Speter * - The second reason not to use the full inquiry data length is 89434768Speter * that we don't need it here. The only reason we issue a 89534768Speter * standard inquiry is to get the vendor name, device name, 89634768Speter * and revision so scsi_print_inquiry() can print them. 89734768Speter * 89834768Speter * If, at some point in the future, more inquiry data is needed for 89934768Speter * some reason, this code should use a procedure similar to the 90034768Speter * probe code. i.e., issue a short inquiry, and determine from 90134768Speter * the additional length passed back from the device how much 90234768Speter * inquiry data the device supports. Once the amount the device 90334768Speter * supports is determined, issue an inquiry for that amount and no 90434768Speter * more. 90534768Speter * 90634768Speter * KDM, 2/18/2000 90734768Speter */ 90834768Speter scsi_inquiry(&ccb->csio, 90934768Speter /* retries */ retry_count, 91034768Speter /* cbfcnp */ NULL, 91134768Speter /* tag_action */ task_attr, 91234768Speter /* inq_buf */ (u_int8_t *)inq_buf, 91334768Speter /* inq_len */ SHORT_INQUIRY_LENGTH, 91434768Speter /* evpd */ 0, 91534768Speter /* page_code */ 0, 91634768Speter /* sense_len */ SSD_FULL_SIZE, 91734768Speter /* timeout */ timeout ? timeout : 5000); 91834768Speter 91934768Speter /* Disable freezing the device queue */ 92034768Speter ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 92134768Speter 92234768Speter if (arglist & CAM_ARG_ERR_RECOVER) 92334768Speter ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 92434768Speter 92534768Speter if (cam_send_ccb(device, ccb) < 0) { 92634768Speter perror("error sending SCSI inquiry"); 92734768Speter 92834768Speter if (arglist & CAM_ARG_VERBOSE) { 92934768Speter cam_error_print(device, ccb, CAM_ESF_ALL, 93034768Speter CAM_EPF_ALL, stderr); 93134768Speter } 93234768Speter 93334768Speter cam_freeccb(ccb); 93496755Strhodes return(1); 93534768Speter } 93634768Speter 93734768Speter if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 93834768Speter error = 1; 93928415Speter 94028415Speter if (arglist & CAM_ARG_VERBOSE) { 94128415Speter cam_error_print(device, ccb, CAM_ESF_ALL, 94234768Speter CAM_EPF_ALL, stderr); 94334768Speter } 94428415Speter } 94528415Speter 94628415Speter cam_freeccb(ccb); 94734768Speter 94828415Speter if (error != 0) { 94928415Speter free(inq_buf); 95028415Speter return(error); 95128415Speter } 95228415Speter 95328415Speter fprintf(stdout, "%s%d: ", device->device_name, 95428415Speter device->dev_unit_num); 95528415Speter scsi_print_inquiry(inq_buf); 95628415Speter 95728415Speter free(inq_buf); 95828415Speter 95928415Speter return(0); 96028415Speter} 96128415Speter 96228415Speterstatic int 96328415Speterscsiserial(struct cam_device *device, int task_attr, int retry_count, 96497512Sphk int timeout) 96534768Speter{ 96634768Speter union ccb *ccb; 96734768Speter struct scsi_vpd_unit_serial_number *serial_buf; 96834768Speter char serial_num[SVPD_SERIAL_NUM_SIZE + 1]; 96934768Speter int error = 0; 97034768Speter 97134768Speter ccb = cam_getccb(device); 97234768Speter 97334768Speter if (ccb == NULL) { 97434768Speter warnx("couldn't allocate CCB"); 97534768Speter return(1); 97634768Speter } 97734768Speter 97834768Speter /* cam_getccb cleans up the header, caller has to zero the payload */ 97934768Speter CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 98097512Sphk 98134768Speter serial_buf = (struct scsi_vpd_unit_serial_number *) 98234768Speter malloc(sizeof(*serial_buf)); 98334768Speter 98434768Speter if (serial_buf == NULL) { 98534768Speter cam_freeccb(ccb); 98634768Speter warnx("can't malloc memory for serial number"); 98734768Speter return(1); 98834768Speter } 98934768Speter 99034768Speter scsi_inquiry(&ccb->csio, 99134768Speter /*retries*/ retry_count, 99234768Speter /*cbfcnp*/ NULL, 99334768Speter /* tag_action */ task_attr, 99434768Speter /* inq_buf */ (u_int8_t *)serial_buf, 99534768Speter /* inq_len */ sizeof(*serial_buf), 99634768Speter /* evpd */ 1, 99734768Speter /* page_code */ SVPD_UNIT_SERIAL_NUMBER, 99834768Speter /* sense_len */ SSD_FULL_SIZE, 99934768Speter /* timeout */ timeout ? timeout : 5000); 100034768Speter 100134768Speter /* Disable freezing the device queue */ 100234768Speter ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 100334768Speter 100434768Speter if (arglist & CAM_ARG_ERR_RECOVER) 100534768Speter ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 100634768Speter 100734768Speter if (cam_send_ccb(device, ccb) < 0) { 100828415Speter warn("error getting serial number"); 100928415Speter 101028415Speter if (arglist & CAM_ARG_VERBOSE) { 101134768Speter cam_error_print(device, ccb, CAM_ESF_ALL, 101234768Speter CAM_EPF_ALL, stderr); 1013204552Salfred } 1014204552Salfred 1015204552Salfred cam_freeccb(ccb); 1016204552Salfred free(serial_buf); 1017204552Salfred return(1); 1018204552Salfred } 1019204552Salfred 102034768Speter if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 102134768Speter error = 1; 102234768Speter 102334768Speter if (arglist & CAM_ARG_VERBOSE) { 102428415Speter cam_error_print(device, ccb, CAM_ESF_ALL, 102534768Speter CAM_EPF_ALL, stderr); 1026 } 1027 } 1028 1029 cam_freeccb(ccb); 1030 1031 if (error != 0) { 1032 free(serial_buf); 1033 return(error); 1034 } 1035 1036 bcopy(serial_buf->serial_num, serial_num, serial_buf->length); 1037 serial_num[serial_buf->length] = '\0'; 1038 1039 if ((arglist & CAM_ARG_GET_STDINQ) 1040 || (arglist & CAM_ARG_GET_XFERRATE)) 1041 fprintf(stdout, "%s%d: Serial Number ", 1042 device->device_name, device->dev_unit_num); 1043 1044 fprintf(stdout, "%.60s\n", serial_num); 1045 1046 free(serial_buf); 1047 1048 return(0); 1049} 1050 1051int 1052camxferrate(struct cam_device *device) 1053{ 1054 struct ccb_pathinq cpi; 1055 u_int32_t freq = 0; 1056 u_int32_t speed = 0; 1057 union ccb *ccb; 1058 u_int mb; 1059 int retval = 0; 1060 1061 if ((retval = get_cpi(device, &cpi)) != 0) 1062 return (1); 1063 1064 ccb = cam_getccb(device); 1065 1066 if (ccb == NULL) { 1067 warnx("couldn't allocate CCB"); 1068 return(1); 1069 } 1070 1071 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts); 1072 1073 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 1074 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS; 1075 1076 if (((retval = cam_send_ccb(device, ccb)) < 0) 1077 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 1078 const char error_string[] = "error getting transfer settings"; 1079 1080 if (retval < 0) 1081 warn(error_string); 1082 else 1083 warnx(error_string); 1084 1085 if (arglist & CAM_ARG_VERBOSE) 1086 cam_error_print(device, ccb, CAM_ESF_ALL, 1087 CAM_EPF_ALL, stderr); 1088 1089 retval = 1; 1090 1091 goto xferrate_bailout; 1092 1093 } 1094 1095 speed = cpi.base_transfer_speed; 1096 freq = 0; 1097 if (ccb->cts.transport == XPORT_SPI) { 1098 struct ccb_trans_settings_spi *spi = 1099 &ccb->cts.xport_specific.spi; 1100 1101 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { 1102 freq = scsi_calc_syncsrate(spi->sync_period); 1103 speed = freq; 1104 } 1105 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 1106 speed *= (0x01 << spi->bus_width); 1107 } 1108 } else if (ccb->cts.transport == XPORT_FC) { 1109 struct ccb_trans_settings_fc *fc = 1110 &ccb->cts.xport_specific.fc; 1111 1112 if (fc->valid & CTS_FC_VALID_SPEED) 1113 speed = fc->bitrate; 1114 } else if (ccb->cts.transport == XPORT_SAS) { 1115 struct ccb_trans_settings_sas *sas = 1116 &ccb->cts.xport_specific.sas; 1117 1118 if (sas->valid & CTS_SAS_VALID_SPEED) 1119 speed = sas->bitrate; 1120 } else if (ccb->cts.transport == XPORT_ATA) { 1121 struct ccb_trans_settings_pata *pata = 1122 &ccb->cts.xport_specific.ata; 1123 1124 if (pata->valid & CTS_ATA_VALID_MODE) 1125 speed = ata_mode2speed(pata->mode); 1126 } else if (ccb->cts.transport == XPORT_SATA) { 1127 struct ccb_trans_settings_sata *sata = 1128 &ccb->cts.xport_specific.sata; 1129 1130 if (sata->valid & CTS_SATA_VALID_REVISION) 1131 speed = ata_revision2speed(sata->revision); 1132 } 1133 1134 mb = speed / 1000; 1135 if (mb > 0) { 1136 fprintf(stdout, "%s%d: %d.%03dMB/s transfers", 1137 device->device_name, device->dev_unit_num, 1138 mb, speed % 1000); 1139 } else { 1140 fprintf(stdout, "%s%d: %dKB/s transfers", 1141 device->device_name, device->dev_unit_num, 1142 speed); 1143 } 1144 1145 if (ccb->cts.transport == XPORT_SPI) { 1146 struct ccb_trans_settings_spi *spi = 1147 &ccb->cts.xport_specific.spi; 1148 1149 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 1150 && (spi->sync_offset != 0)) 1151 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000, 1152 freq % 1000, spi->sync_offset); 1153 1154 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) 1155 && (spi->bus_width > 0)) { 1156 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 1157 && (spi->sync_offset != 0)) { 1158 fprintf(stdout, ", "); 1159 } else { 1160 fprintf(stdout, " ("); 1161 } 1162 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width)); 1163 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 1164 && (spi->sync_offset != 0)) { 1165 fprintf(stdout, ")"); 1166 } 1167 } else if (ccb->cts.transport == XPORT_ATA) { 1168 struct ccb_trans_settings_pata *pata = 1169 &ccb->cts.xport_specific.ata; 1170 1171 printf(" ("); 1172 if (pata->valid & CTS_ATA_VALID_MODE) 1173 printf("%s, ", ata_mode2string(pata->mode)); 1174 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) 1175 printf("ATAPI %dbytes, ", pata->atapi); 1176 if (pata->valid & CTS_ATA_VALID_BYTECOUNT) 1177 printf("PIO %dbytes", pata->bytecount); 1178 printf(")"); 1179 } else if (ccb->cts.transport == XPORT_SATA) { 1180 struct ccb_trans_settings_sata *sata = 1181 &ccb->cts.xport_specific.sata; 1182 1183 printf(" ("); 1184 if (sata->valid & CTS_SATA_VALID_REVISION) 1185 printf("SATA %d.x, ", sata->revision); 1186 else 1187 printf("SATA, "); 1188 if (sata->valid & CTS_SATA_VALID_MODE) 1189 printf("%s, ", ata_mode2string(sata->mode)); 1190 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0) 1191 printf("ATAPI %dbytes, ", sata->atapi); 1192 if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 1193 printf("PIO %dbytes", sata->bytecount); 1194 printf(")"); 1195 } 1196 1197 if (ccb->cts.protocol == PROTO_SCSI) { 1198 struct ccb_trans_settings_scsi *scsi = 1199 &ccb->cts.proto_specific.scsi; 1200 if (scsi->valid & CTS_SCSI_VALID_TQ) { 1201 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) { 1202 fprintf(stdout, ", Command Queueing Enabled"); 1203 } 1204 } 1205 } 1206 1207 fprintf(stdout, "\n"); 1208 1209xferrate_bailout: 1210 1211 cam_freeccb(ccb); 1212 1213 return(retval); 1214} 1215 1216static void 1217atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header) 1218{ 1219 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | 1220 ((u_int32_t)parm->lba_size_2 << 16); 1221 1222 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) | 1223 ((u_int64_t)parm->lba_size48_2 << 16) | 1224 ((u_int64_t)parm->lba_size48_3 << 32) | 1225 ((u_int64_t)parm->lba_size48_4 << 48); 1226 1227 if (header) { 1228 printf("\nFeature " 1229 "Support Enabled Value\n"); 1230 } 1231 1232 printf("Host Protected Area (HPA) "); 1233 if (parm->support.command1 & ATA_SUPPORT_PROTECTED) { 1234 u_int64_t lba = lbasize48 ? lbasize48 : lbasize; 1235 printf("yes %s %ju/%ju\n", (hpasize > lba) ? "yes" : "no ", 1236 lba, hpasize); 1237 1238 printf("HPA - Security "); 1239 if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY) 1240 printf("yes\n"); 1241 else 1242 printf("no\n"); 1243 } else { 1244 printf("no\n"); 1245 } 1246} 1247 1248static int 1249atasata(struct ata_params *parm) 1250{ 1251 1252 1253 if (parm->satacapabilities != 0xffff && 1254 parm->satacapabilities != 0x0000) 1255 return 1; 1256 1257 return 0; 1258} 1259 1260static void 1261atacapprint(struct ata_params *parm) 1262{ 1263 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | 1264 ((u_int32_t)parm->lba_size_2 << 16); 1265 1266 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) | 1267 ((u_int64_t)parm->lba_size48_2 << 16) | 1268 ((u_int64_t)parm->lba_size48_3 << 32) | 1269 ((u_int64_t)parm->lba_size48_4 << 48); 1270 1271 printf("\n"); 1272 printf("protocol "); 1273 printf("ATA/ATAPI-%d", ata_version(parm->version_major)); 1274 if (parm->satacapabilities && parm->satacapabilities != 0xffff) { 1275 if (parm->satacapabilities & ATA_SATA_GEN3) 1276 printf(" SATA 3.x\n"); 1277 else if (parm->satacapabilities & ATA_SATA_GEN2) 1278 printf(" SATA 2.x\n"); 1279 else if (parm->satacapabilities & ATA_SATA_GEN1) 1280 printf(" SATA 1.x\n"); 1281 else 1282 printf(" SATA\n"); 1283 } 1284 else 1285 printf("\n"); 1286 printf("device model %.40s\n", parm->model); 1287 printf("firmware revision %.8s\n", parm->revision); 1288 printf("serial number %.20s\n", parm->serial); 1289 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) { 1290 printf("WWN %04x%04x%04x%04x\n", 1291 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]); 1292 } 1293 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) { 1294 printf("media serial number %.30s\n", 1295 parm->media_serial); 1296 } 1297 1298 printf("cylinders %d\n", parm->cylinders); 1299 printf("heads %d\n", parm->heads); 1300 printf("sectors/track %d\n", parm->sectors); 1301 printf("sector size logical %u, physical %lu, offset %lu\n", 1302 ata_logical_sector_size(parm), 1303 (unsigned long)ata_physical_sector_size(parm), 1304 (unsigned long)ata_logical_sector_offset(parm)); 1305 1306 if (parm->config == ATA_PROTO_CFA || 1307 (parm->support.command2 & ATA_SUPPORT_CFA)) 1308 printf("CFA supported\n"); 1309 1310 printf("LBA%ssupported ", 1311 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not "); 1312 if (lbasize) 1313 printf("%d sectors\n", lbasize); 1314 else 1315 printf("\n"); 1316 1317 printf("LBA48%ssupported ", 1318 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not "); 1319 if (lbasize48) 1320 printf("%ju sectors\n", (uintmax_t)lbasize48); 1321 else 1322 printf("\n"); 1323 1324 printf("PIO supported PIO"); 1325 switch (ata_max_pmode(parm)) { 1326 case ATA_PIO4: 1327 printf("4"); 1328 break; 1329 case ATA_PIO3: 1330 printf("3"); 1331 break; 1332 case ATA_PIO2: 1333 printf("2"); 1334 break; 1335 case ATA_PIO1: 1336 printf("1"); 1337 break; 1338 default: 1339 printf("0"); 1340 } 1341 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0) 1342 printf(" w/o IORDY"); 1343 printf("\n"); 1344 1345 printf("DMA%ssupported ", 1346 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not "); 1347 if (parm->capabilities1 & ATA_SUPPORT_DMA) { 1348 if (parm->mwdmamodes & 0xff) { 1349 printf("WDMA"); 1350 if (parm->mwdmamodes & 0x04) 1351 printf("2"); 1352 else if (parm->mwdmamodes & 0x02) 1353 printf("1"); 1354 else if (parm->mwdmamodes & 0x01) 1355 printf("0"); 1356 printf(" "); 1357 } 1358 if ((parm->atavalid & ATA_FLAG_88) && 1359 (parm->udmamodes & 0xff)) { 1360 printf("UDMA"); 1361 if (parm->udmamodes & 0x40) 1362 printf("6"); 1363 else if (parm->udmamodes & 0x20) 1364 printf("5"); 1365 else if (parm->udmamodes & 0x10) 1366 printf("4"); 1367 else if (parm->udmamodes & 0x08) 1368 printf("3"); 1369 else if (parm->udmamodes & 0x04) 1370 printf("2"); 1371 else if (parm->udmamodes & 0x02) 1372 printf("1"); 1373 else if (parm->udmamodes & 0x01) 1374 printf("0"); 1375 printf(" "); 1376 } 1377 } 1378 printf("\n"); 1379 1380 if (parm->media_rotation_rate == 1) { 1381 printf("media RPM non-rotating\n"); 1382 } else if (parm->media_rotation_rate >= 0x0401 && 1383 parm->media_rotation_rate <= 0xFFFE) { 1384 printf("media RPM %d\n", 1385 parm->media_rotation_rate); 1386 } 1387 1388 printf("\nFeature " 1389 "Support Enabled Value Vendor\n"); 1390 printf("read ahead %s %s\n", 1391 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no", 1392 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no"); 1393 printf("write cache %s %s\n", 1394 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no", 1395 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no"); 1396 printf("flush cache %s %s\n", 1397 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no", 1398 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no"); 1399 printf("overlap %s\n", 1400 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no"); 1401 printf("Tagged Command Queuing (TCQ) %s %s", 1402 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no", 1403 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no"); 1404 if (parm->support.command2 & ATA_SUPPORT_QUEUED) { 1405 printf(" %d tags\n", 1406 ATA_QUEUE_LEN(parm->queue) + 1); 1407 } else 1408 printf("\n"); 1409 printf("Native Command Queuing (NCQ) "); 1410 if (parm->satacapabilities != 0xffff && 1411 (parm->satacapabilities & ATA_SUPPORT_NCQ)) { 1412 printf("yes %d tags\n", 1413 ATA_QUEUE_LEN(parm->queue) + 1); 1414 } else 1415 printf("no\n"); 1416 1417 printf("NCQ Queue Management %s\n", atasata(parm) && 1418 parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ? 1419 "yes" : "no"); 1420 printf("NCQ Streaming %s\n", atasata(parm) && 1421 parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ? 1422 "yes" : "no"); 1423 printf("Receive & Send FPDMA Queued %s\n", atasata(parm) && 1424 parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ? 1425 "yes" : "no"); 1426 1427 printf("SMART %s %s\n", 1428 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no", 1429 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no"); 1430 printf("microcode download %s %s\n", 1431 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no", 1432 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no"); 1433 printf("security %s %s\n", 1434 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no", 1435 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no"); 1436 printf("power management %s %s\n", 1437 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no", 1438 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no"); 1439 printf("advanced power management %s %s", 1440 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no", 1441 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no"); 1442 if (parm->support.command2 & ATA_SUPPORT_APM) { 1443 printf(" %d/0x%02X\n", 1444 parm->apm_value & 0xff, parm->apm_value & 0xff); 1445 } else 1446 printf("\n"); 1447 printf("automatic acoustic management %s %s", 1448 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no", 1449 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no"); 1450 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) { 1451 printf(" %d/0x%02X %d/0x%02X\n", 1452 ATA_ACOUSTIC_CURRENT(parm->acoustic), 1453 ATA_ACOUSTIC_CURRENT(parm->acoustic), 1454 ATA_ACOUSTIC_VENDOR(parm->acoustic), 1455 ATA_ACOUSTIC_VENDOR(parm->acoustic)); 1456 } else 1457 printf("\n"); 1458 printf("media status notification %s %s\n", 1459 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no", 1460 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no"); 1461 printf("power-up in Standby %s %s\n", 1462 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no", 1463 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no"); 1464 printf("write-read-verify %s %s", 1465 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no", 1466 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no"); 1467 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) { 1468 printf(" %d/0x%x\n", 1469 parm->wrv_mode, parm->wrv_mode); 1470 } else 1471 printf("\n"); 1472 printf("unload %s %s\n", 1473 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no", 1474 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no"); 1475 printf("general purpose logging %s %s\n", 1476 parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no", 1477 parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no"); 1478 printf("free-fall %s %s\n", 1479 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no", 1480 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no"); 1481 printf("Data Set Management (DSM/TRIM) "); 1482 if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) { 1483 printf("yes\n"); 1484 printf("DSM - max 512byte blocks "); 1485 if (parm->max_dsm_blocks == 0x00) 1486 printf("yes not specified\n"); 1487 else 1488 printf("yes %d\n", 1489 parm->max_dsm_blocks); 1490 1491 printf("DSM - deterministic read "); 1492 if (parm->support3 & ATA_SUPPORT_DRAT) { 1493 if (parm->support3 & ATA_SUPPORT_RZAT) 1494 printf("yes zeroed\n"); 1495 else 1496 printf("yes any value\n"); 1497 } else { 1498 printf("no\n"); 1499 } 1500 } else { 1501 printf("no\n"); 1502 } 1503} 1504 1505static int 1506scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet) 1507{ 1508 struct ata_pass_16 *ata_pass_16; 1509 struct ata_cmd ata_cmd; 1510 1511 ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes; 1512 ata_cmd.command = ata_pass_16->command; 1513 ata_cmd.control = ata_pass_16->control; 1514 ata_cmd.features = ata_pass_16->features; 1515 1516 if (arglist & CAM_ARG_VERBOSE) { 1517 warnx("sending ATA %s via pass_16 with timeout of %u msecs", 1518 ata_op_string(&ata_cmd), 1519 ccb->csio.ccb_h.timeout); 1520 } 1521 1522 /* Disable freezing the device queue */ 1523 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 1524 1525 if (arglist & CAM_ARG_ERR_RECOVER) 1526 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 1527 1528 if (cam_send_ccb(device, ccb) < 0) { 1529 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) { 1530 warn("error sending ATA %s via pass_16", 1531 ata_op_string(&ata_cmd)); 1532 } 1533 1534 if (arglist & CAM_ARG_VERBOSE) { 1535 cam_error_print(device, ccb, CAM_ESF_ALL, 1536 CAM_EPF_ALL, stderr); 1537 } 1538 1539 return (1); 1540 } 1541 1542 if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) && 1543 (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1544 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) { 1545 warnx("ATA %s via pass_16 failed", 1546 ata_op_string(&ata_cmd)); 1547 } 1548 if (arglist & CAM_ARG_VERBOSE) { 1549 cam_error_print(device, ccb, CAM_ESF_ALL, 1550 CAM_EPF_ALL, stderr); 1551 } 1552 1553 return (1); 1554 } 1555 1556 return (0); 1557} 1558 1559 1560static int 1561ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet) 1562{ 1563 if (arglist & CAM_ARG_VERBOSE) { 1564 warnx("sending ATA %s with timeout of %u msecs", 1565 ata_op_string(&(ccb->ataio.cmd)), 1566 ccb->ataio.ccb_h.timeout); 1567 } 1568 1569 /* Disable freezing the device queue */ 1570 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 1571 1572 if (arglist & CAM_ARG_ERR_RECOVER) 1573 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 1574 1575 if (cam_send_ccb(device, ccb) < 0) { 1576 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) { 1577 warn("error sending ATA %s", 1578 ata_op_string(&(ccb->ataio.cmd))); 1579 } 1580 1581 if (arglist & CAM_ARG_VERBOSE) { 1582 cam_error_print(device, ccb, CAM_ESF_ALL, 1583 CAM_EPF_ALL, stderr); 1584 } 1585 1586 return (1); 1587 } 1588 1589 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1590 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) { 1591 warnx("ATA %s failed: %d", 1592 ata_op_string(&(ccb->ataio.cmd)), quiet); 1593 } 1594 1595 if (arglist & CAM_ARG_VERBOSE) { 1596 cam_error_print(device, ccb, CAM_ESF_ALL, 1597 CAM_EPF_ALL, stderr); 1598 } 1599 1600 return (1); 1601 } 1602 1603 return (0); 1604} 1605 1606static int 1607ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries, 1608 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags, 1609 u_int8_t tag_action, u_int8_t command, u_int8_t features, 1610 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr, 1611 u_int16_t dxfer_len, int timeout, int quiet) 1612{ 1613 if (data_ptr != NULL) { 1614 ata_flags |= AP_FLAG_BYT_BLOK_BYTES | 1615 AP_FLAG_TLEN_SECT_CNT; 1616 if (flags & CAM_DIR_OUT) 1617 ata_flags |= AP_FLAG_TDIR_TO_DEV; 1618 else 1619 ata_flags |= AP_FLAG_TDIR_FROM_DEV; 1620 } else { 1621 ata_flags |= AP_FLAG_TLEN_NO_DATA; 1622 } 1623 1624 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 1625 1626 scsi_ata_pass_16(&ccb->csio, 1627 retries, 1628 NULL, 1629 flags, 1630 tag_action, 1631 protocol, 1632 ata_flags, 1633 features, 1634 sector_count, 1635 lba, 1636 command, 1637 /*control*/0, 1638 data_ptr, 1639 dxfer_len, 1640 /*sense_len*/SSD_FULL_SIZE, 1641 timeout); 1642 1643 return scsi_cam_pass_16_send(device, ccb, quiet); 1644} 1645 1646static int 1647ata_try_pass_16(struct cam_device *device) 1648{ 1649 struct ccb_pathinq cpi; 1650 1651 if (get_cpi(device, &cpi) != 0) { 1652 warnx("couldn't get CPI"); 1653 return (-1); 1654 } 1655 1656 if (cpi.protocol == PROTO_SCSI) { 1657 /* possibly compatible with pass_16 */ 1658 return (1); 1659 } 1660 1661 /* likely not compatible with pass_16 */ 1662 return (0); 1663} 1664 1665static int 1666ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries, 1667 u_int32_t flags, u_int8_t protocol, u_int8_t tag_action, 1668 u_int8_t command, u_int8_t features, u_int32_t lba, 1669 u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len, 1670 int timeout, int quiet) 1671{ 1672 1673 1674 switch (ata_try_pass_16(device)) { 1675 case -1: 1676 return (1); 1677 case 1: 1678 /* Try using SCSI Passthrough */ 1679 return ata_do_pass_16(device, ccb, retries, flags, protocol, 1680 0, tag_action, command, features, lba, 1681 sector_count, data_ptr, dxfer_len, 1682 timeout, quiet); 1683 } 1684 1685 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->ataio); 1686 cam_fill_ataio(&ccb->ataio, 1687 retries, 1688 NULL, 1689 flags, 1690 tag_action, 1691 data_ptr, 1692 dxfer_len, 1693 timeout); 1694 1695 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count); 1696 return ata_cam_send(device, ccb, quiet); 1697} 1698 1699static int 1700ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries, 1701 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags, 1702 u_int8_t tag_action, u_int8_t command, u_int8_t features, 1703 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr, 1704 u_int16_t dxfer_len, int timeout, int force48bit) 1705{ 1706 int retval; 1707 1708 retval = ata_try_pass_16(device); 1709 if (retval == -1) 1710 return (1); 1711 1712 if (retval == 1) { 1713 int error; 1714 1715 /* Try using SCSI Passthrough */ 1716 error = ata_do_pass_16(device, ccb, retries, flags, protocol, 1717 ata_flags, tag_action, command, features, 1718 lba, sector_count, data_ptr, dxfer_len, 1719 timeout, 0); 1720 1721 if (ata_flags & AP_FLAG_CHK_COND) { 1722 /* Decode ata_res from sense data */ 1723 struct ata_res_pass16 *res_pass16; 1724 struct ata_res *res; 1725 u_int i; 1726 u_int16_t *ptr; 1727 1728 /* sense_data is 4 byte aligned */ 1729 ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data; 1730 for (i = 0; i < sizeof(*res_pass16) / 2; i++) 1731 ptr[i] = le16toh(ptr[i]); 1732 1733 /* sense_data is 4 byte aligned */ 1734 res_pass16 = (struct ata_res_pass16 *)(uintptr_t) 1735 &ccb->csio.sense_data; 1736 res = &ccb->ataio.res; 1737 res->flags = res_pass16->flags; 1738 res->status = res_pass16->status; 1739 res->error = res_pass16->error; 1740 res->lba_low = res_pass16->lba_low; 1741 res->lba_mid = res_pass16->lba_mid; 1742 res->lba_high = res_pass16->lba_high; 1743 res->device = res_pass16->device; 1744 res->lba_low_exp = res_pass16->lba_low_exp; 1745 res->lba_mid_exp = res_pass16->lba_mid_exp; 1746 res->lba_high_exp = res_pass16->lba_high_exp; 1747 res->sector_count = res_pass16->sector_count; 1748 res->sector_count_exp = res_pass16->sector_count_exp; 1749 } 1750 1751 return (error); 1752 } 1753 1754 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->ataio); 1755 cam_fill_ataio(&ccb->ataio, 1756 retries, 1757 NULL, 1758 flags, 1759 tag_action, 1760 data_ptr, 1761 dxfer_len, 1762 timeout); 1763 1764 if (force48bit || lba > ATA_MAX_28BIT_LBA) 1765 ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count); 1766 else 1767 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count); 1768 1769 if (ata_flags & AP_FLAG_CHK_COND) 1770 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT; 1771 1772 return ata_cam_send(device, ccb, 0); 1773} 1774 1775static void 1776dump_data(uint16_t *ptr, uint32_t len) 1777{ 1778 u_int i; 1779 1780 for (i = 0; i < len / 2; i++) { 1781 if ((i % 8) == 0) 1782 printf(" %3d: ", i); 1783 printf("%04hx ", ptr[i]); 1784 if ((i % 8) == 7) 1785 printf("\n"); 1786 } 1787 if ((i % 8) != 7) 1788 printf("\n"); 1789} 1790 1791static int 1792atahpa_proc_resp(struct cam_device *device, union ccb *ccb, 1793 int is48bit, u_int64_t *hpasize) 1794{ 1795 struct ata_res *res; 1796 1797 res = &ccb->ataio.res; 1798 if (res->status & ATA_STATUS_ERROR) { 1799 if (arglist & CAM_ARG_VERBOSE) { 1800 cam_error_print(device, ccb, CAM_ESF_ALL, 1801 CAM_EPF_ALL, stderr); 1802 printf("error = 0x%02x, sector_count = 0x%04x, " 1803 "device = 0x%02x, status = 0x%02x\n", 1804 res->error, res->sector_count, 1805 res->device, res->status); 1806 } 1807 1808 if (res->error & ATA_ERROR_ID_NOT_FOUND) { 1809 warnx("Max address has already been set since " 1810 "last power-on or hardware reset"); 1811 } 1812 1813 return (1); 1814 } 1815 1816 if (arglist & CAM_ARG_VERBOSE) { 1817 fprintf(stdout, "%s%d: Raw native max data:\n", 1818 device->device_name, device->dev_unit_num); 1819 /* res is 4 byte aligned */ 1820 dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res)); 1821 1822 printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, " 1823 "status = 0x%02x\n", res->error, res->sector_count, 1824 res->device, res->status); 1825 } 1826 1827 if (hpasize != NULL) { 1828 if (is48bit) { 1829 *hpasize = (((u_int64_t)((res->lba_high_exp << 16) | 1830 (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) | 1831 ((res->lba_high << 16) | (res->lba_mid << 8) | 1832 res->lba_low)) + 1; 1833 } else { 1834 *hpasize = (((res->device & 0x0f) << 24) | 1835 (res->lba_high << 16) | (res->lba_mid << 8) | 1836 res->lba_low) + 1; 1837 } 1838 } 1839 1840 return (0); 1841} 1842 1843static int 1844ata_read_native_max(struct cam_device *device, int retry_count, 1845 u_int32_t timeout, union ccb *ccb, 1846 struct ata_params *parm, u_int64_t *hpasize) 1847{ 1848 int error; 1849 u_int cmd, is48bit; 1850 u_int8_t protocol; 1851 1852 is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48; 1853 protocol = AP_PROTO_NON_DATA; 1854 1855 if (is48bit) { 1856 cmd = ATA_READ_NATIVE_MAX_ADDRESS48; 1857 protocol |= AP_EXTEND; 1858 } else { 1859 cmd = ATA_READ_NATIVE_MAX_ADDRESS; 1860 } 1861 1862 error = ata_do_cmd(device, 1863 ccb, 1864 retry_count, 1865 /*flags*/CAM_DIR_NONE, 1866 /*protocol*/protocol, 1867 /*ata_flags*/AP_FLAG_CHK_COND, 1868 /*tag_action*/MSG_SIMPLE_Q_TAG, 1869 /*command*/cmd, 1870 /*features*/0, 1871 /*lba*/0, 1872 /*sector_count*/0, 1873 /*data_ptr*/NULL, 1874 /*dxfer_len*/0, 1875 timeout ? timeout : 1000, 1876 is48bit); 1877 1878 if (error) 1879 return (error); 1880 1881 return atahpa_proc_resp(device, ccb, is48bit, hpasize); 1882} 1883 1884static int 1885atahpa_set_max(struct cam_device *device, int retry_count, 1886 u_int32_t timeout, union ccb *ccb, 1887 int is48bit, u_int64_t maxsize, int persist) 1888{ 1889 int error; 1890 u_int cmd; 1891 u_int8_t protocol; 1892 1893 protocol = AP_PROTO_NON_DATA; 1894 1895 if (is48bit) { 1896 cmd = ATA_SET_MAX_ADDRESS48; 1897 protocol |= AP_EXTEND; 1898 } else { 1899 cmd = ATA_SET_MAX_ADDRESS; 1900 } 1901 1902 /* lba's are zero indexed so the max lba is requested max - 1 */ 1903 if (maxsize) 1904 maxsize--; 1905 1906 error = ata_do_cmd(device, 1907 ccb, 1908 retry_count, 1909 /*flags*/CAM_DIR_NONE, 1910 /*protocol*/protocol, 1911 /*ata_flags*/AP_FLAG_CHK_COND, 1912 /*tag_action*/MSG_SIMPLE_Q_TAG, 1913 /*command*/cmd, 1914 /*features*/ATA_HPA_FEAT_MAX_ADDR, 1915 /*lba*/maxsize, 1916 /*sector_count*/persist, 1917 /*data_ptr*/NULL, 1918 /*dxfer_len*/0, 1919 timeout ? timeout : 1000, 1920 is48bit); 1921 1922 if (error) 1923 return (error); 1924 1925 return atahpa_proc_resp(device, ccb, is48bit, NULL); 1926} 1927 1928static int 1929atahpa_password(struct cam_device *device, int retry_count, 1930 u_int32_t timeout, union ccb *ccb, 1931 int is48bit, struct ata_set_max_pwd *pwd) 1932{ 1933 int error; 1934 u_int cmd; 1935 u_int8_t protocol; 1936 1937 protocol = AP_PROTO_PIO_OUT; 1938 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; 1939 1940 error = ata_do_cmd(device, 1941 ccb, 1942 retry_count, 1943 /*flags*/CAM_DIR_OUT, 1944 /*protocol*/protocol, 1945 /*ata_flags*/AP_FLAG_CHK_COND, 1946 /*tag_action*/MSG_SIMPLE_Q_TAG, 1947 /*command*/cmd, 1948 /*features*/ATA_HPA_FEAT_SET_PWD, 1949 /*lba*/0, 1950 /*sector_count*/0, 1951 /*data_ptr*/(u_int8_t*)pwd, 1952 /*dxfer_len*/sizeof(struct ata_set_max_pwd), 1953 timeout ? timeout : 1000, 1954 is48bit); 1955 1956 if (error) 1957 return (error); 1958 1959 return atahpa_proc_resp(device, ccb, is48bit, NULL); 1960} 1961 1962static int 1963atahpa_lock(struct cam_device *device, int retry_count, 1964 u_int32_t timeout, union ccb *ccb, int is48bit) 1965{ 1966 int error; 1967 u_int cmd; 1968 u_int8_t protocol; 1969 1970 protocol = AP_PROTO_NON_DATA; 1971 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; 1972 1973 error = ata_do_cmd(device, 1974 ccb, 1975 retry_count, 1976 /*flags*/CAM_DIR_NONE, 1977 /*protocol*/protocol, 1978 /*ata_flags*/AP_FLAG_CHK_COND, 1979 /*tag_action*/MSG_SIMPLE_Q_TAG, 1980 /*command*/cmd, 1981 /*features*/ATA_HPA_FEAT_LOCK, 1982 /*lba*/0, 1983 /*sector_count*/0, 1984 /*data_ptr*/NULL, 1985 /*dxfer_len*/0, 1986 timeout ? timeout : 1000, 1987 is48bit); 1988 1989 if (error) 1990 return (error); 1991 1992 return atahpa_proc_resp(device, ccb, is48bit, NULL); 1993} 1994 1995static int 1996atahpa_unlock(struct cam_device *device, int retry_count, 1997 u_int32_t timeout, union ccb *ccb, 1998 int is48bit, struct ata_set_max_pwd *pwd) 1999{ 2000 int error; 2001 u_int cmd; 2002 u_int8_t protocol; 2003 2004 protocol = AP_PROTO_PIO_OUT; 2005 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; 2006 2007 error = ata_do_cmd(device, 2008 ccb, 2009 retry_count, 2010 /*flags*/CAM_DIR_OUT, 2011 /*protocol*/protocol, 2012 /*ata_flags*/AP_FLAG_CHK_COND, 2013 /*tag_action*/MSG_SIMPLE_Q_TAG, 2014 /*command*/cmd, 2015 /*features*/ATA_HPA_FEAT_UNLOCK, 2016 /*lba*/0, 2017 /*sector_count*/0, 2018 /*data_ptr*/(u_int8_t*)pwd, 2019 /*dxfer_len*/sizeof(struct ata_set_max_pwd), 2020 timeout ? timeout : 1000, 2021 is48bit); 2022 2023 if (error) 2024 return (error); 2025 2026 return atahpa_proc_resp(device, ccb, is48bit, NULL); 2027} 2028 2029static int 2030atahpa_freeze_lock(struct cam_device *device, int retry_count, 2031 u_int32_t timeout, union ccb *ccb, int is48bit) 2032{ 2033 int error; 2034 u_int cmd; 2035 u_int8_t protocol; 2036 2037 protocol = AP_PROTO_NON_DATA; 2038 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; 2039 2040 error = ata_do_cmd(device, 2041 ccb, 2042 retry_count, 2043 /*flags*/CAM_DIR_NONE, 2044 /*protocol*/protocol, 2045 /*ata_flags*/AP_FLAG_CHK_COND, 2046 /*tag_action*/MSG_SIMPLE_Q_TAG, 2047 /*command*/cmd, 2048 /*features*/ATA_HPA_FEAT_FREEZE, 2049 /*lba*/0, 2050 /*sector_count*/0, 2051 /*data_ptr*/NULL, 2052 /*dxfer_len*/0, 2053 timeout ? timeout : 1000, 2054 is48bit); 2055 2056 if (error) 2057 return (error); 2058 2059 return atahpa_proc_resp(device, ccb, is48bit, NULL); 2060} 2061 2062 2063int 2064ata_do_identify(struct cam_device *device, int retry_count, int timeout, 2065 union ccb *ccb, struct ata_params** ident_bufp) 2066{ 2067 struct ata_params *ident_buf; 2068 struct ccb_pathinq cpi; 2069 struct ccb_getdev cgd; 2070 u_int i, error; 2071 int16_t *ptr; 2072 u_int8_t command, retry_command; 2073 2074 if (get_cpi(device, &cpi) != 0) { 2075 warnx("couldn't get CPI"); 2076 return (-1); 2077 } 2078 2079 /* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */ 2080 if (cpi.protocol == PROTO_ATA) { 2081 if (get_cgd(device, &cgd) != 0) { 2082 warnx("couldn't get CGD"); 2083 return (-1); 2084 } 2085 2086 command = (cgd.protocol == PROTO_ATA) ? 2087 ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY; 2088 retry_command = 0; 2089 } else { 2090 /* We don't know which for sure so try both */ 2091 command = ATA_ATA_IDENTIFY; 2092 retry_command = ATA_ATAPI_IDENTIFY; 2093 } 2094 2095 ptr = (uint16_t *)calloc(1, sizeof(struct ata_params)); 2096 if (ptr == NULL) { 2097 warnx("can't calloc memory for identify\n"); 2098 return (1); 2099 } 2100 2101 error = ata_do_28bit_cmd(device, 2102 ccb, 2103 /*retries*/retry_count, 2104 /*flags*/CAM_DIR_IN, 2105 /*protocol*/AP_PROTO_PIO_IN, 2106 /*tag_action*/MSG_SIMPLE_Q_TAG, 2107 /*command*/command, 2108 /*features*/0, 2109 /*lba*/0, 2110 /*sector_count*/(u_int8_t)sizeof(struct ata_params), 2111 /*data_ptr*/(u_int8_t *)ptr, 2112 /*dxfer_len*/sizeof(struct ata_params), 2113 /*timeout*/timeout ? timeout : 30 * 1000, 2114 /*quiet*/1); 2115 2116 if (error != 0) { 2117 if (retry_command == 0) { 2118 free(ptr); 2119 return (1); 2120 } 2121 error = ata_do_28bit_cmd(device, 2122 ccb, 2123 /*retries*/retry_count, 2124 /*flags*/CAM_DIR_IN, 2125 /*protocol*/AP_PROTO_PIO_IN, 2126 /*tag_action*/MSG_SIMPLE_Q_TAG, 2127 /*command*/retry_command, 2128 /*features*/0, 2129 /*lba*/0, 2130 /*sector_count*/(u_int8_t) 2131 sizeof(struct ata_params), 2132 /*data_ptr*/(u_int8_t *)ptr, 2133 /*dxfer_len*/sizeof(struct ata_params), 2134 /*timeout*/timeout ? timeout : 30 * 1000, 2135 /*quiet*/0); 2136 2137 if (error != 0) { 2138 free(ptr); 2139 return (1); 2140 } 2141 } 2142 2143 error = 1; 2144 for (i = 0; i < sizeof(struct ata_params) / 2; i++) { 2145 ptr[i] = le16toh(ptr[i]); 2146 if (ptr[i] != 0) 2147 error = 0; 2148 } 2149 2150 if (arglist & CAM_ARG_VERBOSE) { 2151 fprintf(stdout, "%s%d: Raw identify data:\n", 2152 device->device_name, device->dev_unit_num); 2153 dump_data(ptr, sizeof(struct ata_params)); 2154 } 2155 2156 /* check for invalid (all zero) response */ 2157 if (error != 0) { 2158 warnx("Invalid identify response detected"); 2159 free(ptr); 2160 return (error); 2161 } 2162 2163 ident_buf = (struct ata_params *)ptr; 2164 if (strncmp(ident_buf->model, "FX", 2) && 2165 strncmp(ident_buf->model, "NEC", 3) && 2166 strncmp(ident_buf->model, "Pioneer", 7) && 2167 strncmp(ident_buf->model, "SHARP", 5)) { 2168 ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 2169 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 2170 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 2171 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial)); 2172 } 2173 ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 2174 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 2175 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 2176 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 2177 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 2178 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 2179 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial)); 2180 ata_bpack(ident_buf->media_serial, ident_buf->media_serial, 2181 sizeof(ident_buf->media_serial)); 2182 2183 *ident_bufp = ident_buf; 2184 2185 return (0); 2186} 2187 2188 2189static int 2190ataidentify(struct cam_device *device, int retry_count, int timeout) 2191{ 2192 union ccb *ccb; 2193 struct ata_params *ident_buf; 2194 u_int64_t hpasize; 2195 2196 if ((ccb = cam_getccb(device)) == NULL) { 2197 warnx("couldn't allocate CCB"); 2198 return (1); 2199 } 2200 2201 if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) { 2202 cam_freeccb(ccb); 2203 return (1); 2204 } 2205 2206 if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) { 2207 if (ata_read_native_max(device, retry_count, timeout, ccb, 2208 ident_buf, &hpasize) != 0) { 2209 cam_freeccb(ccb); 2210 return (1); 2211 } 2212 } else { 2213 hpasize = 0; 2214 } 2215 2216 printf("%s%d: ", device->device_name, device->dev_unit_num); 2217 ata_print_ident(ident_buf); 2218 camxferrate(device); 2219 atacapprint(ident_buf); 2220 atahpa_print(ident_buf, hpasize, 0); 2221 2222 free(ident_buf); 2223 cam_freeccb(ccb); 2224 2225 return (0); 2226} 2227#endif /* MINIMALISTIC */ 2228 2229 2230#ifndef MINIMALISTIC 2231enum { 2232 ATA_SECURITY_ACTION_PRINT, 2233 ATA_SECURITY_ACTION_FREEZE, 2234 ATA_SECURITY_ACTION_UNLOCK, 2235 ATA_SECURITY_ACTION_DISABLE, 2236 ATA_SECURITY_ACTION_ERASE, 2237 ATA_SECURITY_ACTION_ERASE_ENHANCED, 2238 ATA_SECURITY_ACTION_SET_PASSWORD 2239}; 2240 2241static void 2242atasecurity_print_time(u_int16_t tw) 2243{ 2244 2245 if (tw == 0) 2246 printf("unspecified"); 2247 else if (tw >= 255) 2248 printf("> 508 min"); 2249 else 2250 printf("%i min", 2 * tw); 2251} 2252 2253static u_int32_t 2254atasecurity_erase_timeout_msecs(u_int16_t timeout) 2255{ 2256 2257 if (timeout == 0) 2258 return 2 * 3600 * 1000; /* default: two hours */ 2259 else if (timeout > 255) 2260 return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */ 2261 2262 return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */ 2263} 2264 2265 2266static void 2267atasecurity_notify(u_int8_t command, struct ata_security_password *pwd) 2268{ 2269 struct ata_cmd cmd; 2270 2271 bzero(&cmd, sizeof(cmd)); 2272 cmd.command = command; 2273 printf("Issuing %s", ata_op_string(&cmd)); 2274 2275 if (pwd != NULL) { 2276 char pass[sizeof(pwd->password)+1]; 2277 2278 /* pwd->password may not be null terminated */ 2279 pass[sizeof(pwd->password)] = '\0'; 2280 strncpy(pass, pwd->password, sizeof(pwd->password)); 2281 printf(" password='%s', user='%s'", 2282 pass, 2283 (pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ? 2284 "master" : "user"); 2285 2286 if (command == ATA_SECURITY_SET_PASSWORD) { 2287 printf(", mode='%s'", 2288 (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ? 2289 "maximum" : "high"); 2290 } 2291 } 2292 2293 printf("\n"); 2294} 2295 2296static int 2297atasecurity_freeze(struct cam_device *device, union ccb *ccb, 2298 int retry_count, u_int32_t timeout, int quiet) 2299{ 2300 2301 if (quiet == 0) 2302 atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL); 2303 2304 return ata_do_28bit_cmd(device, 2305 ccb, 2306 retry_count, 2307 /*flags*/CAM_DIR_NONE, 2308 /*protocol*/AP_PROTO_NON_DATA, 2309 /*tag_action*/MSG_SIMPLE_Q_TAG, 2310 /*command*/ATA_SECURITY_FREEZE_LOCK, 2311 /*features*/0, 2312 /*lba*/0, 2313 /*sector_count*/0, 2314 /*data_ptr*/NULL, 2315 /*dxfer_len*/0, 2316 /*timeout*/timeout, 2317 /*quiet*/0); 2318} 2319 2320static int 2321atasecurity_unlock(struct cam_device *device, union ccb *ccb, 2322 int retry_count, u_int32_t timeout, 2323 struct ata_security_password *pwd, int quiet) 2324{ 2325 2326 if (quiet == 0) 2327 atasecurity_notify(ATA_SECURITY_UNLOCK, pwd); 2328 2329 return ata_do_28bit_cmd(device, 2330 ccb, 2331 retry_count, 2332 /*flags*/CAM_DIR_OUT, 2333 /*protocol*/AP_PROTO_PIO_OUT, 2334 /*tag_action*/MSG_SIMPLE_Q_TAG, 2335 /*command*/ATA_SECURITY_UNLOCK, 2336 /*features*/0, 2337 /*lba*/0, 2338 /*sector_count*/0, 2339 /*data_ptr*/(u_int8_t *)pwd, 2340 /*dxfer_len*/sizeof(*pwd), 2341 /*timeout*/timeout, 2342 /*quiet*/0); 2343} 2344 2345static int 2346atasecurity_disable(struct cam_device *device, union ccb *ccb, 2347 int retry_count, u_int32_t timeout, 2348 struct ata_security_password *pwd, int quiet) 2349{ 2350 2351 if (quiet == 0) 2352 atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd); 2353 return ata_do_28bit_cmd(device, 2354 ccb, 2355 retry_count, 2356 /*flags*/CAM_DIR_OUT, 2357 /*protocol*/AP_PROTO_PIO_OUT, 2358 /*tag_action*/MSG_SIMPLE_Q_TAG, 2359 /*command*/ATA_SECURITY_DISABLE_PASSWORD, 2360 /*features*/0, 2361 /*lba*/0, 2362 /*sector_count*/0, 2363 /*data_ptr*/(u_int8_t *)pwd, 2364 /*dxfer_len*/sizeof(*pwd), 2365 /*timeout*/timeout, 2366 /*quiet*/0); 2367} 2368 2369 2370static int 2371atasecurity_erase_confirm(struct cam_device *device, 2372 struct ata_params* ident_buf) 2373{ 2374 2375 printf("\nYou are about to ERASE ALL DATA from the following" 2376 " device:\n%s%d,%s%d: ", device->device_name, 2377 device->dev_unit_num, device->given_dev_name, 2378 device->given_unit_number); 2379 ata_print_ident(ident_buf); 2380 2381 for(;;) { 2382 char str[50]; 2383 printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) "); 2384 2385 if (fgets(str, sizeof(str), stdin) != NULL) { 2386 if (strncasecmp(str, "yes", 3) == 0) { 2387 return (1); 2388 } else if (strncasecmp(str, "no", 2) == 0) { 2389 return (0); 2390 } else { 2391 printf("Please answer \"yes\" or " 2392 "\"no\"\n"); 2393 } 2394 } 2395 } 2396 2397 /* NOTREACHED */ 2398 return (0); 2399} 2400 2401static int 2402atasecurity_erase(struct cam_device *device, union ccb *ccb, 2403 int retry_count, u_int32_t timeout, 2404 u_int32_t erase_timeout, 2405 struct ata_security_password *pwd, int quiet) 2406{ 2407 int error; 2408 2409 if (quiet == 0) 2410 atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL); 2411 2412 error = ata_do_28bit_cmd(device, 2413 ccb, 2414 retry_count, 2415 /*flags*/CAM_DIR_NONE, 2416 /*protocol*/AP_PROTO_NON_DATA, 2417 /*tag_action*/MSG_SIMPLE_Q_TAG, 2418 /*command*/ATA_SECURITY_ERASE_PREPARE, 2419 /*features*/0, 2420 /*lba*/0, 2421 /*sector_count*/0, 2422 /*data_ptr*/NULL, 2423 /*dxfer_len*/0, 2424 /*timeout*/timeout, 2425 /*quiet*/0); 2426 2427 if (error != 0) 2428 return error; 2429 2430 if (quiet == 0) 2431 atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd); 2432 2433 error = ata_do_28bit_cmd(device, 2434 ccb, 2435 retry_count, 2436 /*flags*/CAM_DIR_OUT, 2437 /*protocol*/AP_PROTO_PIO_OUT, 2438 /*tag_action*/MSG_SIMPLE_Q_TAG, 2439 /*command*/ATA_SECURITY_ERASE_UNIT, 2440 /*features*/0, 2441 /*lba*/0, 2442 /*sector_count*/0, 2443 /*data_ptr*/(u_int8_t *)pwd, 2444 /*dxfer_len*/sizeof(*pwd), 2445 /*timeout*/erase_timeout, 2446 /*quiet*/0); 2447 2448 if (error == 0 && quiet == 0) 2449 printf("\nErase Complete\n"); 2450 2451 return error; 2452} 2453 2454static int 2455atasecurity_set_password(struct cam_device *device, union ccb *ccb, 2456 int retry_count, u_int32_t timeout, 2457 struct ata_security_password *pwd, int quiet) 2458{ 2459 2460 if (quiet == 0) 2461 atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd); 2462 2463 return ata_do_28bit_cmd(device, 2464 ccb, 2465 retry_count, 2466 /*flags*/CAM_DIR_OUT, 2467 /*protocol*/AP_PROTO_PIO_OUT, 2468 /*tag_action*/MSG_SIMPLE_Q_TAG, 2469 /*command*/ATA_SECURITY_SET_PASSWORD, 2470 /*features*/0, 2471 /*lba*/0, 2472 /*sector_count*/0, 2473 /*data_ptr*/(u_int8_t *)pwd, 2474 /*dxfer_len*/sizeof(*pwd), 2475 /*timeout*/timeout, 2476 /*quiet*/0); 2477} 2478 2479static void 2480atasecurity_print(struct ata_params *parm) 2481{ 2482 2483 printf("\nSecurity Option Value\n"); 2484 if (arglist & CAM_ARG_VERBOSE) { 2485 printf("status %04x\n", 2486 parm->security_status); 2487 } 2488 printf("supported %s\n", 2489 parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no"); 2490 if (!(parm->security_status & ATA_SECURITY_SUPPORTED)) 2491 return; 2492 printf("enabled %s\n", 2493 parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no"); 2494 printf("drive locked %s\n", 2495 parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no"); 2496 printf("security config frozen %s\n", 2497 parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no"); 2498 printf("count expired %s\n", 2499 parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no"); 2500 printf("security level %s\n", 2501 parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high"); 2502 printf("enhanced erase supported %s\n", 2503 parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no"); 2504 printf("erase time "); 2505 atasecurity_print_time(parm->erase_time); 2506 printf("\n"); 2507 printf("enhanced erase time "); 2508 atasecurity_print_time(parm->enhanced_erase_time); 2509 printf("\n"); 2510 printf("master password rev %04x%s\n", 2511 parm->master_passwd_revision, 2512 parm->master_passwd_revision == 0x0000 || 2513 parm->master_passwd_revision == 0xFFFF ? " (unsupported)" : ""); 2514} 2515 2516/* 2517 * Validates and copies the password in optarg to the passed buffer. 2518 * If the password in optarg is the same length as the buffer then 2519 * the data will still be copied but no null termination will occur. 2520 */ 2521static int 2522ata_getpwd(u_int8_t *passwd, int max, char opt) 2523{ 2524 int len; 2525 2526 len = strlen(optarg); 2527 if (len > max) { 2528 warnx("-%c password is too long", opt); 2529 return (1); 2530 } else if (len == 0) { 2531 warnx("-%c password is missing", opt); 2532 return (1); 2533 } else if (optarg[0] == '-'){ 2534 warnx("-%c password starts with '-' (generic arg?)", opt); 2535 return (1); 2536 } else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) { 2537 warnx("-%c password conflicts with existing password from -%c", 2538 opt, pwd_opt); 2539 return (1); 2540 } 2541 2542 /* Callers pass in a buffer which does NOT need to be terminated */ 2543 strncpy(passwd, optarg, max); 2544 pwd_opt = opt; 2545 2546 return (0); 2547} 2548 2549enum { 2550 ATA_HPA_ACTION_PRINT, 2551 ATA_HPA_ACTION_SET_MAX, 2552 ATA_HPA_ACTION_SET_PWD, 2553 ATA_HPA_ACTION_LOCK, 2554 ATA_HPA_ACTION_UNLOCK, 2555 ATA_HPA_ACTION_FREEZE_LOCK 2556}; 2557 2558static int 2559atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf, 2560 u_int64_t maxsize, int persist) 2561{ 2562 printf("\nYou are about to configure HPA to limit the user accessible\n" 2563 "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize, 2564 persist ? "persistently" : "temporarily", 2565 device->device_name, device->dev_unit_num, 2566 device->given_dev_name, device->given_unit_number); 2567 ata_print_ident(ident_buf); 2568 2569 for(;;) { 2570 char str[50]; 2571 printf("\nAre you SURE you want to configure HPA? (yes/no) "); 2572 2573 if (NULL != fgets(str, sizeof(str), stdin)) { 2574 if (0 == strncasecmp(str, "yes", 3)) { 2575 return (1); 2576 } else if (0 == strncasecmp(str, "no", 2)) { 2577 return (0); 2578 } else { 2579 printf("Please answer \"yes\" or " 2580 "\"no\"\n"); 2581 } 2582 } 2583 } 2584 2585 /* NOTREACHED */ 2586 return (0); 2587} 2588 2589static int 2590atahpa(struct cam_device *device, int retry_count, int timeout, 2591 int argc, char **argv, char *combinedopt) 2592{ 2593 union ccb *ccb; 2594 struct ata_params *ident_buf; 2595 struct ccb_getdev cgd; 2596 struct ata_set_max_pwd pwd; 2597 int error, confirm, quiet, c, action, actions, setpwd, persist; 2598 int security, is48bit, pwdsize; 2599 u_int64_t hpasize, maxsize; 2600 2601 actions = 0; 2602 setpwd = 0; 2603 confirm = 0; 2604 quiet = 0; 2605 maxsize = 0; 2606 persist = 0; 2607 security = 0; 2608 2609 memset(&pwd, 0, sizeof(pwd)); 2610 2611 /* default action is to print hpa information */ 2612 action = ATA_HPA_ACTION_PRINT; 2613 pwdsize = sizeof(pwd.password); 2614 2615 while ((c = getopt(argc, argv, combinedopt)) != -1) { 2616 switch(c){ 2617 case 's': 2618 action = ATA_HPA_ACTION_SET_MAX; 2619 maxsize = strtoumax(optarg, NULL, 0); 2620 actions++; 2621 break; 2622 2623 case 'p': 2624 if (ata_getpwd(pwd.password, pwdsize, c) != 0) 2625 return (1); 2626 action = ATA_HPA_ACTION_SET_PWD; 2627 security = 1; 2628 actions++; 2629 break; 2630 2631 case 'l': 2632 action = ATA_HPA_ACTION_LOCK; 2633 security = 1; 2634 actions++; 2635 break; 2636 2637 case 'U': 2638 if (ata_getpwd(pwd.password, pwdsize, c) != 0) 2639 return (1); 2640 action = ATA_HPA_ACTION_UNLOCK; 2641 security = 1; 2642 actions++; 2643 break; 2644 2645 case 'f': 2646 action = ATA_HPA_ACTION_FREEZE_LOCK; 2647 security = 1; 2648 actions++; 2649 break; 2650 2651 case 'P': 2652 persist = 1; 2653 break; 2654 2655 case 'y': 2656 confirm++; 2657 break; 2658 2659 case 'q': 2660 quiet++; 2661 break; 2662 } 2663 } 2664 2665 if (actions > 1) { 2666 warnx("too many hpa actions specified"); 2667 return (1); 2668 } 2669 2670 if (get_cgd(device, &cgd) != 0) { 2671 warnx("couldn't get CGD"); 2672 return (1); 2673 } 2674 2675 ccb = cam_getccb(device); 2676 if (ccb == NULL) { 2677 warnx("couldn't allocate CCB"); 2678 return (1); 2679 } 2680 2681 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf); 2682 if (error != 0) { 2683 cam_freeccb(ccb); 2684 return (1); 2685 } 2686 2687 if (quiet == 0) { 2688 printf("%s%d: ", device->device_name, device->dev_unit_num); 2689 ata_print_ident(ident_buf); 2690 camxferrate(device); 2691 } 2692 2693 if (action == ATA_HPA_ACTION_PRINT) { 2694 error = ata_read_native_max(device, retry_count, timeout, ccb, 2695 ident_buf, &hpasize); 2696 if (error == 0) 2697 atahpa_print(ident_buf, hpasize, 1); 2698 2699 cam_freeccb(ccb); 2700 free(ident_buf); 2701 return (error); 2702 } 2703 2704 if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) { 2705 warnx("HPA is not supported by this device"); 2706 cam_freeccb(ccb); 2707 free(ident_buf); 2708 return (1); 2709 } 2710 2711 if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) { 2712 warnx("HPA Security is not supported by this device"); 2713 cam_freeccb(ccb); 2714 free(ident_buf); 2715 return (1); 2716 } 2717 2718 is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48; 2719 2720 /* 2721 * The ATA spec requires: 2722 * 1. Read native max addr is called directly before set max addr 2723 * 2. Read native max addr is NOT called before any other set max call 2724 */ 2725 switch(action) { 2726 case ATA_HPA_ACTION_SET_MAX: 2727 if (confirm == 0 && 2728 atahpa_set_confirm(device, ident_buf, maxsize, 2729 persist) == 0) { 2730 cam_freeccb(ccb); 2731 free(ident_buf); 2732 return (1); 2733 } 2734 2735 error = ata_read_native_max(device, retry_count, timeout, 2736 ccb, ident_buf, &hpasize); 2737 if (error == 0) { 2738 error = atahpa_set_max(device, retry_count, timeout, 2739 ccb, is48bit, maxsize, persist); 2740 if (error == 0) { 2741 /* redo identify to get new lba values */ 2742 error = ata_do_identify(device, retry_count, 2743 timeout, ccb, 2744 &ident_buf); 2745 atahpa_print(ident_buf, hpasize, 1); 2746 } 2747 } 2748 break; 2749 2750 case ATA_HPA_ACTION_SET_PWD: 2751 error = atahpa_password(device, retry_count, timeout, 2752 ccb, is48bit, &pwd); 2753 if (error == 0) 2754 printf("HPA password has been set\n"); 2755 break; 2756 2757 case ATA_HPA_ACTION_LOCK: 2758 error = atahpa_lock(device, retry_count, timeout, 2759 ccb, is48bit); 2760 if (error == 0) 2761 printf("HPA has been locked\n"); 2762 break; 2763 2764 case ATA_HPA_ACTION_UNLOCK: 2765 error = atahpa_unlock(device, retry_count, timeout, 2766 ccb, is48bit, &pwd); 2767 if (error == 0) 2768 printf("HPA has been unlocked\n"); 2769 break; 2770 2771 case ATA_HPA_ACTION_FREEZE_LOCK: 2772 error = atahpa_freeze_lock(device, retry_count, timeout, 2773 ccb, is48bit); 2774 if (error == 0) 2775 printf("HPA has been frozen\n"); 2776 break; 2777 2778 default: 2779 errx(1, "Option currently not supported"); 2780 } 2781 2782 cam_freeccb(ccb); 2783 free(ident_buf); 2784 2785 return (error); 2786} 2787 2788static int 2789atasecurity(struct cam_device *device, int retry_count, int timeout, 2790 int argc, char **argv, char *combinedopt) 2791{ 2792 union ccb *ccb; 2793 struct ata_params *ident_buf; 2794 int error, confirm, quiet, c, action, actions, setpwd; 2795 int security_enabled, erase_timeout, pwdsize; 2796 struct ata_security_password pwd; 2797 2798 actions = 0; 2799 setpwd = 0; 2800 erase_timeout = 0; 2801 confirm = 0; 2802 quiet = 0; 2803 2804 memset(&pwd, 0, sizeof(pwd)); 2805 2806 /* default action is to print security information */ 2807 action = ATA_SECURITY_ACTION_PRINT; 2808 2809 /* user is master by default as its safer that way */ 2810 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER; 2811 pwdsize = sizeof(pwd.password); 2812 2813 while ((c = getopt(argc, argv, combinedopt)) != -1) { 2814 switch(c){ 2815 case 'f': 2816 action = ATA_SECURITY_ACTION_FREEZE; 2817 actions++; 2818 break; 2819 2820 case 'U': 2821 if (strcasecmp(optarg, "user") == 0) { 2822 pwd.ctrl |= ATA_SECURITY_PASSWORD_USER; 2823 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER; 2824 } else if (strcasecmp(optarg, "master") == 0) { 2825 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER; 2826 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER; 2827 } else { 2828 warnx("-U argument '%s' is invalid (must be " 2829 "'user' or 'master')", optarg); 2830 return (1); 2831 } 2832 break; 2833 2834 case 'l': 2835 if (strcasecmp(optarg, "high") == 0) { 2836 pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH; 2837 pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM; 2838 } else if (strcasecmp(optarg, "maximum") == 0) { 2839 pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM; 2840 pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH; 2841 } else { 2842 warnx("-l argument '%s' is unknown (must be " 2843 "'high' or 'maximum')", optarg); 2844 return (1); 2845 } 2846 break; 2847 2848 case 'k': 2849 if (ata_getpwd(pwd.password, pwdsize, c) != 0) 2850 return (1); 2851 action = ATA_SECURITY_ACTION_UNLOCK; 2852 actions++; 2853 break; 2854 2855 case 'd': 2856 if (ata_getpwd(pwd.password, pwdsize, c) != 0) 2857 return (1); 2858 action = ATA_SECURITY_ACTION_DISABLE; 2859 actions++; 2860 break; 2861 2862 case 'e': 2863 if (ata_getpwd(pwd.password, pwdsize, c) != 0) 2864 return (1); 2865 action = ATA_SECURITY_ACTION_ERASE; 2866 actions++; 2867 break; 2868 2869 case 'h': 2870 if (ata_getpwd(pwd.password, pwdsize, c) != 0) 2871 return (1); 2872 pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED; 2873 action = ATA_SECURITY_ACTION_ERASE_ENHANCED; 2874 actions++; 2875 break; 2876 2877 case 's': 2878 if (ata_getpwd(pwd.password, pwdsize, c) != 0) 2879 return (1); 2880 setpwd = 1; 2881 if (action == ATA_SECURITY_ACTION_PRINT) 2882 action = ATA_SECURITY_ACTION_SET_PASSWORD; 2883 /* 2884 * Don't increment action as this can be combined 2885 * with other actions. 2886 */ 2887 break; 2888 2889 case 'y': 2890 confirm++; 2891 break; 2892 2893 case 'q': 2894 quiet++; 2895 break; 2896 2897 case 'T': 2898 erase_timeout = atoi(optarg) * 1000; 2899 break; 2900 } 2901 } 2902 2903 if (actions > 1) { 2904 warnx("too many security actions specified"); 2905 return (1); 2906 } 2907 2908 if ((ccb = cam_getccb(device)) == NULL) { 2909 warnx("couldn't allocate CCB"); 2910 return (1); 2911 } 2912 2913 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf); 2914 if (error != 0) { 2915 cam_freeccb(ccb); 2916 return (1); 2917 } 2918 2919 if (quiet == 0) { 2920 printf("%s%d: ", device->device_name, device->dev_unit_num); 2921 ata_print_ident(ident_buf); 2922 camxferrate(device); 2923 } 2924 2925 if (action == ATA_SECURITY_ACTION_PRINT) { 2926 atasecurity_print(ident_buf); 2927 free(ident_buf); 2928 cam_freeccb(ccb); 2929 return (0); 2930 } 2931 2932 if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) { 2933 warnx("Security not supported"); 2934 free(ident_buf); 2935 cam_freeccb(ccb); 2936 return (1); 2937 } 2938 2939 /* default timeout 15 seconds the same as linux hdparm */ 2940 timeout = timeout ? timeout : 15 * 1000; 2941 2942 security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED; 2943 2944 /* first set the password if requested */ 2945 if (setpwd == 1) { 2946 /* confirm we can erase before setting the password if erasing */ 2947 if (confirm == 0 && 2948 (action == ATA_SECURITY_ACTION_ERASE_ENHANCED || 2949 action == ATA_SECURITY_ACTION_ERASE) && 2950 atasecurity_erase_confirm(device, ident_buf) == 0) { 2951 cam_freeccb(ccb); 2952 free(ident_buf); 2953 return (error); 2954 } 2955 2956 if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) { 2957 pwd.revision = ident_buf->master_passwd_revision; 2958 if (pwd.revision != 0 && pwd.revision != 0xfff && 2959 --pwd.revision == 0) { 2960 pwd.revision = 0xfffe; 2961 } 2962 } 2963 error = atasecurity_set_password(device, ccb, retry_count, 2964 timeout, &pwd, quiet); 2965 if (error != 0) { 2966 cam_freeccb(ccb); 2967 free(ident_buf); 2968 return (error); 2969 } 2970 security_enabled = 1; 2971 } 2972 2973 switch(action) { 2974 case ATA_SECURITY_ACTION_FREEZE: 2975 error = atasecurity_freeze(device, ccb, retry_count, 2976 timeout, quiet); 2977 break; 2978 2979 case ATA_SECURITY_ACTION_UNLOCK: 2980 if (security_enabled) { 2981 if (ident_buf->security_status & ATA_SECURITY_LOCKED) { 2982 error = atasecurity_unlock(device, ccb, 2983 retry_count, timeout, &pwd, quiet); 2984 } else { 2985 warnx("Can't unlock, drive is not locked"); 2986 error = 1; 2987 } 2988 } else { 2989 warnx("Can't unlock, security is disabled"); 2990 error = 1; 2991 } 2992 break; 2993 2994 case ATA_SECURITY_ACTION_DISABLE: 2995 if (security_enabled) { 2996 /* First unlock the drive if its locked */ 2997 if (ident_buf->security_status & ATA_SECURITY_LOCKED) { 2998 error = atasecurity_unlock(device, ccb, 2999 retry_count, 3000 timeout, 3001 &pwd, 3002 quiet); 3003 } 3004 3005 if (error == 0) { 3006 error = atasecurity_disable(device, 3007 ccb, 3008 retry_count, 3009 timeout, 3010 &pwd, 3011 quiet); 3012 } 3013 } else { 3014 warnx("Can't disable security (already disabled)"); 3015 error = 1; 3016 } 3017 break; 3018 3019 case ATA_SECURITY_ACTION_ERASE: 3020 if (security_enabled) { 3021 if (erase_timeout == 0) { 3022 erase_timeout = atasecurity_erase_timeout_msecs( 3023 ident_buf->erase_time); 3024 } 3025 3026 error = atasecurity_erase(device, ccb, retry_count, 3027 timeout, erase_timeout, &pwd, 3028 quiet); 3029 } else { 3030 warnx("Can't secure erase (security is disabled)"); 3031 error = 1; 3032 } 3033 break; 3034 3035 case ATA_SECURITY_ACTION_ERASE_ENHANCED: 3036 if (security_enabled) { 3037 if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) { 3038 if (erase_timeout == 0) { 3039 erase_timeout = 3040 atasecurity_erase_timeout_msecs( 3041 ident_buf->enhanced_erase_time); 3042 } 3043 3044 error = atasecurity_erase(device, ccb, 3045 retry_count, timeout, 3046 erase_timeout, &pwd, 3047 quiet); 3048 } else { 3049 warnx("Enhanced erase is not supported"); 3050 error = 1; 3051 } 3052 } else { 3053 warnx("Can't secure erase (enhanced), " 3054 "(security is disabled)"); 3055 error = 1; 3056 } 3057 break; 3058 } 3059 3060 cam_freeccb(ccb); 3061 free(ident_buf); 3062 3063 return (error); 3064} 3065#endif /* MINIMALISTIC */ 3066 3067/* 3068 * Parse out a bus, or a bus, target and lun in the following 3069 * format: 3070 * bus 3071 * bus:target 3072 * bus:target:lun 3073 * 3074 * Returns the number of parsed components, or 0. 3075 */ 3076static int 3077parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun, 3078 cam_argmask *arglst) 3079{ 3080 char *tmpstr; 3081 int convs = 0; 3082 3083 while (isspace(*tstr) && (*tstr != '\0')) 3084 tstr++; 3085 3086 tmpstr = (char *)strtok(tstr, ":"); 3087 if ((tmpstr != NULL) && (*tmpstr != '\0')) { 3088 *bus = strtol(tmpstr, NULL, 0); 3089 *arglst |= CAM_ARG_BUS; 3090 convs++; 3091 tmpstr = (char *)strtok(NULL, ":"); 3092 if ((tmpstr != NULL) && (*tmpstr != '\0')) { 3093 *target = strtol(tmpstr, NULL, 0); 3094 *arglst |= CAM_ARG_TARGET; 3095 convs++; 3096 tmpstr = (char *)strtok(NULL, ":"); 3097 if ((tmpstr != NULL) && (*tmpstr != '\0')) { 3098 *lun = strtol(tmpstr, NULL, 0); 3099 *arglst |= CAM_ARG_LUN; 3100 convs++; 3101 } 3102 } 3103 } 3104 3105 return convs; 3106} 3107 3108static int 3109dorescan_or_reset(int argc, char **argv, int rescan) 3110{ 3111 static const char must[] = 3112 "you must specify \"all\", a bus, or a bus:target:lun to %s"; 3113 int rv, error = 0; 3114 path_id_t bus = CAM_BUS_WILDCARD; 3115 target_id_t target = CAM_TARGET_WILDCARD; 3116 lun_id_t lun = CAM_LUN_WILDCARD; 3117 char *tstr; 3118 3119 if (argc < 3) { 3120 warnx(must, rescan? "rescan" : "reset"); 3121 return(1); 3122 } 3123 3124 tstr = argv[optind]; 3125 while (isspace(*tstr) && (*tstr != '\0')) 3126 tstr++; 3127 if (strncasecmp(tstr, "all", strlen("all")) == 0) 3128 arglist |= CAM_ARG_BUS; 3129 else if (isdigit(*tstr)) { 3130 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist); 3131 if (rv != 1 && rv != 3) { 3132 warnx(must, rescan? "rescan" : "reset"); 3133 return(1); 3134 } 3135 } else { 3136 char name[30]; 3137 int unit; 3138 int fd = -1; 3139 union ccb ccb; 3140 3141 /* 3142 * Note that resetting or rescanning a device used to 3143 * require a bus or bus:target:lun. This is because the 3144 * device in question may not exist and you're trying to 3145 * get the controller to rescan to find it. It may also be 3146 * because the device is hung / unresponsive, and opening 3147 * an unresponsive device is not desireable. 3148 * 3149 * It can be more convenient to reference a device by 3150 * peripheral name and unit number, though, and it is 3151 * possible to get the bus:target:lun for devices that 3152 * currently exist in the EDT. So this can work for 3153 * devices that we want to reset, or devices that exist 3154 * that we want to rescan, but not devices that do not 3155 * exist yet. 3156 * 3157 * So, we are careful here to look up the bus/target/lun 3158 * for the device the user wants to operate on, specified 3159 * by peripheral instance (e.g. da0, pass32) without 3160 * actually opening that device. The process is similar to 3161 * what cam_lookup_pass() does, except that we don't 3162 * actually open the passthrough driver instance in the end. 3163 */ 3164 3165 if (cam_get_device(tstr, name, sizeof(name), &unit) == -1) { 3166 warnx("%s", cam_errbuf); 3167 error = 1; 3168 goto bailout; 3169 } 3170 3171 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { 3172 warn("Unable to open %s", XPT_DEVICE); 3173 error = 1; 3174 goto bailout; 3175 } 3176 3177 bzero(&ccb, sizeof(ccb)); 3178 3179 /* 3180 * The function code isn't strictly necessary for the 3181 * GETPASSTHRU ioctl. 3182 */ 3183 ccb.ccb_h.func_code = XPT_GDEVLIST; 3184 3185 /* 3186 * These two are necessary for the GETPASSTHRU ioctl to 3187 * work. 3188 */ 3189 strlcpy(ccb.cgdl.periph_name, name, 3190 sizeof(ccb.cgdl.periph_name)); 3191 ccb.cgdl.unit_number = unit; 3192 3193 /* 3194 * Attempt to get the passthrough device. This ioctl will 3195 * fail if the device name is null, if the device doesn't 3196 * exist, or if the passthrough driver isn't in the kernel. 3197 */ 3198 if (ioctl(fd, CAMGETPASSTHRU, &ccb) == -1) { 3199 warn("Unable to find bus:target:lun for device %s%d", 3200 name, unit); 3201 error = 1; 3202 close(fd); 3203 goto bailout; 3204 } 3205 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3206 const struct cam_status_entry *entry; 3207 3208 entry = cam_fetch_status_entry(ccb.ccb_h.status); 3209 warnx("Unable to find bus:target_lun for device %s%d, " 3210 "CAM status: %s (%#x)", name, unit, 3211 entry ? entry->status_text : "Unknown", 3212 ccb.ccb_h.status); 3213 error = 1; 3214 close(fd); 3215 goto bailout; 3216 } 3217 3218 /* 3219 * The kernel fills in the bus/target/lun. We don't 3220 * need the passthrough device name and unit number since 3221 * we aren't going to open it. 3222 */ 3223 bus = ccb.ccb_h.path_id; 3224 target = ccb.ccb_h.target_id; 3225 lun = ccb.ccb_h.target_lun; 3226 3227 arglist |= CAM_ARG_BUS | CAM_ARG_TARGET | CAM_ARG_LUN; 3228 3229 close(fd); 3230 } 3231 3232 if ((arglist & CAM_ARG_BUS) 3233 && (arglist & CAM_ARG_TARGET) 3234 && (arglist & CAM_ARG_LUN)) 3235 error = scanlun_or_reset_dev(bus, target, lun, rescan); 3236 else 3237 error = rescan_or_reset_bus(bus, rescan); 3238 3239bailout: 3240 3241 return(error); 3242} 3243 3244static int 3245rescan_or_reset_bus(path_id_t bus, int rescan) 3246{ 3247 union ccb *ccb = NULL, *matchccb = NULL; 3248 int fd = -1, retval; 3249 int bufsize; 3250 3251 retval = 0; 3252 3253 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) { 3254 warnx("error opening transport layer device %s", XPT_DEVICE); 3255 warn("%s", XPT_DEVICE); 3256 return(1); 3257 } 3258 3259 ccb = malloc(sizeof(*ccb)); 3260 if (ccb == NULL) { 3261 warn("failed to allocate CCB"); 3262 retval = 1; 3263 goto bailout; 3264 } 3265 bzero(ccb, sizeof(*ccb)); 3266 3267 if (bus != CAM_BUS_WILDCARD) { 3268 ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS; 3269 ccb->ccb_h.path_id = bus; 3270 ccb->ccb_h.target_id = CAM_TARGET_WILDCARD; 3271 ccb->ccb_h.target_lun = CAM_LUN_WILDCARD; 3272 ccb->crcn.flags = CAM_FLAG_NONE; 3273 3274 /* run this at a low priority */ 3275 ccb->ccb_h.pinfo.priority = 5; 3276 3277 if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) { 3278 warn("CAMIOCOMMAND ioctl failed"); 3279 retval = 1; 3280 goto bailout; 3281 } 3282 3283 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 3284 fprintf(stdout, "%s of bus %d was successful\n", 3285 rescan ? "Re-scan" : "Reset", bus); 3286 } else { 3287 fprintf(stdout, "%s of bus %d returned error %#x\n", 3288 rescan ? "Re-scan" : "Reset", bus, 3289 ccb->ccb_h.status & CAM_STATUS_MASK); 3290 retval = 1; 3291 } 3292 3293 goto bailout; 3294 } 3295 3296 3297 /* 3298 * The right way to handle this is to modify the xpt so that it can 3299 * handle a wildcarded bus in a rescan or reset CCB. At the moment 3300 * that isn't implemented, so instead we enumerate the busses and 3301 * send the rescan or reset to those busses in the case where the 3302 * given bus is -1 (wildcard). We don't send a rescan or reset 3303 * to the xpt bus; sending a rescan to the xpt bus is effectively a 3304 * no-op, sending a rescan to the xpt bus would result in a status of 3305 * CAM_REQ_INVALID. 3306 */ 3307 matchccb = malloc(sizeof(*matchccb)); 3308 if (matchccb == NULL) { 3309 warn("failed to allocate CCB"); 3310 retval = 1; 3311 goto bailout; 3312 } 3313 bzero(matchccb, sizeof(*matchccb)); 3314 matchccb->ccb_h.func_code = XPT_DEV_MATCH; 3315 matchccb->ccb_h.path_id = CAM_BUS_WILDCARD; 3316 bufsize = sizeof(struct dev_match_result) * 20; 3317 matchccb->cdm.match_buf_len = bufsize; 3318 matchccb->cdm.matches=(struct dev_match_result *)malloc(bufsize); 3319 if (matchccb->cdm.matches == NULL) { 3320 warnx("can't malloc memory for matches"); 3321 retval = 1; 3322 goto bailout; 3323 } 3324 matchccb->cdm.num_matches = 0; 3325 3326 matchccb->cdm.num_patterns = 1; 3327 matchccb->cdm.pattern_buf_len = sizeof(struct dev_match_pattern); 3328 3329 matchccb->cdm.patterns = (struct dev_match_pattern *)malloc( 3330 matchccb->cdm.pattern_buf_len); 3331 if (matchccb->cdm.patterns == NULL) { 3332 warnx("can't malloc memory for patterns"); 3333 retval = 1; 3334 goto bailout; 3335 } 3336 matchccb->cdm.patterns[0].type = DEV_MATCH_BUS; 3337 matchccb->cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY; 3338 3339 do { 3340 unsigned int i; 3341 3342 if (ioctl(fd, CAMIOCOMMAND, matchccb) == -1) { 3343 warn("CAMIOCOMMAND ioctl failed"); 3344 retval = 1; 3345 goto bailout; 3346 } 3347 3348 if ((matchccb->ccb_h.status != CAM_REQ_CMP) 3349 || ((matchccb->cdm.status != CAM_DEV_MATCH_LAST) 3350 && (matchccb->cdm.status != CAM_DEV_MATCH_MORE))) { 3351 warnx("got CAM error %#x, CDM error %d\n", 3352 matchccb->ccb_h.status, matchccb->cdm.status); 3353 retval = 1; 3354 goto bailout; 3355 } 3356 3357 for (i = 0; i < matchccb->cdm.num_matches; i++) { 3358 struct bus_match_result *bus_result; 3359 3360 /* This shouldn't happen. */ 3361 if (matchccb->cdm.matches[i].type != DEV_MATCH_BUS) 3362 continue; 3363 3364 bus_result =&matchccb->cdm.matches[i].result.bus_result; 3365 3366 /* 3367 * We don't want to rescan or reset the xpt bus. 3368 * See above. 3369 */ 3370 if (bus_result->path_id == CAM_XPT_PATH_ID) 3371 continue; 3372 3373 ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS : 3374 XPT_RESET_BUS; 3375 ccb->ccb_h.path_id = bus_result->path_id; 3376 ccb->ccb_h.target_id = CAM_TARGET_WILDCARD; 3377 ccb->ccb_h.target_lun = CAM_LUN_WILDCARD; 3378 ccb->crcn.flags = CAM_FLAG_NONE; 3379 3380 /* run this at a low priority */ 3381 ccb->ccb_h.pinfo.priority = 5; 3382 3383 if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) { 3384 warn("CAMIOCOMMAND ioctl failed"); 3385 retval = 1; 3386 goto bailout; 3387 } 3388 3389 if ((ccb->ccb_h.status & CAM_STATUS_MASK)==CAM_REQ_CMP){ 3390 fprintf(stdout, "%s of bus %d was successful\n", 3391 rescan? "Re-scan" : "Reset", 3392 bus_result->path_id); 3393 } else { 3394 /* 3395 * Don't bail out just yet, maybe the other 3396 * rescan or reset commands will complete 3397 * successfully. 3398 */ 3399 fprintf(stderr, "%s of bus %d returned error " 3400 "%#x\n", rescan? "Re-scan" : "Reset", 3401 bus_result->path_id, 3402 ccb->ccb_h.status & CAM_STATUS_MASK); 3403 retval = 1; 3404 } 3405 } 3406 } while ((matchccb->ccb_h.status == CAM_REQ_CMP) 3407 && (matchccb->cdm.status == CAM_DEV_MATCH_MORE)); 3408 3409bailout: 3410 3411 if (fd != -1) 3412 close(fd); 3413 3414 if (matchccb != NULL) { 3415 free(matchccb->cdm.patterns); 3416 free(matchccb->cdm.matches); 3417 free(matchccb); 3418 } 3419 free(ccb); 3420 3421 return(retval); 3422} 3423 3424static int 3425scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan) 3426{ 3427 union ccb ccb; 3428 struct cam_device *device; 3429 int fd; 3430 3431 device = NULL; 3432 3433 if (bus == CAM_BUS_WILDCARD) { 3434 warnx("invalid bus number %d", bus); 3435 return(1); 3436 } 3437 3438 if (target == CAM_TARGET_WILDCARD) { 3439 warnx("invalid target number %d", target); 3440 return(1); 3441 } 3442 3443 if (lun == CAM_LUN_WILDCARD) { 3444 warnx("invalid lun number %jx", (uintmax_t)lun); 3445 return(1); 3446 } 3447 3448 fd = -1; 3449 3450 bzero(&ccb, sizeof(union ccb)); 3451 3452 if (scan) { 3453 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) { 3454 warnx("error opening transport layer device %s\n", 3455 XPT_DEVICE); 3456 warn("%s", XPT_DEVICE); 3457 return(1); 3458 } 3459 } else { 3460 device = cam_open_btl(bus, target, lun, O_RDWR, NULL); 3461 if (device == NULL) { 3462 warnx("%s", cam_errbuf); 3463 return(1); 3464 } 3465 } 3466 3467 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV; 3468 ccb.ccb_h.path_id = bus; 3469 ccb.ccb_h.target_id = target; 3470 ccb.ccb_h.target_lun = lun; 3471 ccb.ccb_h.timeout = 5000; 3472 ccb.crcn.flags = CAM_FLAG_NONE; 3473 3474 /* run this at a low priority */ 3475 ccb.ccb_h.pinfo.priority = 5; 3476 3477 if (scan) { 3478 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) { 3479 warn("CAMIOCOMMAND ioctl failed"); 3480 close(fd); 3481 return(1); 3482 } 3483 } else { 3484 if (cam_send_ccb(device, &ccb) < 0) { 3485 warn("error sending XPT_RESET_DEV CCB"); 3486 cam_close_device(device); 3487 return(1); 3488 } 3489 } 3490 3491 if (scan) 3492 close(fd); 3493 else 3494 cam_close_device(device); 3495 3496 /* 3497 * An error code of CAM_BDR_SENT is normal for a BDR request. 3498 */ 3499 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 3500 || ((!scan) 3501 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) { 3502 fprintf(stdout, "%s of %d:%d:%jx was successful\n", 3503 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun); 3504 return(0); 3505 } else { 3506 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n", 3507 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun, 3508 ccb.ccb_h.status & CAM_STATUS_MASK); 3509 return(1); 3510 } 3511} 3512 3513#ifndef MINIMALISTIC 3514 3515static struct scsi_nv defect_list_type_map[] = { 3516 { "block", SRDD10_BLOCK_FORMAT }, 3517 { "extbfi", SRDD10_EXT_BFI_FORMAT }, 3518 { "extphys", SRDD10_EXT_PHYS_FORMAT }, 3519 { "longblock", SRDD10_LONG_BLOCK_FORMAT }, 3520 { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT }, 3521 { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT } 3522}; 3523 3524static int 3525readdefects(struct cam_device *device, int argc, char **argv, 3526 char *combinedopt, int task_attr, int retry_count, int timeout) 3527{ 3528 union ccb *ccb = NULL; 3529 struct scsi_read_defect_data_hdr_10 *hdr10 = NULL; 3530 struct scsi_read_defect_data_hdr_12 *hdr12 = NULL; 3531 size_t hdr_size = 0, entry_size = 0; 3532 int use_12byte = 0; 3533 int hex_format = 0; 3534 u_int8_t *defect_list = NULL; 3535 u_int8_t list_format = 0; 3536 int list_type_set = 0; 3537 u_int32_t dlist_length = 0; 3538 u_int32_t returned_length = 0, valid_len = 0; 3539 u_int32_t num_returned = 0, num_valid = 0; 3540 u_int32_t max_possible_size = 0, hdr_max = 0; 3541 u_int32_t starting_offset = 0; 3542 u_int8_t returned_format, returned_type; 3543 unsigned int i; 3544 int summary = 0, quiet = 0; 3545 int c, error = 0; 3546 int lists_specified = 0; 3547 int get_length = 1, first_pass = 1; 3548 int mads = 0; 3549 3550 while ((c = getopt(argc, argv, combinedopt)) != -1) { 3551 switch(c){ 3552 case 'f': 3553 { 3554 scsi_nv_status status; 3555 int entry_num = 0; 3556 3557 status = scsi_get_nv(defect_list_type_map, 3558 sizeof(defect_list_type_map) / 3559 sizeof(defect_list_type_map[0]), optarg, 3560 &entry_num, SCSI_NV_FLAG_IG_CASE); 3561 3562 if (status == SCSI_NV_FOUND) { 3563 list_format = defect_list_type_map[ 3564 entry_num].value; 3565 list_type_set = 1; 3566 } else { 3567 warnx("%s: %s %s option %s", __func__, 3568 (status == SCSI_NV_AMBIGUOUS) ? 3569 "ambiguous" : "invalid", "defect list type", 3570 optarg); 3571 error = 1; 3572 goto defect_bailout; 3573 } 3574 break; 3575 } 3576 case 'G': 3577 arglist |= CAM_ARG_GLIST; 3578 break; 3579 case 'P': 3580 arglist |= CAM_ARG_PLIST; 3581 break; 3582 case 'q': 3583 quiet = 1; 3584 break; 3585 case 's': 3586 summary = 1; 3587 break; 3588 case 'S': { 3589 char *endptr; 3590 3591 starting_offset = strtoul(optarg, &endptr, 0); 3592 if (*endptr != '\0') { 3593 error = 1; 3594 warnx("invalid starting offset %s", optarg); 3595 goto defect_bailout; 3596 } 3597 break; 3598 } 3599 case 'X': 3600 hex_format = 1; 3601 break; 3602 default: 3603 break; 3604 } 3605 } 3606 3607 if (list_type_set == 0) { 3608 error = 1; 3609 warnx("no defect list format specified"); 3610 goto defect_bailout; 3611 } 3612 3613 if (arglist & CAM_ARG_PLIST) { 3614 list_format |= SRDD10_PLIST; 3615 lists_specified++; 3616 } 3617 3618 if (arglist & CAM_ARG_GLIST) { 3619 list_format |= SRDD10_GLIST; 3620 lists_specified++; 3621 } 3622 3623 /* 3624 * This implies a summary, and was the previous behavior. 3625 */ 3626 if (lists_specified == 0) 3627 summary = 1; 3628 3629 ccb = cam_getccb(device); 3630 3631retry_12byte: 3632 3633 /* 3634 * We start off asking for just the header to determine how much 3635 * defect data is available. Some Hitachi drives return an error 3636 * if you ask for more data than the drive has. Once we know the 3637 * length, we retry the command with the returned length. 3638 */ 3639 if (use_12byte == 0) 3640 dlist_length = sizeof(*hdr10); 3641 else 3642 dlist_length = sizeof(*hdr12); 3643 3644retry: 3645 if (defect_list != NULL) { 3646 free(defect_list); 3647 defect_list = NULL; 3648 } 3649 defect_list = malloc(dlist_length); 3650 if (defect_list == NULL) { 3651 warnx("can't malloc memory for defect list"); 3652 error = 1; 3653 goto defect_bailout; 3654 } 3655 3656next_batch: 3657 bzero(defect_list, dlist_length); 3658 3659 /* 3660 * cam_getccb() zeros the CCB header only. So we need to zero the 3661 * payload portion of the ccb. 3662 */ 3663 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 3664 3665 scsi_read_defects(&ccb->csio, 3666 /*retries*/ retry_count, 3667 /*cbfcnp*/ NULL, 3668 /*tag_action*/ task_attr, 3669 /*list_format*/ list_format, 3670 /*addr_desc_index*/ starting_offset, 3671 /*data_ptr*/ defect_list, 3672 /*dxfer_len*/ dlist_length, 3673 /*minimum_cmd_size*/ use_12byte ? 12 : 0, 3674 /*sense_len*/ SSD_FULL_SIZE, 3675 /*timeout*/ timeout ? timeout : 5000); 3676 3677 /* Disable freezing the device queue */ 3678 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 3679 3680 if (cam_send_ccb(device, ccb) < 0) { 3681 perror("error reading defect list"); 3682 3683 if (arglist & CAM_ARG_VERBOSE) { 3684 cam_error_print(device, ccb, CAM_ESF_ALL, 3685 CAM_EPF_ALL, stderr); 3686 } 3687 3688 error = 1; 3689 goto defect_bailout; 3690 } 3691 3692 valid_len = ccb->csio.dxfer_len - ccb->csio.resid; 3693 3694 if (use_12byte == 0) { 3695 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list; 3696 hdr_size = sizeof(*hdr10); 3697 hdr_max = SRDDH10_MAX_LENGTH; 3698 3699 if (valid_len >= hdr_size) { 3700 returned_length = scsi_2btoul(hdr10->length); 3701 returned_format = hdr10->format; 3702 } else { 3703 returned_length = 0; 3704 returned_format = 0; 3705 } 3706 } else { 3707 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list; 3708 hdr_size = sizeof(*hdr12); 3709 hdr_max = SRDDH12_MAX_LENGTH; 3710 3711 if (valid_len >= hdr_size) { 3712 returned_length = scsi_4btoul(hdr12->length); 3713 returned_format = hdr12->format; 3714 } else { 3715 returned_length = 0; 3716 returned_format = 0; 3717 } 3718 } 3719 3720 returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK; 3721 switch (returned_type) { 3722 case SRDD10_BLOCK_FORMAT: 3723 entry_size = sizeof(struct scsi_defect_desc_block); 3724 break; 3725 case SRDD10_LONG_BLOCK_FORMAT: 3726 entry_size = sizeof(struct scsi_defect_desc_long_block); 3727 break; 3728 case SRDD10_EXT_PHYS_FORMAT: 3729 case SRDD10_PHYSICAL_SECTOR_FORMAT: 3730 entry_size = sizeof(struct scsi_defect_desc_phys_sector); 3731 break; 3732 case SRDD10_EXT_BFI_FORMAT: 3733 case SRDD10_BYTES_FROM_INDEX_FORMAT: 3734 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index); 3735 break; 3736 default: 3737 warnx("Unknown defect format 0x%x\n", returned_type); 3738 error = 1; 3739 goto defect_bailout; 3740 break; 3741 } 3742 3743 max_possible_size = (hdr_max / entry_size) * entry_size; 3744 num_returned = returned_length / entry_size; 3745 num_valid = min(returned_length, valid_len - hdr_size); 3746 num_valid /= entry_size; 3747 3748 if (get_length != 0) { 3749 get_length = 0; 3750 3751 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 3752 CAM_SCSI_STATUS_ERROR) { 3753 struct scsi_sense_data *sense; 3754 int error_code, sense_key, asc, ascq; 3755 3756 sense = &ccb->csio.sense_data; 3757 scsi_extract_sense_len(sense, ccb->csio.sense_len - 3758 ccb->csio.sense_resid, &error_code, &sense_key, 3759 &asc, &ascq, /*show_errors*/ 1); 3760 3761 /* 3762 * If the drive is reporting that it just doesn't 3763 * support the defect list format, go ahead and use 3764 * the length it reported. Otherwise, the length 3765 * may not be valid, so use the maximum. 3766 */ 3767 if ((sense_key == SSD_KEY_RECOVERED_ERROR) 3768 && (asc == 0x1c) && (ascq == 0x00) 3769 && (returned_length > 0)) { 3770 if ((use_12byte == 0) 3771 && (returned_length >= max_possible_size)) { 3772 get_length = 1; 3773 use_12byte = 1; 3774 goto retry_12byte; 3775 } 3776 dlist_length = returned_length + hdr_size; 3777 } else if ((sense_key == SSD_KEY_RECOVERED_ERROR) 3778 && (asc == 0x1f) && (ascq == 0x00) 3779 && (returned_length > 0)) { 3780 /* Partial defect list transfer */ 3781 /* 3782 * Hitachi drives return this error 3783 * along with a partial defect list if they 3784 * have more defects than the 10 byte 3785 * command can support. Retry with the 12 3786 * byte command. 3787 */ 3788 if (use_12byte == 0) { 3789 get_length = 1; 3790 use_12byte = 1; 3791 goto retry_12byte; 3792 } 3793 dlist_length = returned_length + hdr_size; 3794 } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST) 3795 && (asc == 0x24) && (ascq == 0x00)) { 3796 /* Invalid field in CDB */ 3797 /* 3798 * SBC-3 says that if the drive has more 3799 * defects than can be reported with the 3800 * 10 byte command, it should return this 3801 * error and no data. Retry with the 12 3802 * byte command. 3803 */ 3804 if (use_12byte == 0) { 3805 get_length = 1; 3806 use_12byte = 1; 3807 goto retry_12byte; 3808 } 3809 dlist_length = returned_length + hdr_size; 3810 } else { 3811 /* 3812 * If we got a SCSI error and no valid length, 3813 * just use the 10 byte maximum. The 12 3814 * byte maximum is too large. 3815 */ 3816 if (returned_length == 0) 3817 dlist_length = SRDD10_MAX_LENGTH; 3818 else { 3819 if ((use_12byte == 0) 3820 && (returned_length >= 3821 max_possible_size)) { 3822 get_length = 1; 3823 use_12byte = 1; 3824 goto retry_12byte; 3825 } 3826 dlist_length = returned_length + 3827 hdr_size; 3828 } 3829 } 3830 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != 3831 CAM_REQ_CMP){ 3832 error = 1; 3833 warnx("Error reading defect header"); 3834 if (arglist & CAM_ARG_VERBOSE) 3835 cam_error_print(device, ccb, CAM_ESF_ALL, 3836 CAM_EPF_ALL, stderr); 3837 goto defect_bailout; 3838 } else { 3839 if ((use_12byte == 0) 3840 && (returned_length >= max_possible_size)) { 3841 get_length = 1; 3842 use_12byte = 1; 3843 goto retry_12byte; 3844 } 3845 dlist_length = returned_length + hdr_size; 3846 } 3847 if (summary != 0) { 3848 fprintf(stdout, "%u", num_returned); 3849 if (quiet == 0) { 3850 fprintf(stdout, " defect%s", 3851 (num_returned != 1) ? "s" : ""); 3852 } 3853 fprintf(stdout, "\n"); 3854 3855 goto defect_bailout; 3856 } 3857 3858 /* 3859 * We always limit the list length to the 10-byte maximum 3860 * length (0xffff). The reason is that some controllers 3861 * can't handle larger I/Os, and we can transfer the entire 3862 * 10 byte list in one shot. For drives that support the 12 3863 * byte read defects command, we'll step through the list 3864 * by specifying a starting offset. For drives that don't 3865 * support the 12 byte command's starting offset, we'll 3866 * just display the first 64K. 3867 */ 3868 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH); 3869 3870 goto retry; 3871 } 3872 3873 3874 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) 3875 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) 3876 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { 3877 struct scsi_sense_data *sense; 3878 int error_code, sense_key, asc, ascq; 3879 3880 sense = &ccb->csio.sense_data; 3881 scsi_extract_sense_len(sense, ccb->csio.sense_len - 3882 ccb->csio.sense_resid, &error_code, &sense_key, &asc, 3883 &ascq, /*show_errors*/ 1); 3884 3885 /* 3886 * According to the SCSI spec, if the disk doesn't support 3887 * the requested format, it will generally return a sense 3888 * key of RECOVERED ERROR, and an additional sense code 3889 * of "DEFECT LIST NOT FOUND". HGST drives also return 3890 * Primary/Grown defect list not found errors. So just 3891 * check for an ASC of 0x1c. 3892 */ 3893 if ((sense_key == SSD_KEY_RECOVERED_ERROR) 3894 && (asc == 0x1c)) { 3895 const char *format_str; 3896 3897 format_str = scsi_nv_to_str(defect_list_type_map, 3898 sizeof(defect_list_type_map) / 3899 sizeof(defect_list_type_map[0]), 3900 list_format & SRDD10_DLIST_FORMAT_MASK); 3901 warnx("requested defect format %s not available", 3902 format_str ? format_str : "unknown"); 3903 3904 format_str = scsi_nv_to_str(defect_list_type_map, 3905 sizeof(defect_list_type_map) / 3906 sizeof(defect_list_type_map[0]), returned_type); 3907 if (format_str != NULL) { 3908 warnx("Device returned %s format", 3909 format_str); 3910 } else { 3911 error = 1; 3912 warnx("Device returned unknown defect" 3913 " data format %#x", returned_type); 3914 goto defect_bailout; 3915 } 3916 } else { 3917 error = 1; 3918 warnx("Error returned from read defect data command"); 3919 if (arglist & CAM_ARG_VERBOSE) 3920 cam_error_print(device, ccb, CAM_ESF_ALL, 3921 CAM_EPF_ALL, stderr); 3922 goto defect_bailout; 3923 } 3924 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3925 error = 1; 3926 warnx("Error returned from read defect data command"); 3927 if (arglist & CAM_ARG_VERBOSE) 3928 cam_error_print(device, ccb, CAM_ESF_ALL, 3929 CAM_EPF_ALL, stderr); 3930 goto defect_bailout; 3931 } 3932 3933 if (first_pass != 0) { 3934 fprintf(stderr, "Got %d defect", num_returned); 3935 3936 if ((lists_specified == 0) || (num_returned == 0)) { 3937 fprintf(stderr, "s.\n"); 3938 goto defect_bailout; 3939 } else if (num_returned == 1) 3940 fprintf(stderr, ":\n"); 3941 else 3942 fprintf(stderr, "s:\n"); 3943 3944 first_pass = 0; 3945 } 3946 3947 /* 3948 * XXX KDM I should probably clean up the printout format for the 3949 * disk defects. 3950 */ 3951 switch (returned_type) { 3952 case SRDD10_PHYSICAL_SECTOR_FORMAT: 3953 case SRDD10_EXT_PHYS_FORMAT: 3954 { 3955 struct scsi_defect_desc_phys_sector *dlist; 3956 3957 dlist = (struct scsi_defect_desc_phys_sector *) 3958 (defect_list + hdr_size); 3959 3960 for (i = 0; i < num_valid; i++) { 3961 uint32_t sector; 3962 3963 sector = scsi_4btoul(dlist[i].sector); 3964 if (returned_type == SRDD10_EXT_PHYS_FORMAT) { 3965 mads = (sector & SDD_EXT_PHYS_MADS) ? 3966 0 : 1; 3967 sector &= ~SDD_EXT_PHYS_FLAG_MASK; 3968 } 3969 if (hex_format == 0) 3970 fprintf(stdout, "%d:%d:%d%s", 3971 scsi_3btoul(dlist[i].cylinder), 3972 dlist[i].head, 3973 scsi_4btoul(dlist[i].sector), 3974 mads ? " - " : "\n"); 3975 else 3976 fprintf(stdout, "0x%x:0x%x:0x%x%s", 3977 scsi_3btoul(dlist[i].cylinder), 3978 dlist[i].head, 3979 scsi_4btoul(dlist[i].sector), 3980 mads ? " - " : "\n"); 3981 mads = 0; 3982 } 3983 if (num_valid < num_returned) { 3984 starting_offset += num_valid; 3985 goto next_batch; 3986 } 3987 break; 3988 } 3989 case SRDD10_BYTES_FROM_INDEX_FORMAT: 3990 case SRDD10_EXT_BFI_FORMAT: 3991 { 3992 struct scsi_defect_desc_bytes_from_index *dlist; 3993 3994 dlist = (struct scsi_defect_desc_bytes_from_index *) 3995 (defect_list + hdr_size); 3996 3997 for (i = 0; i < num_valid; i++) { 3998 uint32_t bfi; 3999 4000 bfi = scsi_4btoul(dlist[i].bytes_from_index); 4001 if (returned_type == SRDD10_EXT_BFI_FORMAT) { 4002 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0; 4003 bfi &= ~SDD_EXT_BFI_FLAG_MASK; 4004 } 4005 if (hex_format == 0) 4006 fprintf(stdout, "%d:%d:%d%s", 4007 scsi_3btoul(dlist[i].cylinder), 4008 dlist[i].head, 4009 scsi_4btoul(dlist[i].bytes_from_index), 4010 mads ? " - " : "\n"); 4011 else 4012 fprintf(stdout, "0x%x:0x%x:0x%x%s", 4013 scsi_3btoul(dlist[i].cylinder), 4014 dlist[i].head, 4015 scsi_4btoul(dlist[i].bytes_from_index), 4016 mads ? " - " : "\n"); 4017 4018 mads = 0; 4019 } 4020 if (num_valid < num_returned) { 4021 starting_offset += num_valid; 4022 goto next_batch; 4023 } 4024 break; 4025 } 4026 case SRDDH10_BLOCK_FORMAT: 4027 { 4028 struct scsi_defect_desc_block *dlist; 4029 4030 dlist = (struct scsi_defect_desc_block *) 4031 (defect_list + hdr_size); 4032 4033 for (i = 0; i < num_valid; i++) { 4034 if (hex_format == 0) 4035 fprintf(stdout, "%u\n", 4036 scsi_4btoul(dlist[i].address)); 4037 else 4038 fprintf(stdout, "0x%x\n", 4039 scsi_4btoul(dlist[i].address)); 4040 } 4041 4042 if (num_valid < num_returned) { 4043 starting_offset += num_valid; 4044 goto next_batch; 4045 } 4046 4047 break; 4048 } 4049 case SRDD10_LONG_BLOCK_FORMAT: 4050 { 4051 struct scsi_defect_desc_long_block *dlist; 4052 4053 dlist = (struct scsi_defect_desc_long_block *) 4054 (defect_list + hdr_size); 4055 4056 for (i = 0; i < num_valid; i++) { 4057 if (hex_format == 0) 4058 fprintf(stdout, "%ju\n", 4059 (uintmax_t)scsi_8btou64( 4060 dlist[i].address)); 4061 else 4062 fprintf(stdout, "0x%jx\n", 4063 (uintmax_t)scsi_8btou64( 4064 dlist[i].address)); 4065 } 4066 4067 if (num_valid < num_returned) { 4068 starting_offset += num_valid; 4069 goto next_batch; 4070 } 4071 break; 4072 } 4073 default: 4074 fprintf(stderr, "Unknown defect format 0x%x\n", 4075 returned_type); 4076 error = 1; 4077 break; 4078 } 4079defect_bailout: 4080 4081 if (defect_list != NULL) 4082 free(defect_list); 4083 4084 if (ccb != NULL) 4085 cam_freeccb(ccb); 4086 4087 return(error); 4088} 4089#endif /* MINIMALISTIC */ 4090 4091#if 0 4092void 4093reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks) 4094{ 4095 union ccb *ccb; 4096 4097 ccb = cam_getccb(device); 4098 4099 cam_freeccb(ccb); 4100} 4101#endif 4102 4103#ifndef MINIMALISTIC 4104void 4105mode_sense(struct cam_device *device, int dbd, int pc, int page, int subpage, 4106 int task_attr, int retry_count, int timeout, u_int8_t *data, 4107 int datalen) 4108{ 4109 union ccb *ccb; 4110 int retval; 4111 4112 ccb = cam_getccb(device); 4113 4114 if (ccb == NULL) 4115 errx(1, "mode_sense: couldn't allocate CCB"); 4116 4117 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 4118 4119 scsi_mode_sense_subpage(&ccb->csio, 4120 /* retries */ retry_count, 4121 /* cbfcnp */ NULL, 4122 /* tag_action */ task_attr, 4123 /* dbd */ dbd, 4124 /* pc */ pc << 6, 4125 /* page */ page, 4126 /* subpage */ subpage, 4127 /* param_buf */ data, 4128 /* param_len */ datalen, 4129 /* minimum_cmd_size */ 0, 4130 /* sense_len */ SSD_FULL_SIZE, 4131 /* timeout */ timeout ? timeout : 5000); 4132 4133 if (arglist & CAM_ARG_ERR_RECOVER) 4134 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 4135 4136 /* Disable freezing the device queue */ 4137 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 4138 4139 if (((retval = cam_send_ccb(device, ccb)) < 0) 4140 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 4141 if (arglist & CAM_ARG_VERBOSE) { 4142 cam_error_print(device, ccb, CAM_ESF_ALL, 4143 CAM_EPF_ALL, stderr); 4144 } 4145 cam_freeccb(ccb); 4146 cam_close_device(device); 4147 if (retval < 0) 4148 err(1, "error sending mode sense command"); 4149 else 4150 errx(1, "error sending mode sense command"); 4151 } 4152 4153 cam_freeccb(ccb); 4154} 4155 4156void 4157mode_select(struct cam_device *device, int save_pages, int task_attr, 4158 int retry_count, int timeout, u_int8_t *data, int datalen) 4159{ 4160 union ccb *ccb; 4161 int retval; 4162 4163 ccb = cam_getccb(device); 4164 4165 if (ccb == NULL) 4166 errx(1, "mode_select: couldn't allocate CCB"); 4167 4168 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 4169 4170 scsi_mode_select(&ccb->csio, 4171 /* retries */ retry_count, 4172 /* cbfcnp */ NULL, 4173 /* tag_action */ task_attr, 4174 /* scsi_page_fmt */ 1, 4175 /* save_pages */ save_pages, 4176 /* param_buf */ data, 4177 /* param_len */ datalen, 4178 /* sense_len */ SSD_FULL_SIZE, 4179 /* timeout */ timeout ? timeout : 5000); 4180 4181 if (arglist & CAM_ARG_ERR_RECOVER) 4182 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 4183 4184 /* Disable freezing the device queue */ 4185 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 4186 4187 if (((retval = cam_send_ccb(device, ccb)) < 0) 4188 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 4189 if (arglist & CAM_ARG_VERBOSE) { 4190 cam_error_print(device, ccb, CAM_ESF_ALL, 4191 CAM_EPF_ALL, stderr); 4192 } 4193 cam_freeccb(ccb); 4194 cam_close_device(device); 4195 4196 if (retval < 0) 4197 err(1, "error sending mode select command"); 4198 else 4199 errx(1, "error sending mode select command"); 4200 4201 } 4202 4203 cam_freeccb(ccb); 4204} 4205 4206void 4207modepage(struct cam_device *device, int argc, char **argv, char *combinedopt, 4208 int task_attr, int retry_count, int timeout) 4209{ 4210 char *str_subpage; 4211 int c, page = -1, subpage = -1, pc = 0; 4212 int binary = 0, dbd = 0, edit = 0, list = 0; 4213 4214 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4215 switch(c) { 4216 case 'b': 4217 binary = 1; 4218 break; 4219 case 'd': 4220 dbd = 1; 4221 break; 4222 case 'e': 4223 edit = 1; 4224 break; 4225 case 'l': 4226 list++; 4227 break; 4228 case 'm': 4229 str_subpage = optarg; 4230 strsep(&str_subpage, ","); 4231 page = strtol(optarg, NULL, 0); 4232 if (str_subpage) 4233 subpage = strtol(str_subpage, NULL, 0); 4234 else 4235 subpage = 0; 4236 if (page < 0) 4237 errx(1, "invalid mode page %d", page); 4238 if (subpage < 0) 4239 errx(1, "invalid mode subpage %d", subpage); 4240 break; 4241 case 'P': 4242 pc = strtol(optarg, NULL, 0); 4243 if ((pc < 0) || (pc > 3)) 4244 errx(1, "invalid page control field %d", pc); 4245 break; 4246 default: 4247 break; 4248 } 4249 } 4250 4251 if (page == -1 && list == 0) 4252 errx(1, "you must specify a mode page!"); 4253 4254 if (list != 0) { 4255 mode_list(device, dbd, pc, list > 1, task_attr, retry_count, 4256 timeout); 4257 } else { 4258 mode_edit(device, dbd, pc, page, subpage, edit, binary, 4259 task_attr, retry_count, timeout); 4260 } 4261} 4262 4263static int 4264scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, 4265 int task_attr, int retry_count, int timeout) 4266{ 4267 union ccb *ccb; 4268 u_int32_t flags = CAM_DIR_NONE; 4269 u_int8_t *data_ptr = NULL; 4270 u_int8_t cdb[20]; 4271 u_int8_t atacmd[12]; 4272 struct get_hook hook; 4273 int c, data_bytes = 0, valid_bytes; 4274 int cdb_len = 0; 4275 int atacmd_len = 0; 4276 int dmacmd = 0; 4277 int fpdmacmd = 0; 4278 int need_res = 0; 4279 char *datastr = NULL, *tstr, *resstr = NULL; 4280 int error = 0; 4281 int fd_data = 0, fd_res = 0; 4282 int retval; 4283 4284 ccb = cam_getccb(device); 4285 4286 if (ccb == NULL) { 4287 warnx("scsicmd: error allocating ccb"); 4288 return(1); 4289 } 4290 4291 CCB_CLEAR_ALL_EXCEPT_HDR(ccb); 4292 4293 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4294 switch(c) { 4295 case 'a': 4296 tstr = optarg; 4297 while (isspace(*tstr) && (*tstr != '\0')) 4298 tstr++; 4299 hook.argc = argc - optind; 4300 hook.argv = argv + optind; 4301 hook.got = 0; 4302 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr, 4303 iget, &hook); 4304 /* 4305 * Increment optind by the number of arguments the 4306 * encoding routine processed. After each call to 4307 * getopt(3), optind points to the argument that 4308 * getopt should process _next_. In this case, 4309 * that means it points to the first command string 4310 * argument, if there is one. Once we increment 4311 * this, it should point to either the next command 4312 * line argument, or it should be past the end of 4313 * the list. 4314 */ 4315 optind += hook.got; 4316 break; 4317 case 'c': 4318 tstr = optarg; 4319 while (isspace(*tstr) && (*tstr != '\0')) 4320 tstr++; 4321 hook.argc = argc - optind; 4322 hook.argv = argv + optind; 4323 hook.got = 0; 4324 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr, 4325 iget, &hook); 4326 /* 4327 * Increment optind by the number of arguments the 4328 * encoding routine processed. After each call to 4329 * getopt(3), optind points to the argument that 4330 * getopt should process _next_. In this case, 4331 * that means it points to the first command string 4332 * argument, if there is one. Once we increment 4333 * this, it should point to either the next command 4334 * line argument, or it should be past the end of 4335 * the list. 4336 */ 4337 optind += hook.got; 4338 break; 4339 case 'd': 4340 dmacmd = 1; 4341 break; 4342 case 'f': 4343 fpdmacmd = 1; 4344 break; 4345 case 'i': 4346 if (arglist & CAM_ARG_CMD_OUT) { 4347 warnx("command must either be " 4348 "read or write, not both"); 4349 error = 1; 4350 goto scsicmd_bailout; 4351 } 4352 arglist |= CAM_ARG_CMD_IN; 4353 flags = CAM_DIR_IN; 4354 data_bytes = strtol(optarg, NULL, 0); 4355 if (data_bytes <= 0) { 4356 warnx("invalid number of input bytes %d", 4357 data_bytes); 4358 error = 1; 4359 goto scsicmd_bailout; 4360 } 4361 hook.argc = argc - optind; 4362 hook.argv = argv + optind; 4363 hook.got = 0; 4364 optind++; 4365 datastr = cget(&hook, NULL); 4366 /* 4367 * If the user supplied "-" instead of a format, he 4368 * wants the data to be written to stdout. 4369 */ 4370 if ((datastr != NULL) 4371 && (datastr[0] == '-')) 4372 fd_data = 1; 4373 4374 data_ptr = (u_int8_t *)malloc(data_bytes); 4375 if (data_ptr == NULL) { 4376 warnx("can't malloc memory for data_ptr"); 4377 error = 1; 4378 goto scsicmd_bailout; 4379 } 4380 break; 4381 case 'o': 4382 if (arglist & CAM_ARG_CMD_IN) { 4383 warnx("command must either be " 4384 "read or write, not both"); 4385 error = 1; 4386 goto scsicmd_bailout; 4387 } 4388 arglist |= CAM_ARG_CMD_OUT; 4389 flags = CAM_DIR_OUT; 4390 data_bytes = strtol(optarg, NULL, 0); 4391 if (data_bytes <= 0) { 4392 warnx("invalid number of output bytes %d", 4393 data_bytes); 4394 error = 1; 4395 goto scsicmd_bailout; 4396 } 4397 hook.argc = argc - optind; 4398 hook.argv = argv + optind; 4399 hook.got = 0; 4400 datastr = cget(&hook, NULL); 4401 data_ptr = (u_int8_t *)malloc(data_bytes); 4402 if (data_ptr == NULL) { 4403 warnx("can't malloc memory for data_ptr"); 4404 error = 1; 4405 goto scsicmd_bailout; 4406 } 4407 bzero(data_ptr, data_bytes); 4408 /* 4409 * If the user supplied "-" instead of a format, he 4410 * wants the data to be read from stdin. 4411 */ 4412 if ((datastr != NULL) 4413 && (datastr[0] == '-')) 4414 fd_data = 1; 4415 else 4416 buff_encode_visit(data_ptr, data_bytes, datastr, 4417 iget, &hook); 4418 optind += hook.got; 4419 break; 4420 case 'r': 4421 need_res = 1; 4422 hook.argc = argc - optind; 4423 hook.argv = argv + optind; 4424 hook.got = 0; 4425 resstr = cget(&hook, NULL); 4426 if ((resstr != NULL) && (resstr[0] == '-')) 4427 fd_res = 1; 4428 optind += hook.got; 4429 break; 4430 default: 4431 break; 4432 } 4433 } 4434 4435 /* 4436 * If fd_data is set, and we're writing to the device, we need to 4437 * read the data the user wants written from stdin. 4438 */ 4439 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) { 4440 ssize_t amt_read; 4441 int amt_to_read = data_bytes; 4442 u_int8_t *buf_ptr = data_ptr; 4443 4444 for (amt_read = 0; amt_to_read > 0; 4445 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) { 4446 if (amt_read == -1) { 4447 warn("error reading data from stdin"); 4448 error = 1; 4449 goto scsicmd_bailout; 4450 } 4451 amt_to_read -= amt_read; 4452 buf_ptr += amt_read; 4453 } 4454 } 4455 4456 if (arglist & CAM_ARG_ERR_RECOVER) 4457 flags |= CAM_PASS_ERR_RECOVER; 4458 4459 /* Disable freezing the device queue */ 4460 flags |= CAM_DEV_QFRZDIS; 4461 4462 if (cdb_len) { 4463 /* 4464 * This is taken from the SCSI-3 draft spec. 4465 * (T10/1157D revision 0.3) 4466 * The top 3 bits of an opcode are the group code. 4467 * The next 5 bits are the command code. 4468 * Group 0: six byte commands 4469 * Group 1: ten byte commands 4470 * Group 2: ten byte commands 4471 * Group 3: reserved 4472 * Group 4: sixteen byte commands 4473 * Group 5: twelve byte commands 4474 * Group 6: vendor specific 4475 * Group 7: vendor specific 4476 */ 4477 switch((cdb[0] >> 5) & 0x7) { 4478 case 0: 4479 cdb_len = 6; 4480 break; 4481 case 1: 4482 case 2: 4483 cdb_len = 10; 4484 break; 4485 case 3: 4486 case 6: 4487 case 7: 4488 /* computed by buff_encode_visit */ 4489 break; 4490 case 4: 4491 cdb_len = 16; 4492 break; 4493 case 5: 4494 cdb_len = 12; 4495 break; 4496 } 4497 4498 /* 4499 * We should probably use csio_build_visit or something like that 4500 * here, but it's easier to encode arguments as you go. The 4501 * alternative would be skipping the CDB argument and then encoding 4502 * it here, since we've got the data buffer argument by now. 4503 */ 4504 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len); 4505 4506 cam_fill_csio(&ccb->csio, 4507 /*retries*/ retry_count, 4508 /*cbfcnp*/ NULL, 4509 /*flags*/ flags, 4510 /*tag_action*/ task_attr, 4511 /*data_ptr*/ data_ptr, 4512 /*dxfer_len*/ data_bytes, 4513 /*sense_len*/ SSD_FULL_SIZE, 4514 /*cdb_len*/ cdb_len, 4515 /*timeout*/ timeout ? timeout : 5000); 4516 } else { 4517 atacmd_len = 12; 4518 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len); 4519 if (need_res) 4520 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT; 4521 if (dmacmd) 4522 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA; 4523 if (fpdmacmd) 4524 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA; 4525 4526 cam_fill_ataio(&ccb->ataio, 4527 /*retries*/ retry_count, 4528 /*cbfcnp*/ NULL, 4529 /*flags*/ flags, 4530 /*tag_action*/ 0, 4531 /*data_ptr*/ data_ptr, 4532 /*dxfer_len*/ data_bytes, 4533 /*timeout*/ timeout ? timeout : 5000); 4534 } 4535 4536 if (((retval = cam_send_ccb(device, ccb)) < 0) 4537 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 4538 const char warnstr[] = "error sending command"; 4539 4540 if (retval < 0) 4541 warn(warnstr); 4542 else 4543 warnx(warnstr); 4544 4545 if (arglist & CAM_ARG_VERBOSE) { 4546 cam_error_print(device, ccb, CAM_ESF_ALL, 4547 CAM_EPF_ALL, stderr); 4548 } 4549 4550 error = 1; 4551 goto scsicmd_bailout; 4552 } 4553 4554 if (atacmd_len && need_res) { 4555 if (fd_res == 0) { 4556 buff_decode_visit(&ccb->ataio.res.status, 11, resstr, 4557 arg_put, NULL); 4558 fprintf(stdout, "\n"); 4559 } else { 4560 fprintf(stdout, 4561 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 4562 ccb->ataio.res.status, 4563 ccb->ataio.res.error, 4564 ccb->ataio.res.lba_low, 4565 ccb->ataio.res.lba_mid, 4566 ccb->ataio.res.lba_high, 4567 ccb->ataio.res.device, 4568 ccb->ataio.res.lba_low_exp, 4569 ccb->ataio.res.lba_mid_exp, 4570 ccb->ataio.res.lba_high_exp, 4571 ccb->ataio.res.sector_count, 4572 ccb->ataio.res.sector_count_exp); 4573 fflush(stdout); 4574 } 4575 } 4576 4577 if (cdb_len) 4578 valid_bytes = ccb->csio.dxfer_len - ccb->csio.resid; 4579 else 4580 valid_bytes = ccb->ataio.dxfer_len - ccb->ataio.resid; 4581 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 4582 && (arglist & CAM_ARG_CMD_IN) 4583 && (valid_bytes > 0)) { 4584 if (fd_data == 0) { 4585 buff_decode_visit(data_ptr, valid_bytes, datastr, 4586 arg_put, NULL); 4587 fprintf(stdout, "\n"); 4588 } else { 4589 ssize_t amt_written; 4590 int amt_to_write = valid_bytes; 4591 u_int8_t *buf_ptr = data_ptr; 4592 4593 for (amt_written = 0; (amt_to_write > 0) && 4594 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){ 4595 amt_to_write -= amt_written; 4596 buf_ptr += amt_written; 4597 } 4598 if (amt_written == -1) { 4599 warn("error writing data to stdout"); 4600 error = 1; 4601 goto scsicmd_bailout; 4602 } else if ((amt_written == 0) 4603 && (amt_to_write > 0)) { 4604 warnx("only wrote %u bytes out of %u", 4605 valid_bytes - amt_to_write, valid_bytes); 4606 } 4607 } 4608 } 4609 4610scsicmd_bailout: 4611 4612 if ((data_bytes > 0) && (data_ptr != NULL)) 4613 free(data_ptr); 4614 4615 cam_freeccb(ccb); 4616 4617 return(error); 4618} 4619 4620static int 4621camdebug(int argc, char **argv, char *combinedopt) 4622{ 4623 int c, fd; 4624 path_id_t bus = CAM_BUS_WILDCARD; 4625 target_id_t target = CAM_TARGET_WILDCARD; 4626 lun_id_t lun = CAM_LUN_WILDCARD; 4627 char *tstr, *tmpstr = NULL; 4628 union ccb ccb; 4629 int error = 0; 4630 4631 bzero(&ccb, sizeof(union ccb)); 4632 4633 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4634 switch(c) { 4635 case 'I': 4636 arglist |= CAM_ARG_DEBUG_INFO; 4637 ccb.cdbg.flags |= CAM_DEBUG_INFO; 4638 break; 4639 case 'P': 4640 arglist |= CAM_ARG_DEBUG_PERIPH; 4641 ccb.cdbg.flags |= CAM_DEBUG_PERIPH; 4642 break; 4643 case 'S': 4644 arglist |= CAM_ARG_DEBUG_SUBTRACE; 4645 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE; 4646 break; 4647 case 'T': 4648 arglist |= CAM_ARG_DEBUG_TRACE; 4649 ccb.cdbg.flags |= CAM_DEBUG_TRACE; 4650 break; 4651 case 'X': 4652 arglist |= CAM_ARG_DEBUG_XPT; 4653 ccb.cdbg.flags |= CAM_DEBUG_XPT; 4654 break; 4655 case 'c': 4656 arglist |= CAM_ARG_DEBUG_CDB; 4657 ccb.cdbg.flags |= CAM_DEBUG_CDB; 4658 break; 4659 case 'p': 4660 arglist |= CAM_ARG_DEBUG_PROBE; 4661 ccb.cdbg.flags |= CAM_DEBUG_PROBE; 4662 break; 4663 default: 4664 break; 4665 } 4666 } 4667 4668 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) { 4669 warnx("error opening transport layer device %s", XPT_DEVICE); 4670 warn("%s", XPT_DEVICE); 4671 return(1); 4672 } 4673 argc -= optind; 4674 argv += optind; 4675 4676 if (argc <= 0) { 4677 warnx("you must specify \"off\", \"all\" or a bus,"); 4678 warnx("bus:target, or bus:target:lun"); 4679 close(fd); 4680 return(1); 4681 } 4682 4683 tstr = *argv; 4684 4685 while (isspace(*tstr) && (*tstr != '\0')) 4686 tstr++; 4687 4688 if (strncmp(tstr, "off", 3) == 0) { 4689 ccb.cdbg.flags = CAM_DEBUG_NONE; 4690 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH| 4691 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE| 4692 CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE); 4693 } else if (strncmp(tstr, "all", 3) != 0) { 4694 tmpstr = (char *)strtok(tstr, ":"); 4695 if ((tmpstr != NULL) && (*tmpstr != '\0')){ 4696 bus = strtol(tmpstr, NULL, 0); 4697 arglist |= CAM_ARG_BUS; 4698 tmpstr = (char *)strtok(NULL, ":"); 4699 if ((tmpstr != NULL) && (*tmpstr != '\0')){ 4700 target = strtol(tmpstr, NULL, 0); 4701 arglist |= CAM_ARG_TARGET; 4702 tmpstr = (char *)strtok(NULL, ":"); 4703 if ((tmpstr != NULL) && (*tmpstr != '\0')){ 4704 lun = strtol(tmpstr, NULL, 0); 4705 arglist |= CAM_ARG_LUN; 4706 } 4707 } 4708 } else { 4709 error = 1; 4710 warnx("you must specify \"all\", \"off\", or a bus,"); 4711 warnx("bus:target, or bus:target:lun to debug"); 4712 } 4713 } 4714 4715 if (error == 0) { 4716 4717 ccb.ccb_h.func_code = XPT_DEBUG; 4718 ccb.ccb_h.path_id = bus; 4719 ccb.ccb_h.target_id = target; 4720 ccb.ccb_h.target_lun = lun; 4721 4722 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 4723 warn("CAMIOCOMMAND ioctl failed"); 4724 error = 1; 4725 } 4726 4727 if (error == 0) { 4728 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == 4729 CAM_FUNC_NOTAVAIL) { 4730 warnx("CAM debugging not available"); 4731 warnx("you need to put options CAMDEBUG in" 4732 " your kernel config file!"); 4733 error = 1; 4734 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) != 4735 CAM_REQ_CMP) { 4736 warnx("XPT_DEBUG CCB failed with status %#x", 4737 ccb.ccb_h.status); 4738 error = 1; 4739 } else { 4740 if (ccb.cdbg.flags == CAM_DEBUG_NONE) { 4741 fprintf(stderr, 4742 "Debugging turned off\n"); 4743 } else { 4744 fprintf(stderr, 4745 "Debugging enabled for " 4746 "%d:%d:%jx\n", 4747 bus, target, (uintmax_t)lun); 4748 } 4749 } 4750 } 4751 close(fd); 4752 } 4753 4754 return(error); 4755} 4756 4757static int 4758tagcontrol(struct cam_device *device, int argc, char **argv, 4759 char *combinedopt) 4760{ 4761 int c; 4762 union ccb *ccb; 4763 int numtags = -1; 4764 int retval = 0; 4765 int quiet = 0; 4766 char pathstr[1024]; 4767 4768 ccb = cam_getccb(device); 4769 4770 if (ccb == NULL) { 4771 warnx("tagcontrol: error allocating ccb"); 4772 return(1); 4773 } 4774 4775 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4776 switch(c) { 4777 case 'N': 4778 numtags = strtol(optarg, NULL, 0); 4779 if (numtags < 0) { 4780 warnx("tag count %d is < 0", numtags); 4781 retval = 1; 4782 goto tagcontrol_bailout; 4783 } 4784 break; 4785 case 'q': 4786 quiet++; 4787 break; 4788 default: 4789 break; 4790 } 4791 } 4792 4793 cam_path_string(device, pathstr, sizeof(pathstr)); 4794 4795 if (numtags >= 0) { 4796 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->crs); 4797 ccb->ccb_h.func_code = XPT_REL_SIMQ; 4798 ccb->ccb_h.flags = CAM_DEV_QFREEZE; 4799 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS; 4800 ccb->crs.openings = numtags; 4801 4802 4803 if (cam_send_ccb(device, ccb) < 0) { 4804 perror("error sending XPT_REL_SIMQ CCB"); 4805 retval = 1; 4806 goto tagcontrol_bailout; 4807 } 4808 4809 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 4810 warnx("XPT_REL_SIMQ CCB failed"); 4811 cam_error_print(device, ccb, CAM_ESF_ALL, 4812 CAM_EPF_ALL, stderr); 4813 retval = 1; 4814 goto tagcontrol_bailout; 4815 } 4816 4817 4818 if (quiet == 0) 4819 fprintf(stdout, "%stagged openings now %d\n", 4820 pathstr, ccb->crs.openings); 4821 } 4822 4823 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgds); 4824 4825 ccb->ccb_h.func_code = XPT_GDEV_STATS; 4826 4827 if (cam_send_ccb(device, ccb) < 0) { 4828 perror("error sending XPT_GDEV_STATS CCB"); 4829 retval = 1; 4830 goto tagcontrol_bailout; 4831 } 4832 4833 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 4834 warnx("XPT_GDEV_STATS CCB failed"); 4835 cam_error_print(device, ccb, CAM_ESF_ALL, 4836 CAM_EPF_ALL, stderr); 4837 retval = 1; 4838 goto tagcontrol_bailout; 4839 } 4840 4841 if (arglist & CAM_ARG_VERBOSE) { 4842 fprintf(stdout, "%s", pathstr); 4843 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings); 4844 fprintf(stdout, "%s", pathstr); 4845 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active); 4846 fprintf(stdout, "%s", pathstr); 4847 fprintf(stdout, "allocated %d\n", ccb->cgds.allocated); 4848 fprintf(stdout, "%s", pathstr); 4849 fprintf(stdout, "queued %d\n", ccb->cgds.queued); 4850 fprintf(stdout, "%s", pathstr); 4851 fprintf(stdout, "held %d\n", ccb->cgds.held); 4852 fprintf(stdout, "%s", pathstr); 4853 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags); 4854 fprintf(stdout, "%s", pathstr); 4855 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags); 4856 } else { 4857 if (quiet == 0) { 4858 fprintf(stdout, "%s", pathstr); 4859 fprintf(stdout, "device openings: "); 4860 } 4861 fprintf(stdout, "%d\n", ccb->cgds.dev_openings + 4862 ccb->cgds.dev_active); 4863 } 4864 4865tagcontrol_bailout: 4866 4867 cam_freeccb(ccb); 4868 return(retval); 4869} 4870 4871static void 4872cts_print(struct cam_device *device, struct ccb_trans_settings *cts) 4873{ 4874 char pathstr[1024]; 4875 4876 cam_path_string(device, pathstr, sizeof(pathstr)); 4877 4878 if (cts->transport == XPORT_SPI) { 4879 struct ccb_trans_settings_spi *spi = 4880 &cts->xport_specific.spi; 4881 4882 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { 4883 4884 fprintf(stdout, "%ssync parameter: %d\n", pathstr, 4885 spi->sync_period); 4886 4887 if (spi->sync_offset != 0) { 4888 u_int freq; 4889 4890 freq = scsi_calc_syncsrate(spi->sync_period); 4891 fprintf(stdout, "%sfrequency: %d.%03dMHz\n", 4892 pathstr, freq / 1000, freq % 1000); 4893 } 4894 } 4895 4896 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) { 4897 fprintf(stdout, "%soffset: %d\n", pathstr, 4898 spi->sync_offset); 4899 } 4900 4901 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) { 4902 fprintf(stdout, "%sbus width: %d bits\n", pathstr, 4903 (0x01 << spi->bus_width) * 8); 4904 } 4905 4906 if (spi->valid & CTS_SPI_VALID_DISC) { 4907 fprintf(stdout, "%sdisconnection is %s\n", pathstr, 4908 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ? 4909 "enabled" : "disabled"); 4910 } 4911 } 4912 if (cts->transport == XPORT_FC) { 4913 struct ccb_trans_settings_fc *fc = 4914 &cts->xport_specific.fc; 4915 4916 if (fc->valid & CTS_FC_VALID_WWNN) 4917 fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr, 4918 (long long) fc->wwnn); 4919 if (fc->valid & CTS_FC_VALID_WWPN) 4920 fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr, 4921 (long long) fc->wwpn); 4922 if (fc->valid & CTS_FC_VALID_PORT) 4923 fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port); 4924 if (fc->valid & CTS_FC_VALID_SPEED) 4925 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n", 4926 pathstr, fc->bitrate / 1000, fc->bitrate % 1000); 4927 } 4928 if (cts->transport == XPORT_SAS) { 4929 struct ccb_trans_settings_sas *sas = 4930 &cts->xport_specific.sas; 4931 4932 if (sas->valid & CTS_SAS_VALID_SPEED) 4933 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n", 4934 pathstr, sas->bitrate / 1000, sas->bitrate % 1000); 4935 } 4936 if (cts->transport == XPORT_ATA) { 4937 struct ccb_trans_settings_pata *pata = 4938 &cts->xport_specific.ata; 4939 4940 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) { 4941 fprintf(stdout, "%sATA mode: %s\n", pathstr, 4942 ata_mode2string(pata->mode)); 4943 } 4944 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) { 4945 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr, 4946 pata->atapi); 4947 } 4948 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) { 4949 fprintf(stdout, "%sPIO transaction length: %d\n", 4950 pathstr, pata->bytecount); 4951 } 4952 } 4953 if (cts->transport == XPORT_SATA) { 4954 struct ccb_trans_settings_sata *sata = 4955 &cts->xport_specific.sata; 4956 4957 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) { 4958 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr, 4959 sata->revision); 4960 } 4961 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) { 4962 fprintf(stdout, "%sATA mode: %s\n", pathstr, 4963 ata_mode2string(sata->mode)); 4964 } 4965 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) { 4966 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr, 4967 sata->atapi); 4968 } 4969 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) { 4970 fprintf(stdout, "%sPIO transaction length: %d\n", 4971 pathstr, sata->bytecount); 4972 } 4973 if ((sata->valid & CTS_SATA_VALID_PM) != 0) { 4974 fprintf(stdout, "%sPMP presence: %d\n", pathstr, 4975 sata->pm_present); 4976 } 4977 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) { 4978 fprintf(stdout, "%sNumber of tags: %d\n", pathstr, 4979 sata->tags); 4980 } 4981 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) { 4982 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr, 4983 sata->caps); 4984 } 4985 } 4986 if (cts->protocol == PROTO_ATA) { 4987 struct ccb_trans_settings_ata *ata= 4988 &cts->proto_specific.ata; 4989 4990 if (ata->valid & CTS_ATA_VALID_TQ) { 4991 fprintf(stdout, "%stagged queueing: %s\n", pathstr, 4992 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ? 4993 "enabled" : "disabled"); 4994 } 4995 } 4996 if (cts->protocol == PROTO_SCSI) { 4997 struct ccb_trans_settings_scsi *scsi= 4998 &cts->proto_specific.scsi; 4999 5000 if (scsi->valid & CTS_SCSI_VALID_TQ) { 5001 fprintf(stdout, "%stagged queueing: %s\n", pathstr, 5002 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ? 5003 "enabled" : "disabled"); 5004 } 5005 } 5006 5007} 5008 5009/* 5010 * Get a path inquiry CCB for the specified device. 5011 */ 5012static int 5013get_cpi(struct cam_device *device, struct ccb_pathinq *cpi) 5014{ 5015 union ccb *ccb; 5016 int retval = 0; 5017 5018 ccb = cam_getccb(device); 5019 if (ccb == NULL) { 5020 warnx("get_cpi: couldn't allocate CCB"); 5021 return(1); 5022 } 5023 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi); 5024 ccb->ccb_h.func_code = XPT_PATH_INQ; 5025 if (cam_send_ccb(device, ccb) < 0) { 5026 warn("get_cpi: error sending Path Inquiry CCB"); 5027 if (arglist & CAM_ARG_VERBOSE) 5028 cam_error_print(device, ccb, CAM_ESF_ALL, 5029 CAM_EPF_ALL, stderr); 5030 retval = 1; 5031 goto get_cpi_bailout; 5032 } 5033 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 5034 if (arglist & CAM_ARG_VERBOSE) 5035 cam_error_print(device, ccb, CAM_ESF_ALL, 5036 CAM_EPF_ALL, stderr); 5037 retval = 1; 5038 goto get_cpi_bailout; 5039 } 5040 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq)); 5041 5042get_cpi_bailout: 5043 cam_freeccb(ccb); 5044 return(retval); 5045} 5046 5047/* 5048 * Get a get device CCB for the specified device. 5049 */ 5050static int 5051get_cgd(struct cam_device *device, struct ccb_getdev *cgd) 5052{ 5053 union ccb *ccb; 5054 int retval = 0; 5055 5056 ccb = cam_getccb(device); 5057 if (ccb == NULL) { 5058 warnx("get_cgd: couldn't allocate CCB"); 5059 return(1); 5060 } 5061 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd); 5062 ccb->ccb_h.func_code = XPT_GDEV_TYPE; 5063 if (cam_send_ccb(device, ccb) < 0) { 5064 warn("get_cgd: error sending Path Inquiry CCB"); 5065 if (arglist & CAM_ARG_VERBOSE) 5066 cam_error_print(device, ccb, CAM_ESF_ALL, 5067 CAM_EPF_ALL, stderr); 5068 retval = 1; 5069 goto get_cgd_bailout; 5070 } 5071 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 5072 if (arglist & CAM_ARG_VERBOSE) 5073 cam_error_print(device, ccb, CAM_ESF_ALL, 5074 CAM_EPF_ALL, stderr); 5075 retval = 1; 5076 goto get_cgd_bailout; 5077 } 5078 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev)); 5079 5080get_cgd_bailout: 5081 cam_freeccb(ccb); 5082 return(retval); 5083} 5084 5085/* 5086 * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an 5087 * error. 5088 */ 5089int 5090dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count, 5091 int timeout, int verbosemode) 5092{ 5093 union ccb *ccb = NULL; 5094 struct scsi_vpd_supported_page_list sup_pages; 5095 int i; 5096 int retval = 0; 5097 5098 ccb = cam_getccb(dev); 5099 if (ccb == NULL) { 5100 warn("Unable to allocate CCB"); 5101 retval = -1; 5102 goto bailout; 5103 } 5104 5105 /* cam_getccb cleans up the header, caller has to zero the payload */ 5106 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 5107 5108 bzero(&sup_pages, sizeof(sup_pages)); 5109 5110 scsi_inquiry(&ccb->csio, 5111 /*retries*/ retry_count, 5112 /*cbfcnp*/ NULL, 5113 /* tag_action */ MSG_SIMPLE_Q_TAG, 5114 /* inq_buf */ (u_int8_t *)&sup_pages, 5115 /* inq_len */ sizeof(sup_pages), 5116 /* evpd */ 1, 5117 /* page_code */ SVPD_SUPPORTED_PAGE_LIST, 5118 /* sense_len */ SSD_FULL_SIZE, 5119 /* timeout */ timeout ? timeout : 5000); 5120 5121 /* Disable freezing the device queue */ 5122 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 5123 5124 if (retry_count != 0) 5125 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 5126 5127 if (cam_send_ccb(dev, ccb) < 0) { 5128 cam_freeccb(ccb); 5129 ccb = NULL; 5130 retval = -1; 5131 goto bailout; 5132 } 5133 5134 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 5135 if (verbosemode != 0) 5136 cam_error_print(dev, ccb, CAM_ESF_ALL, 5137 CAM_EPF_ALL, stderr); 5138 retval = -1; 5139 goto bailout; 5140 } 5141 5142 for (i = 0; i < sup_pages.length; i++) { 5143 if (sup_pages.list[i] == page_id) { 5144 retval = 1; 5145 goto bailout; 5146 } 5147 } 5148bailout: 5149 if (ccb != NULL) 5150 cam_freeccb(ccb); 5151 5152 return (retval); 5153} 5154 5155/* 5156 * devtype is filled in with the type of device. 5157 * Returns 0 for success, non-zero for failure. 5158 */ 5159int 5160get_device_type(struct cam_device *dev, int retry_count, int timeout, 5161 int verbosemode, camcontrol_devtype *devtype) 5162{ 5163 struct ccb_getdev cgd; 5164 int retval = 0; 5165 5166 retval = get_cgd(dev, &cgd); 5167 if (retval != 0) 5168 goto bailout; 5169 5170 switch (cgd.protocol) { 5171 case PROTO_SCSI: 5172 break; 5173 case PROTO_ATA: 5174 case PROTO_ATAPI: 5175 case PROTO_SATAPM: 5176 *devtype = CC_DT_ATA; 5177 goto bailout; 5178 break; /*NOTREACHED*/ 5179 default: 5180 *devtype = CC_DT_UNKNOWN; 5181 goto bailout; 5182 break; /*NOTREACHED*/ 5183 } 5184 5185 /* 5186 * Check for the ATA Information VPD page (0x89). If this is an 5187 * ATA device behind a SCSI to ATA translation layer, this VPD page 5188 * should be present. 5189 * 5190 * If that VPD page isn't present, or we get an error back from the 5191 * INQUIRY command, we'll just treat it as a normal SCSI device. 5192 */ 5193 retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count, 5194 timeout, verbosemode); 5195 if (retval == 1) 5196 *devtype = CC_DT_ATA_BEHIND_SCSI; 5197 else 5198 *devtype = CC_DT_SCSI; 5199 5200 retval = 0; 5201 5202bailout: 5203 return (retval); 5204} 5205 5206void 5207build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags, 5208 uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features, 5209 uint16_t sector_count, uint64_t lba, uint8_t command, uint8_t *data_ptr, 5210 uint16_t dxfer_len, uint8_t sense_len, uint32_t timeout, 5211 int is48bit, camcontrol_devtype devtype) 5212{ 5213 if (devtype == CC_DT_ATA) { 5214 cam_fill_ataio(&ccb->ataio, 5215 /*retries*/ retry_count, 5216 /*cbfcnp*/ NULL, 5217 /*flags*/ flags, 5218 /*tag_action*/ tag_action, 5219 /*data_ptr*/ data_ptr, 5220 /*dxfer_len*/ dxfer_len, 5221 /*timeout*/ timeout); 5222 if (is48bit || lba > ATA_MAX_28BIT_LBA) 5223 ata_48bit_cmd(&ccb->ataio, command, features, lba, 5224 sector_count); 5225 else 5226 ata_28bit_cmd(&ccb->ataio, command, features, lba, 5227 sector_count); 5228 } else { 5229 if (is48bit || lba > ATA_MAX_28BIT_LBA) 5230 protocol |= AP_EXTEND; 5231 5232 scsi_ata_pass_16(&ccb->csio, 5233 /*retries*/ retry_count, 5234 /*cbfcnp*/ NULL, 5235 /*flags*/ flags, 5236 /*tag_action*/ tag_action, 5237 /*protocol*/ protocol, 5238 /*ata_flags*/ ata_flags, 5239 /*features*/ features, 5240 /*sector_count*/ sector_count, 5241 /*lba*/ lba, 5242 /*command*/ command, 5243 /*control*/ 0, 5244 /*data_ptr*/ data_ptr, 5245 /*dxfer_len*/ dxfer_len, 5246 /*sense_len*/ sense_len, 5247 /*timeout*/ timeout); 5248 } 5249} 5250 5251 5252static void 5253cpi_print(struct ccb_pathinq *cpi) 5254{ 5255 char adapter_str[1024]; 5256 uint64_t i; 5257 5258 snprintf(adapter_str, sizeof(adapter_str), 5259 "%s%d:", cpi->dev_name, cpi->unit_number); 5260 5261 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str, 5262 cpi->version_num); 5263 5264 for (i = 1; i < UINT8_MAX; i = i << 1) { 5265 const char *str; 5266 5267 if ((i & cpi->hba_inquiry) == 0) 5268 continue; 5269 5270 fprintf(stdout, "%s supports ", adapter_str); 5271 5272 switch(i) { 5273 case PI_MDP_ABLE: 5274 str = "MDP message"; 5275 break; 5276 case PI_WIDE_32: 5277 str = "32 bit wide SCSI"; 5278 break; 5279 case PI_WIDE_16: 5280 str = "16 bit wide SCSI"; 5281 break; 5282 case PI_SDTR_ABLE: 5283 str = "SDTR message"; 5284 break; 5285 case PI_LINKED_CDB: 5286 str = "linked CDBs"; 5287 break; 5288 case PI_TAG_ABLE: 5289 str = "tag queue messages"; 5290 break; 5291 case PI_SOFT_RST: 5292 str = "soft reset alternative"; 5293 break; 5294 case PI_SATAPM: 5295 str = "SATA Port Multiplier"; 5296 break; 5297 default: 5298 str = "unknown PI bit set"; 5299 break; 5300 } 5301 fprintf(stdout, "%s\n", str); 5302 } 5303 5304 for (i = 1; i < UINT32_MAX; i = i << 1) { 5305 const char *str; 5306 5307 if ((i & cpi->hba_misc) == 0) 5308 continue; 5309 5310 fprintf(stdout, "%s ", adapter_str); 5311 5312 switch(i) { 5313 case PIM_SCANHILO: 5314 str = "bus scans from high ID to low ID"; 5315 break; 5316 case PIM_NOREMOVE: 5317 str = "removable devices not included in scan"; 5318 break; 5319 case PIM_NOINITIATOR: 5320 str = "initiator role not supported"; 5321 break; 5322 case PIM_NOBUSRESET: 5323 str = "user has disabled initial BUS RESET or" 5324 " controller is in target/mixed mode"; 5325 break; 5326 case PIM_NO_6_BYTE: 5327 str = "do not send 6-byte commands"; 5328 break; 5329 case PIM_SEQSCAN: 5330 str = "scan bus sequentially"; 5331 break; 5332 default: 5333 str = "unknown PIM bit set"; 5334 break; 5335 } 5336 fprintf(stdout, "%s\n", str); 5337 } 5338 5339 for (i = 1; i < UINT16_MAX; i = i << 1) { 5340 const char *str; 5341 5342 if ((i & cpi->target_sprt) == 0) 5343 continue; 5344 5345 fprintf(stdout, "%s supports ", adapter_str); 5346 switch(i) { 5347 case PIT_PROCESSOR: 5348 str = "target mode processor mode"; 5349 break; 5350 case PIT_PHASE: 5351 str = "target mode phase cog. mode"; 5352 break; 5353 case PIT_DISCONNECT: 5354 str = "disconnects in target mode"; 5355 break; 5356 case PIT_TERM_IO: 5357 str = "terminate I/O message in target mode"; 5358 break; 5359 case PIT_GRP_6: 5360 str = "group 6 commands in target mode"; 5361 break; 5362 case PIT_GRP_7: 5363 str = "group 7 commands in target mode"; 5364 break; 5365 default: 5366 str = "unknown PIT bit set"; 5367 break; 5368 } 5369 5370 fprintf(stdout, "%s\n", str); 5371 } 5372 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str, 5373 cpi->hba_eng_cnt); 5374 fprintf(stdout, "%s maximum target: %d\n", adapter_str, 5375 cpi->max_target); 5376 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str, 5377 cpi->max_lun); 5378 fprintf(stdout, "%s highest path ID in subsystem: %d\n", 5379 adapter_str, cpi->hpath_id); 5380 fprintf(stdout, "%s initiator ID: %d\n", adapter_str, 5381 cpi->initiator_id); 5382 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid); 5383 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid); 5384 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n", 5385 adapter_str, cpi->hba_vendor); 5386 fprintf(stdout, "%s HBA device ID: 0x%04x\n", 5387 adapter_str, cpi->hba_device); 5388 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n", 5389 adapter_str, cpi->hba_subvendor); 5390 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n", 5391 adapter_str, cpi->hba_subdevice); 5392 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id); 5393 fprintf(stdout, "%s base transfer speed: ", adapter_str); 5394 if (cpi->base_transfer_speed > 1000) 5395 fprintf(stdout, "%d.%03dMB/sec\n", 5396 cpi->base_transfer_speed / 1000, 5397 cpi->base_transfer_speed % 1000); 5398 else 5399 fprintf(stdout, "%dKB/sec\n", 5400 (cpi->base_transfer_speed % 1000) * 1000); 5401 fprintf(stdout, "%s maximum transfer size: %u bytes\n", 5402 adapter_str, cpi->maxio); 5403} 5404 5405static int 5406get_print_cts(struct cam_device *device, int user_settings, int quiet, 5407 struct ccb_trans_settings *cts) 5408{ 5409 int retval; 5410 union ccb *ccb; 5411 5412 retval = 0; 5413 ccb = cam_getccb(device); 5414 5415 if (ccb == NULL) { 5416 warnx("get_print_cts: error allocating ccb"); 5417 return(1); 5418 } 5419 5420 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts); 5421 5422 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 5423 5424 if (user_settings == 0) 5425 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS; 5426 else 5427 ccb->cts.type = CTS_TYPE_USER_SETTINGS; 5428 5429 if (cam_send_ccb(device, ccb) < 0) { 5430 perror("error sending XPT_GET_TRAN_SETTINGS CCB"); 5431 if (arglist & CAM_ARG_VERBOSE) 5432 cam_error_print(device, ccb, CAM_ESF_ALL, 5433 CAM_EPF_ALL, stderr); 5434 retval = 1; 5435 goto get_print_cts_bailout; 5436 } 5437 5438 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 5439 warnx("XPT_GET_TRANS_SETTINGS CCB failed"); 5440 if (arglist & CAM_ARG_VERBOSE) 5441 cam_error_print(device, ccb, CAM_ESF_ALL, 5442 CAM_EPF_ALL, stderr); 5443 retval = 1; 5444 goto get_print_cts_bailout; 5445 } 5446 5447 if (quiet == 0) 5448 cts_print(device, &ccb->cts); 5449 5450 if (cts != NULL) 5451 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings)); 5452 5453get_print_cts_bailout: 5454 5455 cam_freeccb(ccb); 5456 5457 return(retval); 5458} 5459 5460static int 5461ratecontrol(struct cam_device *device, int task_attr, int retry_count, 5462 int timeout, int argc, char **argv, char *combinedopt) 5463{ 5464 int c; 5465 union ccb *ccb; 5466 int user_settings = 0; 5467 int retval = 0; 5468 int disc_enable = -1, tag_enable = -1; 5469 int mode = -1; 5470 int offset = -1; 5471 double syncrate = -1; 5472 int bus_width = -1; 5473 int quiet = 0; 5474 int change_settings = 0, send_tur = 0; 5475 struct ccb_pathinq cpi; 5476 5477 ccb = cam_getccb(device); 5478 if (ccb == NULL) { 5479 warnx("ratecontrol: error allocating ccb"); 5480 return(1); 5481 } 5482 while ((c = getopt(argc, argv, combinedopt)) != -1) { 5483 switch(c){ 5484 case 'a': 5485 send_tur = 1; 5486 break; 5487 case 'c': 5488 user_settings = 0; 5489 break; 5490 case 'D': 5491 if (strncasecmp(optarg, "enable", 6) == 0) 5492 disc_enable = 1; 5493 else if (strncasecmp(optarg, "disable", 7) == 0) 5494 disc_enable = 0; 5495 else { 5496 warnx("-D argument \"%s\" is unknown", optarg); 5497 retval = 1; 5498 goto ratecontrol_bailout; 5499 } 5500 change_settings = 1; 5501 break; 5502 case 'M': 5503 mode = ata_string2mode(optarg); 5504 if (mode < 0) { 5505 warnx("unknown mode '%s'", optarg); 5506 retval = 1; 5507 goto ratecontrol_bailout; 5508 } 5509 change_settings = 1; 5510 break; 5511 case 'O': 5512 offset = strtol(optarg, NULL, 0); 5513 if (offset < 0) { 5514 warnx("offset value %d is < 0", offset); 5515 retval = 1; 5516 goto ratecontrol_bailout; 5517 } 5518 change_settings = 1; 5519 break; 5520 case 'q': 5521 quiet++; 5522 break; 5523 case 'R': 5524 syncrate = atof(optarg); 5525 if (syncrate < 0) { 5526 warnx("sync rate %f is < 0", syncrate); 5527 retval = 1; 5528 goto ratecontrol_bailout; 5529 } 5530 change_settings = 1; 5531 break; 5532 case 'T': 5533 if (strncasecmp(optarg, "enable", 6) == 0) 5534 tag_enable = 1; 5535 else if (strncasecmp(optarg, "disable", 7) == 0) 5536 tag_enable = 0; 5537 else { 5538 warnx("-T argument \"%s\" is unknown", optarg); 5539 retval = 1; 5540 goto ratecontrol_bailout; 5541 } 5542 change_settings = 1; 5543 break; 5544 case 'U': 5545 user_settings = 1; 5546 break; 5547 case 'W': 5548 bus_width = strtol(optarg, NULL, 0); 5549 if (bus_width < 0) { 5550 warnx("bus width %d is < 0", bus_width); 5551 retval = 1; 5552 goto ratecontrol_bailout; 5553 } 5554 change_settings = 1; 5555 break; 5556 default: 5557 break; 5558 } 5559 } 5560 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi); 5561 /* 5562 * Grab path inquiry information, so we can determine whether 5563 * or not the initiator is capable of the things that the user 5564 * requests. 5565 */ 5566 ccb->ccb_h.func_code = XPT_PATH_INQ; 5567 if (cam_send_ccb(device, ccb) < 0) { 5568 perror("error sending XPT_PATH_INQ CCB"); 5569 if (arglist & CAM_ARG_VERBOSE) { 5570 cam_error_print(device, ccb, CAM_ESF_ALL, 5571 CAM_EPF_ALL, stderr); 5572 } 5573 retval = 1; 5574 goto ratecontrol_bailout; 5575 } 5576 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 5577 warnx("XPT_PATH_INQ CCB failed"); 5578 if (arglist & CAM_ARG_VERBOSE) { 5579 cam_error_print(device, ccb, CAM_ESF_ALL, 5580 CAM_EPF_ALL, stderr); 5581 } 5582 retval = 1; 5583 goto ratecontrol_bailout; 5584 } 5585 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq)); 5586 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts); 5587 if (quiet == 0) { 5588 fprintf(stdout, "%s parameters:\n", 5589 user_settings ? "User" : "Current"); 5590 } 5591 retval = get_print_cts(device, user_settings, quiet, &ccb->cts); 5592 if (retval != 0) 5593 goto ratecontrol_bailout; 5594 5595 if (arglist & CAM_ARG_VERBOSE) 5596 cpi_print(&cpi); 5597 5598 if (change_settings) { 5599 int didsettings = 0; 5600 struct ccb_trans_settings_spi *spi = NULL; 5601 struct ccb_trans_settings_pata *pata = NULL; 5602 struct ccb_trans_settings_sata *sata = NULL; 5603 struct ccb_trans_settings_ata *ata = NULL; 5604 struct ccb_trans_settings_scsi *scsi = NULL; 5605 5606 if (ccb->cts.transport == XPORT_SPI) 5607 spi = &ccb->cts.xport_specific.spi; 5608 if (ccb->cts.transport == XPORT_ATA) 5609 pata = &ccb->cts.xport_specific.ata; 5610 if (ccb->cts.transport == XPORT_SATA) 5611 sata = &ccb->cts.xport_specific.sata; 5612 if (ccb->cts.protocol == PROTO_ATA) 5613 ata = &ccb->cts.proto_specific.ata; 5614 if (ccb->cts.protocol == PROTO_SCSI) 5615 scsi = &ccb->cts.proto_specific.scsi; 5616 ccb->cts.xport_specific.valid = 0; 5617 ccb->cts.proto_specific.valid = 0; 5618 if (spi && disc_enable != -1) { 5619 spi->valid |= CTS_SPI_VALID_DISC; 5620 if (disc_enable == 0) 5621 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 5622 else 5623 spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 5624 didsettings++; 5625 } 5626 if (tag_enable != -1) { 5627 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) { 5628 warnx("HBA does not support tagged queueing, " 5629 "so you cannot modify tag settings"); 5630 retval = 1; 5631 goto ratecontrol_bailout; 5632 } 5633 if (ata) { 5634 ata->valid |= CTS_SCSI_VALID_TQ; 5635 if (tag_enable == 0) 5636 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB; 5637 else 5638 ata->flags |= CTS_ATA_FLAGS_TAG_ENB; 5639 didsettings++; 5640 } else if (scsi) { 5641 scsi->valid |= CTS_SCSI_VALID_TQ; 5642 if (tag_enable == 0) 5643 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 5644 else 5645 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 5646 didsettings++; 5647 } 5648 } 5649 if (spi && offset != -1) { 5650 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 5651 warnx("HBA is not capable of changing offset"); 5652 retval = 1; 5653 goto ratecontrol_bailout; 5654 } 5655 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 5656 spi->sync_offset = offset; 5657 didsettings++; 5658 } 5659 if (spi && syncrate != -1) { 5660 int prelim_sync_period; 5661 5662 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 5663 warnx("HBA is not capable of changing " 5664 "transfer rates"); 5665 retval = 1; 5666 goto ratecontrol_bailout; 5667 } 5668 spi->valid |= CTS_SPI_VALID_SYNC_RATE; 5669 /* 5670 * The sync rate the user gives us is in MHz. 5671 * We need to translate it into KHz for this 5672 * calculation. 5673 */ 5674 syncrate *= 1000; 5675 /* 5676 * Next, we calculate a "preliminary" sync period 5677 * in tenths of a nanosecond. 5678 */ 5679 if (syncrate == 0) 5680 prelim_sync_period = 0; 5681 else 5682 prelim_sync_period = 10000000 / syncrate; 5683 spi->sync_period = 5684 scsi_calc_syncparam(prelim_sync_period); 5685 didsettings++; 5686 } 5687 if (sata && syncrate != -1) { 5688 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 5689 warnx("HBA is not capable of changing " 5690 "transfer rates"); 5691 retval = 1; 5692 goto ratecontrol_bailout; 5693 } 5694 if (!user_settings) { 5695 warnx("You can modify only user rate " 5696 "settings for SATA"); 5697 retval = 1; 5698 goto ratecontrol_bailout; 5699 } 5700 sata->revision = ata_speed2revision(syncrate * 100); 5701 if (sata->revision < 0) { 5702 warnx("Invalid rate %f", syncrate); 5703 retval = 1; 5704 goto ratecontrol_bailout; 5705 } 5706 sata->valid |= CTS_SATA_VALID_REVISION; 5707 didsettings++; 5708 } 5709 if ((pata || sata) && mode != -1) { 5710 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 5711 warnx("HBA is not capable of changing " 5712 "transfer rates"); 5713 retval = 1; 5714 goto ratecontrol_bailout; 5715 } 5716 if (!user_settings) { 5717 warnx("You can modify only user mode " 5718 "settings for ATA/SATA"); 5719 retval = 1; 5720 goto ratecontrol_bailout; 5721 } 5722 if (pata) { 5723 pata->mode = mode; 5724 pata->valid |= CTS_ATA_VALID_MODE; 5725 } else { 5726 sata->mode = mode; 5727 sata->valid |= CTS_SATA_VALID_MODE; 5728 } 5729 didsettings++; 5730 } 5731 /* 5732 * The bus_width argument goes like this: 5733 * 0 == 8 bit 5734 * 1 == 16 bit 5735 * 2 == 32 bit 5736 * Therefore, if you shift the number of bits given on the 5737 * command line right by 4, you should get the correct 5738 * number. 5739 */ 5740 if (spi && bus_width != -1) { 5741 /* 5742 * We might as well validate things here with a 5743 * decipherable error message, rather than what 5744 * will probably be an indecipherable error message 5745 * by the time it gets back to us. 5746 */ 5747 if ((bus_width == 16) 5748 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) { 5749 warnx("HBA does not support 16 bit bus width"); 5750 retval = 1; 5751 goto ratecontrol_bailout; 5752 } else if ((bus_width == 32) 5753 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) { 5754 warnx("HBA does not support 32 bit bus width"); 5755 retval = 1; 5756 goto ratecontrol_bailout; 5757 } else if ((bus_width != 8) 5758 && (bus_width != 16) 5759 && (bus_width != 32)) { 5760 warnx("Invalid bus width %d", bus_width); 5761 retval = 1; 5762 goto ratecontrol_bailout; 5763 } 5764 spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 5765 spi->bus_width = bus_width >> 4; 5766 didsettings++; 5767 } 5768 if (didsettings == 0) { 5769 goto ratecontrol_bailout; 5770 } 5771 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 5772 if (cam_send_ccb(device, ccb) < 0) { 5773 perror("error sending XPT_SET_TRAN_SETTINGS CCB"); 5774 if (arglist & CAM_ARG_VERBOSE) { 5775 cam_error_print(device, ccb, CAM_ESF_ALL, 5776 CAM_EPF_ALL, stderr); 5777 } 5778 retval = 1; 5779 goto ratecontrol_bailout; 5780 } 5781 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 5782 warnx("XPT_SET_TRANS_SETTINGS CCB failed"); 5783 if (arglist & CAM_ARG_VERBOSE) { 5784 cam_error_print(device, ccb, CAM_ESF_ALL, 5785 CAM_EPF_ALL, stderr); 5786 } 5787 retval = 1; 5788 goto ratecontrol_bailout; 5789 } 5790 } 5791 if (send_tur) { 5792 retval = testunitready(device, task_attr, retry_count, timeout, 5793 (arglist & CAM_ARG_VERBOSE) ? 0 : 1); 5794 /* 5795 * If the TUR didn't succeed, just bail. 5796 */ 5797 if (retval != 0) { 5798 if (quiet == 0) 5799 fprintf(stderr, "Test Unit Ready failed\n"); 5800 goto ratecontrol_bailout; 5801 } 5802 } 5803 if ((change_settings || send_tur) && !quiet && 5804 (ccb->cts.transport == XPORT_ATA || 5805 ccb->cts.transport == XPORT_SATA || send_tur)) { 5806 fprintf(stdout, "New parameters:\n"); 5807 retval = get_print_cts(device, user_settings, 0, NULL); 5808 } 5809 5810ratecontrol_bailout: 5811 cam_freeccb(ccb); 5812 return(retval); 5813} 5814 5815static int 5816scsiformat(struct cam_device *device, int argc, char **argv, 5817 char *combinedopt, int task_attr, int retry_count, int timeout) 5818{ 5819 union ccb *ccb; 5820 int c; 5821 int ycount = 0, quiet = 0; 5822 int error = 0, retval = 0; 5823 int use_timeout = 10800 * 1000; 5824 int immediate = 1; 5825 struct format_defect_list_header fh; 5826 u_int8_t *data_ptr = NULL; 5827 u_int32_t dxfer_len = 0; 5828 u_int8_t byte2 = 0; 5829 int num_warnings = 0; 5830 int reportonly = 0; 5831 5832 ccb = cam_getccb(device); 5833 5834 if (ccb == NULL) { 5835 warnx("scsiformat: error allocating ccb"); 5836 return(1); 5837 } 5838 5839 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 5840 5841 while ((c = getopt(argc, argv, combinedopt)) != -1) { 5842 switch(c) { 5843 case 'q': 5844 quiet++; 5845 break; 5846 case 'r': 5847 reportonly = 1; 5848 break; 5849 case 'w': 5850 immediate = 0; 5851 break; 5852 case 'y': 5853 ycount++; 5854 break; 5855 } 5856 } 5857 5858 if (reportonly) 5859 goto doreport; 5860 5861 if (quiet == 0) { 5862 fprintf(stdout, "You are about to REMOVE ALL DATA from the " 5863 "following device:\n"); 5864 5865 error = scsidoinquiry(device, argc, argv, combinedopt, 5866 task_attr, retry_count, timeout); 5867 5868 if (error != 0) { 5869 warnx("scsiformat: error sending inquiry"); 5870 goto scsiformat_bailout; 5871 } 5872 } 5873 5874 if (ycount == 0) { 5875 if (!get_confirmation()) { 5876 error = 1; 5877 goto scsiformat_bailout; 5878 } 5879 } 5880 5881 if (timeout != 0) 5882 use_timeout = timeout; 5883 5884 if (quiet == 0) { 5885 fprintf(stdout, "Current format timeout is %d seconds\n", 5886 use_timeout / 1000); 5887 } 5888 5889 /* 5890 * If the user hasn't disabled questions and didn't specify a 5891 * timeout on the command line, ask them if they want the current 5892 * timeout. 5893 */ 5894 if ((ycount == 0) 5895 && (timeout == 0)) { 5896 char str[1024]; 5897 int new_timeout = 0; 5898 5899 fprintf(stdout, "Enter new timeout in seconds or press\n" 5900 "return to keep the current timeout [%d] ", 5901 use_timeout / 1000); 5902 5903 if (fgets(str, sizeof(str), stdin) != NULL) { 5904 if (str[0] != '\0') 5905 new_timeout = atoi(str); 5906 } 5907 5908 if (new_timeout != 0) { 5909 use_timeout = new_timeout * 1000; 5910 fprintf(stdout, "Using new timeout value %d\n", 5911 use_timeout / 1000); 5912 } 5913 } 5914 5915 /* 5916 * Keep this outside the if block below to silence any unused 5917 * variable warnings. 5918 */ 5919 bzero(&fh, sizeof(fh)); 5920 5921 /* 5922 * If we're in immediate mode, we've got to include the format 5923 * header 5924 */ 5925 if (immediate != 0) { 5926 fh.byte2 = FU_DLH_IMMED; 5927 data_ptr = (u_int8_t *)&fh; 5928 dxfer_len = sizeof(fh); 5929 byte2 = FU_FMT_DATA; 5930 } else if (quiet == 0) { 5931 fprintf(stdout, "Formatting..."); 5932 fflush(stdout); 5933 } 5934 5935 scsi_format_unit(&ccb->csio, 5936 /* retries */ retry_count, 5937 /* cbfcnp */ NULL, 5938 /* tag_action */ task_attr, 5939 /* byte2 */ byte2, 5940 /* ileave */ 0, 5941 /* data_ptr */ data_ptr, 5942 /* dxfer_len */ dxfer_len, 5943 /* sense_len */ SSD_FULL_SIZE, 5944 /* timeout */ use_timeout); 5945 5946 /* Disable freezing the device queue */ 5947 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 5948 5949 if (arglist & CAM_ARG_ERR_RECOVER) 5950 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 5951 5952 if (((retval = cam_send_ccb(device, ccb)) < 0) 5953 || ((immediate == 0) 5954 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) { 5955 const char errstr[] = "error sending format command"; 5956 5957 if (retval < 0) 5958 warn(errstr); 5959 else 5960 warnx(errstr); 5961 5962 if (arglist & CAM_ARG_VERBOSE) { 5963 cam_error_print(device, ccb, CAM_ESF_ALL, 5964 CAM_EPF_ALL, stderr); 5965 } 5966 error = 1; 5967 goto scsiformat_bailout; 5968 } 5969 5970 /* 5971 * If we ran in non-immediate mode, we already checked for errors 5972 * above and printed out any necessary information. If we're in 5973 * immediate mode, we need to loop through and get status 5974 * information periodically. 5975 */ 5976 if (immediate == 0) { 5977 if (quiet == 0) { 5978 fprintf(stdout, "Format Complete\n"); 5979 } 5980 goto scsiformat_bailout; 5981 } 5982 5983doreport: 5984 do { 5985 cam_status status; 5986 5987 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 5988 5989 /* 5990 * There's really no need to do error recovery or 5991 * retries here, since we're just going to sit in a 5992 * loop and wait for the device to finish formatting. 5993 */ 5994 scsi_test_unit_ready(&ccb->csio, 5995 /* retries */ 0, 5996 /* cbfcnp */ NULL, 5997 /* tag_action */ task_attr, 5998 /* sense_len */ SSD_FULL_SIZE, 5999 /* timeout */ 5000); 6000 6001 /* Disable freezing the device queue */ 6002 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 6003 6004 retval = cam_send_ccb(device, ccb); 6005 6006 /* 6007 * If we get an error from the ioctl, bail out. SCSI 6008 * errors are expected. 6009 */ 6010 if (retval < 0) { 6011 warn("error sending CAMIOCOMMAND ioctl"); 6012 if (arglist & CAM_ARG_VERBOSE) { 6013 cam_error_print(device, ccb, CAM_ESF_ALL, 6014 CAM_EPF_ALL, stderr); 6015 } 6016 error = 1; 6017 goto scsiformat_bailout; 6018 } 6019 6020 status = ccb->ccb_h.status & CAM_STATUS_MASK; 6021 6022 if ((status != CAM_REQ_CMP) 6023 && (status == CAM_SCSI_STATUS_ERROR) 6024 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { 6025 struct scsi_sense_data *sense; 6026 int error_code, sense_key, asc, ascq; 6027 6028 sense = &ccb->csio.sense_data; 6029 scsi_extract_sense_len(sense, ccb->csio.sense_len - 6030 ccb->csio.sense_resid, &error_code, &sense_key, 6031 &asc, &ascq, /*show_errors*/ 1); 6032 6033 /* 6034 * According to the SCSI-2 and SCSI-3 specs, a 6035 * drive that is in the middle of a format should 6036 * return NOT READY with an ASC of "logical unit 6037 * not ready, format in progress". The sense key 6038 * specific bytes will then be a progress indicator. 6039 */ 6040 if ((sense_key == SSD_KEY_NOT_READY) 6041 && (asc == 0x04) && (ascq == 0x04)) { 6042 uint8_t sks[3]; 6043 6044 if ((scsi_get_sks(sense, ccb->csio.sense_len - 6045 ccb->csio.sense_resid, sks) == 0) 6046 && (quiet == 0)) { 6047 uint32_t val; 6048 u_int64_t percentage; 6049 6050 val = scsi_2btoul(&sks[1]); 6051 percentage = 10000ull * val; 6052 6053 fprintf(stdout, 6054 "\rFormatting: %ju.%02u %% " 6055 "(%u/%d) done", 6056 (uintmax_t)(percentage / 6057 (0x10000 * 100)), 6058 (unsigned)((percentage / 6059 0x10000) % 100), 6060 val, 0x10000); 6061 fflush(stdout); 6062 } else if ((quiet == 0) 6063 && (++num_warnings <= 1)) { 6064 warnx("Unexpected SCSI Sense Key " 6065 "Specific value returned " 6066 "during format:"); 6067 scsi_sense_print(device, &ccb->csio, 6068 stderr); 6069 warnx("Unable to print status " 6070 "information, but format will " 6071 "proceed."); 6072 warnx("will exit when format is " 6073 "complete"); 6074 } 6075 sleep(1); 6076 } else { 6077 warnx("Unexpected SCSI error during format"); 6078 cam_error_print(device, ccb, CAM_ESF_ALL, 6079 CAM_EPF_ALL, stderr); 6080 error = 1; 6081 goto scsiformat_bailout; 6082 } 6083 6084 } else if (status != CAM_REQ_CMP) { 6085 warnx("Unexpected CAM status %#x", status); 6086 if (arglist & CAM_ARG_VERBOSE) 6087 cam_error_print(device, ccb, CAM_ESF_ALL, 6088 CAM_EPF_ALL, stderr); 6089 error = 1; 6090 goto scsiformat_bailout; 6091 } 6092 6093 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP); 6094 6095 if (quiet == 0) 6096 fprintf(stdout, "\nFormat Complete\n"); 6097 6098scsiformat_bailout: 6099 6100 cam_freeccb(ccb); 6101 6102 return(error); 6103} 6104 6105static int 6106scsisanitize(struct cam_device *device, int argc, char **argv, 6107 char *combinedopt, int task_attr, int retry_count, int timeout) 6108{ 6109 union ccb *ccb; 6110 u_int8_t action = 0; 6111 int c; 6112 int ycount = 0, quiet = 0; 6113 int error = 0, retval = 0; 6114 int use_timeout = 10800 * 1000; 6115 int immediate = 1; 6116 int invert = 0; 6117 int passes = 0; 6118 int ause = 0; 6119 int fd = -1; 6120 const char *pattern = NULL; 6121 u_int8_t *data_ptr = NULL; 6122 u_int32_t dxfer_len = 0; 6123 u_int8_t byte2 = 0; 6124 int num_warnings = 0; 6125 int reportonly = 0; 6126 6127 ccb = cam_getccb(device); 6128 6129 if (ccb == NULL) { 6130 warnx("scsisanitize: error allocating ccb"); 6131 return(1); 6132 } 6133 6134 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 6135 6136 while ((c = getopt(argc, argv, combinedopt)) != -1) { 6137 switch(c) { 6138 case 'a': 6139 if (strcasecmp(optarg, "overwrite") == 0) 6140 action = SSZ_SERVICE_ACTION_OVERWRITE; 6141 else if (strcasecmp(optarg, "block") == 0) 6142 action = SSZ_SERVICE_ACTION_BLOCK_ERASE; 6143 else if (strcasecmp(optarg, "crypto") == 0) 6144 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE; 6145 else if (strcasecmp(optarg, "exitfailure") == 0) 6146 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE; 6147 else { 6148 warnx("invalid service operation \"%s\"", 6149 optarg); 6150 error = 1; 6151 goto scsisanitize_bailout; 6152 } 6153 break; 6154 case 'c': 6155 passes = strtol(optarg, NULL, 0); 6156 if (passes < 1 || passes > 31) { 6157 warnx("invalid passes value %d", passes); 6158 error = 1; 6159 goto scsisanitize_bailout; 6160 } 6161 break; 6162 case 'I': 6163 invert = 1; 6164 break; 6165 case 'P': 6166 pattern = optarg; 6167 break; 6168 case 'q': 6169 quiet++; 6170 break; 6171 case 'U': 6172 ause = 1; 6173 break; 6174 case 'r': 6175 reportonly = 1; 6176 break; 6177 case 'w': 6178 immediate = 0; 6179 break; 6180 case 'y': 6181 ycount++; 6182 break; 6183 } 6184 } 6185 6186 if (reportonly) 6187 goto doreport; 6188 6189 if (action == 0) { 6190 warnx("an action is required"); 6191 error = 1; 6192 goto scsisanitize_bailout; 6193 } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) { 6194 struct scsi_sanitize_parameter_list *pl; 6195 struct stat sb; 6196 ssize_t sz, amt; 6197 6198 if (pattern == NULL) { 6199 warnx("overwrite action requires -P argument"); 6200 error = 1; 6201 goto scsisanitize_bailout; 6202 } 6203 fd = open(pattern, O_RDONLY); 6204 if (fd < 0) { 6205 warn("cannot open pattern file %s", pattern); 6206 error = 1; 6207 goto scsisanitize_bailout; 6208 } 6209 if (fstat(fd, &sb) < 0) { 6210 warn("cannot stat pattern file %s", pattern); 6211 error = 1; 6212 goto scsisanitize_bailout; 6213 } 6214 sz = sb.st_size; 6215 if (sz > SSZPL_MAX_PATTERN_LENGTH) { 6216 warnx("pattern file size exceeds maximum value %d", 6217 SSZPL_MAX_PATTERN_LENGTH); 6218 error = 1; 6219 goto scsisanitize_bailout; 6220 } 6221 dxfer_len = sizeof(*pl) + sz; 6222 data_ptr = calloc(1, dxfer_len); 6223 if (data_ptr == NULL) { 6224 warnx("cannot allocate parameter list buffer"); 6225 error = 1; 6226 goto scsisanitize_bailout; 6227 } 6228 6229 amt = read(fd, data_ptr + sizeof(*pl), sz); 6230 if (amt < 0) { 6231 warn("cannot read pattern file"); 6232 error = 1; 6233 goto scsisanitize_bailout; 6234 } else if (amt != sz) { 6235 warnx("short pattern file read"); 6236 error = 1; 6237 goto scsisanitize_bailout; 6238 } 6239 6240 pl = (struct scsi_sanitize_parameter_list *)data_ptr; 6241 if (passes == 0) 6242 pl->byte1 = 1; 6243 else 6244 pl->byte1 = passes; 6245 if (invert != 0) 6246 pl->byte1 |= SSZPL_INVERT; 6247 scsi_ulto2b(sz, pl->length); 6248 } else { 6249 const char *arg; 6250 6251 if (passes != 0) 6252 arg = "-c"; 6253 else if (invert != 0) 6254 arg = "-I"; 6255 else if (pattern != NULL) 6256 arg = "-P"; 6257 else 6258 arg = NULL; 6259 if (arg != NULL) { 6260 warnx("%s argument only valid with overwrite " 6261 "operation", arg); 6262 error = 1; 6263 goto scsisanitize_bailout; 6264 } 6265 } 6266 6267 if (quiet == 0) { 6268 fprintf(stdout, "You are about to REMOVE ALL DATA from the " 6269 "following device:\n"); 6270 6271 error = scsidoinquiry(device, argc, argv, combinedopt, 6272 task_attr, retry_count, timeout); 6273 6274 if (error != 0) { 6275 warnx("scsisanitize: error sending inquiry"); 6276 goto scsisanitize_bailout; 6277 } 6278 } 6279 6280 if (ycount == 0) { 6281 if (!get_confirmation()) { 6282 error = 1; 6283 goto scsisanitize_bailout; 6284 } 6285 } 6286 6287 if (timeout != 0) 6288 use_timeout = timeout; 6289 6290 if (quiet == 0) { 6291 fprintf(stdout, "Current sanitize timeout is %d seconds\n", 6292 use_timeout / 1000); 6293 } 6294 6295 /* 6296 * If the user hasn't disabled questions and didn't specify a 6297 * timeout on the command line, ask them if they want the current 6298 * timeout. 6299 */ 6300 if ((ycount == 0) 6301 && (timeout == 0)) { 6302 char str[1024]; 6303 int new_timeout = 0; 6304 6305 fprintf(stdout, "Enter new timeout in seconds or press\n" 6306 "return to keep the current timeout [%d] ", 6307 use_timeout / 1000); 6308 6309 if (fgets(str, sizeof(str), stdin) != NULL) { 6310 if (str[0] != '\0') 6311 new_timeout = atoi(str); 6312 } 6313 6314 if (new_timeout != 0) { 6315 use_timeout = new_timeout * 1000; 6316 fprintf(stdout, "Using new timeout value %d\n", 6317 use_timeout / 1000); 6318 } 6319 } 6320 6321 byte2 = action; 6322 if (ause != 0) 6323 byte2 |= SSZ_UNRESTRICTED_EXIT; 6324 if (immediate != 0) 6325 byte2 |= SSZ_IMMED; 6326 6327 scsi_sanitize(&ccb->csio, 6328 /* retries */ retry_count, 6329 /* cbfcnp */ NULL, 6330 /* tag_action */ task_attr, 6331 /* byte2 */ byte2, 6332 /* control */ 0, 6333 /* data_ptr */ data_ptr, 6334 /* dxfer_len */ dxfer_len, 6335 /* sense_len */ SSD_FULL_SIZE, 6336 /* timeout */ use_timeout); 6337 6338 /* Disable freezing the device queue */ 6339 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 6340 6341 if (arglist & CAM_ARG_ERR_RECOVER) 6342 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 6343 6344 if (cam_send_ccb(device, ccb) < 0) { 6345 warn("error sending sanitize command"); 6346 error = 1; 6347 goto scsisanitize_bailout; 6348 } 6349 6350 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 6351 struct scsi_sense_data *sense; 6352 int error_code, sense_key, asc, ascq; 6353 6354 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 6355 CAM_SCSI_STATUS_ERROR) { 6356 sense = &ccb->csio.sense_data; 6357 scsi_extract_sense_len(sense, ccb->csio.sense_len - 6358 ccb->csio.sense_resid, &error_code, &sense_key, 6359 &asc, &ascq, /*show_errors*/ 1); 6360 6361 if (sense_key == SSD_KEY_ILLEGAL_REQUEST && 6362 asc == 0x20 && ascq == 0x00) 6363 warnx("sanitize is not supported by " 6364 "this device"); 6365 else 6366 warnx("error sanitizing this device"); 6367 } else 6368 warnx("error sanitizing this device"); 6369 6370 if (arglist & CAM_ARG_VERBOSE) { 6371 cam_error_print(device, ccb, CAM_ESF_ALL, 6372 CAM_EPF_ALL, stderr); 6373 } 6374 error = 1; 6375 goto scsisanitize_bailout; 6376 } 6377 6378 /* 6379 * If we ran in non-immediate mode, we already checked for errors 6380 * above and printed out any necessary information. If we're in 6381 * immediate mode, we need to loop through and get status 6382 * information periodically. 6383 */ 6384 if (immediate == 0) { 6385 if (quiet == 0) { 6386 fprintf(stdout, "Sanitize Complete\n"); 6387 } 6388 goto scsisanitize_bailout; 6389 } 6390 6391doreport: 6392 do { 6393 cam_status status; 6394 6395 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 6396 6397 /* 6398 * There's really no need to do error recovery or 6399 * retries here, since we're just going to sit in a 6400 * loop and wait for the device to finish sanitizing. 6401 */ 6402 scsi_test_unit_ready(&ccb->csio, 6403 /* retries */ 0, 6404 /* cbfcnp */ NULL, 6405 /* tag_action */ task_attr, 6406 /* sense_len */ SSD_FULL_SIZE, 6407 /* timeout */ 5000); 6408 6409 /* Disable freezing the device queue */ 6410 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 6411 6412 retval = cam_send_ccb(device, ccb); 6413 6414 /* 6415 * If we get an error from the ioctl, bail out. SCSI 6416 * errors are expected. 6417 */ 6418 if (retval < 0) { 6419 warn("error sending CAMIOCOMMAND ioctl"); 6420 if (arglist & CAM_ARG_VERBOSE) { 6421 cam_error_print(device, ccb, CAM_ESF_ALL, 6422 CAM_EPF_ALL, stderr); 6423 } 6424 error = 1; 6425 goto scsisanitize_bailout; 6426 } 6427 6428 status = ccb->ccb_h.status & CAM_STATUS_MASK; 6429 6430 if ((status != CAM_REQ_CMP) 6431 && (status == CAM_SCSI_STATUS_ERROR) 6432 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { 6433 struct scsi_sense_data *sense; 6434 int error_code, sense_key, asc, ascq; 6435 6436 sense = &ccb->csio.sense_data; 6437 scsi_extract_sense_len(sense, ccb->csio.sense_len - 6438 ccb->csio.sense_resid, &error_code, &sense_key, 6439 &asc, &ascq, /*show_errors*/ 1); 6440 6441 /* 6442 * According to the SCSI-3 spec, a drive that is in the 6443 * middle of a sanitize should return NOT READY with an 6444 * ASC of "logical unit not ready, sanitize in 6445 * progress". The sense key specific bytes will then 6446 * be a progress indicator. 6447 */ 6448 if ((sense_key == SSD_KEY_NOT_READY) 6449 && (asc == 0x04) && (ascq == 0x1b)) { 6450 uint8_t sks[3]; 6451 6452 if ((scsi_get_sks(sense, ccb->csio.sense_len - 6453 ccb->csio.sense_resid, sks) == 0) 6454 && (quiet == 0)) { 6455 int val; 6456 u_int64_t percentage; 6457 6458 val = scsi_2btoul(&sks[1]); 6459 percentage = 10000 * val; 6460 6461 fprintf(stdout, 6462 "\rSanitizing: %ju.%02u %% " 6463 "(%d/%d) done", 6464 (uintmax_t)(percentage / 6465 (0x10000 * 100)), 6466 (unsigned)((percentage / 6467 0x10000) % 100), 6468 val, 0x10000); 6469 fflush(stdout); 6470 } else if ((quiet == 0) 6471 && (++num_warnings <= 1)) { 6472 warnx("Unexpected SCSI Sense Key " 6473 "Specific value returned " 6474 "during sanitize:"); 6475 scsi_sense_print(device, &ccb->csio, 6476 stderr); 6477 warnx("Unable to print status " 6478 "information, but sanitze will " 6479 "proceed."); 6480 warnx("will exit when sanitize is " 6481 "complete"); 6482 } 6483 sleep(1); 6484 } else { 6485 warnx("Unexpected SCSI error during sanitize"); 6486 cam_error_print(device, ccb, CAM_ESF_ALL, 6487 CAM_EPF_ALL, stderr); 6488 error = 1; 6489 goto scsisanitize_bailout; 6490 } 6491 6492 } else if (status != CAM_REQ_CMP) { 6493 warnx("Unexpected CAM status %#x", status); 6494 if (arglist & CAM_ARG_VERBOSE) 6495 cam_error_print(device, ccb, CAM_ESF_ALL, 6496 CAM_EPF_ALL, stderr); 6497 error = 1; 6498 goto scsisanitize_bailout; 6499 } 6500 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP); 6501 6502 if (quiet == 0) 6503 fprintf(stdout, "\nSanitize Complete\n"); 6504 6505scsisanitize_bailout: 6506 if (fd >= 0) 6507 close(fd); 6508 if (data_ptr != NULL) 6509 free(data_ptr); 6510 cam_freeccb(ccb); 6511 6512 return(error); 6513} 6514 6515static int 6516scsireportluns(struct cam_device *device, int argc, char **argv, 6517 char *combinedopt, int task_attr, int retry_count, int timeout) 6518{ 6519 union ccb *ccb; 6520 int c, countonly, lunsonly; 6521 struct scsi_report_luns_data *lundata; 6522 int alloc_len; 6523 uint8_t report_type; 6524 uint32_t list_len, i, j; 6525 int retval; 6526 6527 retval = 0; 6528 lundata = NULL; 6529 report_type = RPL_REPORT_DEFAULT; 6530 ccb = cam_getccb(device); 6531 6532 if (ccb == NULL) { 6533 warnx("%s: error allocating ccb", __func__); 6534 return (1); 6535 } 6536 6537 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 6538 6539 countonly = 0; 6540 lunsonly = 0; 6541 6542 while ((c = getopt(argc, argv, combinedopt)) != -1) { 6543 switch (c) { 6544 case 'c': 6545 countonly++; 6546 break; 6547 case 'l': 6548 lunsonly++; 6549 break; 6550 case 'r': 6551 if (strcasecmp(optarg, "default") == 0) 6552 report_type = RPL_REPORT_DEFAULT; 6553 else if (strcasecmp(optarg, "wellknown") == 0) 6554 report_type = RPL_REPORT_WELLKNOWN; 6555 else if (strcasecmp(optarg, "all") == 0) 6556 report_type = RPL_REPORT_ALL; 6557 else { 6558 warnx("%s: invalid report type \"%s\"", 6559 __func__, optarg); 6560 retval = 1; 6561 goto bailout; 6562 } 6563 break; 6564 default: 6565 break; 6566 } 6567 } 6568 6569 if ((countonly != 0) 6570 && (lunsonly != 0)) { 6571 warnx("%s: you can only specify one of -c or -l", __func__); 6572 retval = 1; 6573 goto bailout; 6574 } 6575 /* 6576 * According to SPC-4, the allocation length must be at least 16 6577 * bytes -- enough for the header and one LUN. 6578 */ 6579 alloc_len = sizeof(*lundata) + 8; 6580 6581retry: 6582 6583 lundata = malloc(alloc_len); 6584 6585 if (lundata == NULL) { 6586 warn("%s: error mallocing %d bytes", __func__, alloc_len); 6587 retval = 1; 6588 goto bailout; 6589 } 6590 6591 scsi_report_luns(&ccb->csio, 6592 /*retries*/ retry_count, 6593 /*cbfcnp*/ NULL, 6594 /*tag_action*/ task_attr, 6595 /*select_report*/ report_type, 6596 /*rpl_buf*/ lundata, 6597 /*alloc_len*/ alloc_len, 6598 /*sense_len*/ SSD_FULL_SIZE, 6599 /*timeout*/ timeout ? timeout : 5000); 6600 6601 /* Disable freezing the device queue */ 6602 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 6603 6604 if (arglist & CAM_ARG_ERR_RECOVER) 6605 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 6606 6607 if (cam_send_ccb(device, ccb) < 0) { 6608 warn("error sending REPORT LUNS command"); 6609 6610 if (arglist & CAM_ARG_VERBOSE) 6611 cam_error_print(device, ccb, CAM_ESF_ALL, 6612 CAM_EPF_ALL, stderr); 6613 6614 retval = 1; 6615 goto bailout; 6616 } 6617 6618 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 6619 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 6620 retval = 1; 6621 goto bailout; 6622 } 6623 6624 6625 list_len = scsi_4btoul(lundata->length); 6626 6627 /* 6628 * If we need to list the LUNs, and our allocation 6629 * length was too short, reallocate and retry. 6630 */ 6631 if ((countonly == 0) 6632 && (list_len > (alloc_len - sizeof(*lundata)))) { 6633 alloc_len = list_len + sizeof(*lundata); 6634 free(lundata); 6635 goto retry; 6636 } 6637 6638 if (lunsonly == 0) 6639 fprintf(stdout, "%u LUN%s found\n", list_len / 8, 6640 ((list_len / 8) > 1) ? "s" : ""); 6641 6642 if (countonly != 0) 6643 goto bailout; 6644 6645 for (i = 0; i < (list_len / 8); i++) { 6646 int no_more; 6647 6648 no_more = 0; 6649 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) { 6650 if (j != 0) 6651 fprintf(stdout, ","); 6652 switch (lundata->luns[i].lundata[j] & 6653 RPL_LUNDATA_ATYP_MASK) { 6654 case RPL_LUNDATA_ATYP_PERIPH: 6655 if ((lundata->luns[i].lundata[j] & 6656 RPL_LUNDATA_PERIPH_BUS_MASK) != 0) 6657 fprintf(stdout, "%d:", 6658 lundata->luns[i].lundata[j] & 6659 RPL_LUNDATA_PERIPH_BUS_MASK); 6660 else if ((j == 0) 6661 && ((lundata->luns[i].lundata[j+2] & 6662 RPL_LUNDATA_PERIPH_BUS_MASK) == 0)) 6663 no_more = 1; 6664 6665 fprintf(stdout, "%d", 6666 lundata->luns[i].lundata[j+1]); 6667 break; 6668 case RPL_LUNDATA_ATYP_FLAT: { 6669 uint8_t tmplun[2]; 6670 tmplun[0] = lundata->luns[i].lundata[j] & 6671 RPL_LUNDATA_FLAT_LUN_MASK; 6672 tmplun[1] = lundata->luns[i].lundata[j+1]; 6673 6674 fprintf(stdout, "%d", scsi_2btoul(tmplun)); 6675 no_more = 1; 6676 break; 6677 } 6678 case RPL_LUNDATA_ATYP_LUN: 6679 fprintf(stdout, "%d:%d:%d", 6680 (lundata->luns[i].lundata[j+1] & 6681 RPL_LUNDATA_LUN_BUS_MASK) >> 5, 6682 lundata->luns[i].lundata[j] & 6683 RPL_LUNDATA_LUN_TARG_MASK, 6684 lundata->luns[i].lundata[j+1] & 6685 RPL_LUNDATA_LUN_LUN_MASK); 6686 break; 6687 case RPL_LUNDATA_ATYP_EXTLUN: { 6688 int field_len_code, eam_code; 6689 6690 eam_code = lundata->luns[i].lundata[j] & 6691 RPL_LUNDATA_EXT_EAM_MASK; 6692 field_len_code = (lundata->luns[i].lundata[j] & 6693 RPL_LUNDATA_EXT_LEN_MASK) >> 4; 6694 6695 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK) 6696 && (field_len_code == 0x00)) { 6697 fprintf(stdout, "%d", 6698 lundata->luns[i].lundata[j+1]); 6699 } else if ((eam_code == 6700 RPL_LUNDATA_EXT_EAM_NOT_SPEC) 6701 && (field_len_code == 0x03)) { 6702 uint8_t tmp_lun[8]; 6703 6704 /* 6705 * This format takes up all 8 bytes. 6706 * If we aren't starting at offset 0, 6707 * that's a bug. 6708 */ 6709 if (j != 0) { 6710 fprintf(stdout, "Invalid " 6711 "offset %d for " 6712 "Extended LUN not " 6713 "specified format", j); 6714 no_more = 1; 6715 break; 6716 } 6717 bzero(tmp_lun, sizeof(tmp_lun)); 6718 bcopy(&lundata->luns[i].lundata[j+1], 6719 &tmp_lun[1], sizeof(tmp_lun) - 1); 6720 fprintf(stdout, "%#jx", 6721 (intmax_t)scsi_8btou64(tmp_lun)); 6722 no_more = 1; 6723 } else { 6724 fprintf(stderr, "Unknown Extended LUN" 6725 "Address method %#x, length " 6726 "code %#x", eam_code, 6727 field_len_code); 6728 no_more = 1; 6729 } 6730 break; 6731 } 6732 default: 6733 fprintf(stderr, "Unknown LUN address method " 6734 "%#x\n", lundata->luns[i].lundata[0] & 6735 RPL_LUNDATA_ATYP_MASK); 6736 break; 6737 } 6738 /* 6739 * For the flat addressing method, there are no 6740 * other levels after it. 6741 */ 6742 if (no_more != 0) 6743 break; 6744 } 6745 fprintf(stdout, "\n"); 6746 } 6747 6748bailout: 6749 6750 cam_freeccb(ccb); 6751 6752 free(lundata); 6753 6754 return (retval); 6755} 6756 6757static int 6758scsireadcapacity(struct cam_device *device, int argc, char **argv, 6759 char *combinedopt, int task_attr, int retry_count, int timeout) 6760{ 6761 union ccb *ccb; 6762 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten; 6763 struct scsi_read_capacity_data rcap; 6764 struct scsi_read_capacity_data_long rcaplong; 6765 uint64_t maxsector; 6766 uint32_t block_len; 6767 int retval; 6768 int c; 6769 6770 blocksizeonly = 0; 6771 humanize = 0; 6772 numblocks = 0; 6773 quiet = 0; 6774 sizeonly = 0; 6775 baseten = 0; 6776 retval = 0; 6777 6778 ccb = cam_getccb(device); 6779 6780 if (ccb == NULL) { 6781 warnx("%s: error allocating ccb", __func__); 6782 return (1); 6783 } 6784 6785 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 6786 6787 while ((c = getopt(argc, argv, combinedopt)) != -1) { 6788 switch (c) { 6789 case 'b': 6790 blocksizeonly++; 6791 break; 6792 case 'h': 6793 humanize++; 6794 baseten = 0; 6795 break; 6796 case 'H': 6797 humanize++; 6798 baseten++; 6799 break; 6800 case 'N': 6801 numblocks++; 6802 break; 6803 case 'q': 6804 quiet++; 6805 break; 6806 case 's': 6807 sizeonly++; 6808 break; 6809 default: 6810 break; 6811 } 6812 } 6813 6814 if ((blocksizeonly != 0) 6815 && (numblocks != 0)) { 6816 warnx("%s: you can only specify one of -b or -N", __func__); 6817 retval = 1; 6818 goto bailout; 6819 } 6820 6821 if ((blocksizeonly != 0) 6822 && (sizeonly != 0)) { 6823 warnx("%s: you can only specify one of -b or -s", __func__); 6824 retval = 1; 6825 goto bailout; 6826 } 6827 6828 if ((humanize != 0) 6829 && (quiet != 0)) { 6830 warnx("%s: you can only specify one of -h/-H or -q", __func__); 6831 retval = 1; 6832 goto bailout; 6833 } 6834 6835 if ((humanize != 0) 6836 && (blocksizeonly != 0)) { 6837 warnx("%s: you can only specify one of -h/-H or -b", __func__); 6838 retval = 1; 6839 goto bailout; 6840 } 6841 6842 scsi_read_capacity(&ccb->csio, 6843 /*retries*/ retry_count, 6844 /*cbfcnp*/ NULL, 6845 /*tag_action*/ task_attr, 6846 &rcap, 6847 SSD_FULL_SIZE, 6848 /*timeout*/ timeout ? timeout : 5000); 6849 6850 /* Disable freezing the device queue */ 6851 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 6852 6853 if (arglist & CAM_ARG_ERR_RECOVER) 6854 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 6855 6856 if (cam_send_ccb(device, ccb) < 0) { 6857 warn("error sending READ CAPACITY command"); 6858 6859 if (arglist & CAM_ARG_VERBOSE) 6860 cam_error_print(device, ccb, CAM_ESF_ALL, 6861 CAM_EPF_ALL, stderr); 6862 6863 retval = 1; 6864 goto bailout; 6865 } 6866 6867 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 6868 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 6869 retval = 1; 6870 goto bailout; 6871 } 6872 6873 maxsector = scsi_4btoul(rcap.addr); 6874 block_len = scsi_4btoul(rcap.length); 6875 6876 /* 6877 * A last block of 2^32-1 means that the true capacity is over 2TB, 6878 * and we need to issue the long READ CAPACITY to get the real 6879 * capacity. Otherwise, we're all set. 6880 */ 6881 if (maxsector != 0xffffffff) 6882 goto do_print; 6883 6884 scsi_read_capacity_16(&ccb->csio, 6885 /*retries*/ retry_count, 6886 /*cbfcnp*/ NULL, 6887 /*tag_action*/ task_attr, 6888 /*lba*/ 0, 6889 /*reladdr*/ 0, 6890 /*pmi*/ 0, 6891 /*rcap_buf*/ (uint8_t *)&rcaplong, 6892 /*rcap_buf_len*/ sizeof(rcaplong), 6893 /*sense_len*/ SSD_FULL_SIZE, 6894 /*timeout*/ timeout ? timeout : 5000); 6895 6896 /* Disable freezing the device queue */ 6897 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 6898 6899 if (arglist & CAM_ARG_ERR_RECOVER) 6900 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 6901 6902 if (cam_send_ccb(device, ccb) < 0) { 6903 warn("error sending READ CAPACITY (16) command"); 6904 6905 if (arglist & CAM_ARG_VERBOSE) 6906 cam_error_print(device, ccb, CAM_ESF_ALL, 6907 CAM_EPF_ALL, stderr); 6908 6909 retval = 1; 6910 goto bailout; 6911 } 6912 6913 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 6914 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 6915 retval = 1; 6916 goto bailout; 6917 } 6918 6919 maxsector = scsi_8btou64(rcaplong.addr); 6920 block_len = scsi_4btoul(rcaplong.length); 6921 6922do_print: 6923 if (blocksizeonly == 0) { 6924 /* 6925 * Humanize implies !quiet, and also implies numblocks. 6926 */ 6927 if (humanize != 0) { 6928 char tmpstr[6]; 6929 int64_t tmpbytes; 6930 int ret; 6931 6932 tmpbytes = (maxsector + 1) * block_len; 6933 ret = humanize_number(tmpstr, sizeof(tmpstr), 6934 tmpbytes, "", HN_AUTOSCALE, 6935 HN_B | HN_DECIMAL | 6936 ((baseten != 0) ? 6937 HN_DIVISOR_1000 : 0)); 6938 if (ret == -1) { 6939 warnx("%s: humanize_number failed!", __func__); 6940 retval = 1; 6941 goto bailout; 6942 } 6943 fprintf(stdout, "Device Size: %s%s", tmpstr, 6944 (sizeonly == 0) ? ", " : "\n"); 6945 } else if (numblocks != 0) { 6946 fprintf(stdout, "%s%ju%s", (quiet == 0) ? 6947 "Blocks: " : "", (uintmax_t)maxsector + 1, 6948 (sizeonly == 0) ? ", " : "\n"); 6949 } else { 6950 fprintf(stdout, "%s%ju%s", (quiet == 0) ? 6951 "Last Block: " : "", (uintmax_t)maxsector, 6952 (sizeonly == 0) ? ", " : "\n"); 6953 } 6954 } 6955 if (sizeonly == 0) 6956 fprintf(stdout, "%s%u%s\n", (quiet == 0) ? 6957 "Block Length: " : "", block_len, (quiet == 0) ? 6958 " bytes" : ""); 6959bailout: 6960 cam_freeccb(ccb); 6961 6962 return (retval); 6963} 6964 6965static int 6966smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt, 6967 int retry_count, int timeout) 6968{ 6969 int c, error = 0; 6970 union ccb *ccb; 6971 uint8_t *smp_request = NULL, *smp_response = NULL; 6972 int request_size = 0, response_size = 0; 6973 int fd_request = 0, fd_response = 0; 6974 char *datastr = NULL; 6975 struct get_hook hook; 6976 int retval; 6977 int flags = 0; 6978 6979 /* 6980 * Note that at the moment we don't support sending SMP CCBs to 6981 * devices that aren't probed by CAM. 6982 */ 6983 ccb = cam_getccb(device); 6984 if (ccb == NULL) { 6985 warnx("%s: error allocating CCB", __func__); 6986 return (1); 6987 } 6988 6989 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio); 6990 6991 while ((c = getopt(argc, argv, combinedopt)) != -1) { 6992 switch (c) { 6993 case 'R': 6994 arglist |= CAM_ARG_CMD_IN; 6995 response_size = strtol(optarg, NULL, 0); 6996 if (response_size <= 0) { 6997 warnx("invalid number of response bytes %d", 6998 response_size); 6999 error = 1; 7000 goto smpcmd_bailout; 7001 } 7002 hook.argc = argc - optind; 7003 hook.argv = argv + optind; 7004 hook.got = 0; 7005 optind++; 7006 datastr = cget(&hook, NULL); 7007 /* 7008 * If the user supplied "-" instead of a format, he 7009 * wants the data to be written to stdout. 7010 */ 7011 if ((datastr != NULL) 7012 && (datastr[0] == '-')) 7013 fd_response = 1; 7014 7015 smp_response = (u_int8_t *)malloc(response_size); 7016 if (smp_response == NULL) { 7017 warn("can't malloc memory for SMP response"); 7018 error = 1; 7019 goto smpcmd_bailout; 7020 } 7021 break; 7022 case 'r': 7023 arglist |= CAM_ARG_CMD_OUT; 7024 request_size = strtol(optarg, NULL, 0); 7025 if (request_size <= 0) { 7026 warnx("invalid number of request bytes %d", 7027 request_size); 7028 error = 1; 7029 goto smpcmd_bailout; 7030 } 7031 hook.argc = argc - optind; 7032 hook.argv = argv + optind; 7033 hook.got = 0; 7034 datastr = cget(&hook, NULL); 7035 smp_request = (u_int8_t *)malloc(request_size); 7036 if (smp_request == NULL) { 7037 warn("can't malloc memory for SMP request"); 7038 error = 1; 7039 goto smpcmd_bailout; 7040 } 7041 bzero(smp_request, request_size); 7042 /* 7043 * If the user supplied "-" instead of a format, he 7044 * wants the data to be read from stdin. 7045 */ 7046 if ((datastr != NULL) 7047 && (datastr[0] == '-')) 7048 fd_request = 1; 7049 else 7050 buff_encode_visit(smp_request, request_size, 7051 datastr, 7052 iget, &hook); 7053 optind += hook.got; 7054 break; 7055 default: 7056 break; 7057 } 7058 } 7059 7060 /* 7061 * If fd_data is set, and we're writing to the device, we need to 7062 * read the data the user wants written from stdin. 7063 */ 7064 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) { 7065 ssize_t amt_read; 7066 int amt_to_read = request_size; 7067 u_int8_t *buf_ptr = smp_request; 7068 7069 for (amt_read = 0; amt_to_read > 0; 7070 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) { 7071 if (amt_read == -1) { 7072 warn("error reading data from stdin"); 7073 error = 1; 7074 goto smpcmd_bailout; 7075 } 7076 amt_to_read -= amt_read; 7077 buf_ptr += amt_read; 7078 } 7079 } 7080 7081 if (((arglist & CAM_ARG_CMD_IN) == 0) 7082 || ((arglist & CAM_ARG_CMD_OUT) == 0)) { 7083 warnx("%s: need both the request (-r) and response (-R) " 7084 "arguments", __func__); 7085 error = 1; 7086 goto smpcmd_bailout; 7087 } 7088 7089 flags |= CAM_DEV_QFRZDIS; 7090 7091 cam_fill_smpio(&ccb->smpio, 7092 /*retries*/ retry_count, 7093 /*cbfcnp*/ NULL, 7094 /*flags*/ flags, 7095 /*smp_request*/ smp_request, 7096 /*smp_request_len*/ request_size, 7097 /*smp_response*/ smp_response, 7098 /*smp_response_len*/ response_size, 7099 /*timeout*/ timeout ? timeout : 5000); 7100 7101 ccb->smpio.flags = SMP_FLAG_NONE; 7102 7103 if (((retval = cam_send_ccb(device, ccb)) < 0) 7104 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 7105 const char warnstr[] = "error sending command"; 7106 7107 if (retval < 0) 7108 warn(warnstr); 7109 else 7110 warnx(warnstr); 7111 7112 if (arglist & CAM_ARG_VERBOSE) { 7113 cam_error_print(device, ccb, CAM_ESF_ALL, 7114 CAM_EPF_ALL, stderr); 7115 } 7116 } 7117 7118 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 7119 && (response_size > 0)) { 7120 if (fd_response == 0) { 7121 buff_decode_visit(smp_response, response_size, 7122 datastr, arg_put, NULL); 7123 fprintf(stdout, "\n"); 7124 } else { 7125 ssize_t amt_written; 7126 int amt_to_write = response_size; 7127 u_int8_t *buf_ptr = smp_response; 7128 7129 for (amt_written = 0; (amt_to_write > 0) && 7130 (amt_written = write(STDOUT_FILENO, buf_ptr, 7131 amt_to_write)) > 0;){ 7132 amt_to_write -= amt_written; 7133 buf_ptr += amt_written; 7134 } 7135 if (amt_written == -1) { 7136 warn("error writing data to stdout"); 7137 error = 1; 7138 goto smpcmd_bailout; 7139 } else if ((amt_written == 0) 7140 && (amt_to_write > 0)) { 7141 warnx("only wrote %u bytes out of %u", 7142 response_size - amt_to_write, 7143 response_size); 7144 } 7145 } 7146 } 7147smpcmd_bailout: 7148 if (ccb != NULL) 7149 cam_freeccb(ccb); 7150 7151 if (smp_request != NULL) 7152 free(smp_request); 7153 7154 if (smp_response != NULL) 7155 free(smp_response); 7156 7157 return (error); 7158} 7159 7160static int 7161smpreportgeneral(struct cam_device *device, int argc, char **argv, 7162 char *combinedopt, int retry_count, int timeout) 7163{ 7164 union ccb *ccb; 7165 struct smp_report_general_request *request = NULL; 7166 struct smp_report_general_response *response = NULL; 7167 struct sbuf *sb = NULL; 7168 int error = 0; 7169 int c, long_response = 0; 7170 int retval; 7171 7172 /* 7173 * Note that at the moment we don't support sending SMP CCBs to 7174 * devices that aren't probed by CAM. 7175 */ 7176 ccb = cam_getccb(device); 7177 if (ccb == NULL) { 7178 warnx("%s: error allocating CCB", __func__); 7179 return (1); 7180 } 7181 7182 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio); 7183 7184 while ((c = getopt(argc, argv, combinedopt)) != -1) { 7185 switch (c) { 7186 case 'l': 7187 long_response = 1; 7188 break; 7189 default: 7190 break; 7191 } 7192 } 7193 request = malloc(sizeof(*request)); 7194 if (request == NULL) { 7195 warn("%s: unable to allocate %zd bytes", __func__, 7196 sizeof(*request)); 7197 error = 1; 7198 goto bailout; 7199 } 7200 7201 response = malloc(sizeof(*response)); 7202 if (response == NULL) { 7203 warn("%s: unable to allocate %zd bytes", __func__, 7204 sizeof(*response)); 7205 error = 1; 7206 goto bailout; 7207 } 7208 7209try_long: 7210 smp_report_general(&ccb->smpio, 7211 retry_count, 7212 /*cbfcnp*/ NULL, 7213 request, 7214 /*request_len*/ sizeof(*request), 7215 (uint8_t *)response, 7216 /*response_len*/ sizeof(*response), 7217 /*long_response*/ long_response, 7218 timeout); 7219 7220 if (((retval = cam_send_ccb(device, ccb)) < 0) 7221 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 7222 const char warnstr[] = "error sending command"; 7223 7224 if (retval < 0) 7225 warn(warnstr); 7226 else 7227 warnx(warnstr); 7228 7229 if (arglist & CAM_ARG_VERBOSE) { 7230 cam_error_print(device, ccb, CAM_ESF_ALL, 7231 CAM_EPF_ALL, stderr); 7232 } 7233 error = 1; 7234 goto bailout; 7235 } 7236 7237 /* 7238 * If the device supports the long response bit, try again and see 7239 * if we can get all of the data. 7240 */ 7241 if ((response->long_response & SMP_RG_LONG_RESPONSE) 7242 && (long_response == 0)) { 7243 ccb->ccb_h.status = CAM_REQ_INPROG; 7244 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio); 7245 long_response = 1; 7246 goto try_long; 7247 } 7248 7249 /* 7250 * XXX KDM detect and decode SMP errors here. 7251 */ 7252 sb = sbuf_new_auto(); 7253 if (sb == NULL) { 7254 warnx("%s: error allocating sbuf", __func__); 7255 goto bailout; 7256 } 7257 7258 smp_report_general_sbuf(response, sizeof(*response), sb); 7259 7260 if (sbuf_finish(sb) != 0) { 7261 warnx("%s: sbuf_finish", __func__); 7262 goto bailout; 7263 } 7264 7265 printf("%s", sbuf_data(sb)); 7266 7267bailout: 7268 if (ccb != NULL) 7269 cam_freeccb(ccb); 7270 7271 if (request != NULL) 7272 free(request); 7273 7274 if (response != NULL) 7275 free(response); 7276 7277 if (sb != NULL) 7278 sbuf_delete(sb); 7279 7280 return (error); 7281} 7282 7283static struct camcontrol_opts phy_ops[] = { 7284 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL}, 7285 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL}, 7286 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL}, 7287 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL}, 7288 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL}, 7289 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL}, 7290 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL}, 7291 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL}, 7292 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL}, 7293 {NULL, 0, 0, NULL} 7294}; 7295 7296static int 7297smpphycontrol(struct cam_device *device, int argc, char **argv, 7298 char *combinedopt, int retry_count, int timeout) 7299{ 7300 union ccb *ccb; 7301 struct smp_phy_control_request *request = NULL; 7302 struct smp_phy_control_response *response = NULL; 7303 int long_response = 0; 7304 int retval = 0; 7305 int phy = -1; 7306 uint32_t phy_operation = SMP_PC_PHY_OP_NOP; 7307 int phy_op_set = 0; 7308 uint64_t attached_dev_name = 0; 7309 int dev_name_set = 0; 7310 uint32_t min_plr = 0, max_plr = 0; 7311 uint32_t pp_timeout_val = 0; 7312 int slumber_partial = 0; 7313 int set_pp_timeout_val = 0; 7314 int c; 7315 7316 /* 7317 * Note that at the moment we don't support sending SMP CCBs to 7318 * devices that aren't probed by CAM. 7319 */ 7320 ccb = cam_getccb(device); 7321 if (ccb == NULL) { 7322 warnx("%s: error allocating CCB", __func__); 7323 return (1); 7324 } 7325 7326 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio); 7327 7328 while ((c = getopt(argc, argv, combinedopt)) != -1) { 7329 switch (c) { 7330 case 'a': 7331 case 'A': 7332 case 's': 7333 case 'S': { 7334 int enable = -1; 7335 7336 if (strcasecmp(optarg, "enable") == 0) 7337 enable = 1; 7338 else if (strcasecmp(optarg, "disable") == 0) 7339 enable = 2; 7340 else { 7341 warnx("%s: Invalid argument %s", __func__, 7342 optarg); 7343 retval = 1; 7344 goto bailout; 7345 } 7346 switch (c) { 7347 case 's': 7348 slumber_partial |= enable << 7349 SMP_PC_SAS_SLUMBER_SHIFT; 7350 break; 7351 case 'S': 7352 slumber_partial |= enable << 7353 SMP_PC_SAS_PARTIAL_SHIFT; 7354 break; 7355 case 'a': 7356 slumber_partial |= enable << 7357 SMP_PC_SATA_SLUMBER_SHIFT; 7358 break; 7359 case 'A': 7360 slumber_partial |= enable << 7361 SMP_PC_SATA_PARTIAL_SHIFT; 7362 break; 7363 default: 7364 warnx("%s: programmer error", __func__); 7365 retval = 1; 7366 goto bailout; 7367 break; /*NOTREACHED*/ 7368 } 7369 break; 7370 } 7371 case 'd': 7372 attached_dev_name = (uintmax_t)strtoumax(optarg, 7373 NULL,0); 7374 dev_name_set = 1; 7375 break; 7376 case 'l': 7377 long_response = 1; 7378 break; 7379 case 'm': 7380 /* 7381 * We don't do extensive checking here, so this 7382 * will continue to work when new speeds come out. 7383 */ 7384 min_plr = strtoul(optarg, NULL, 0); 7385 if ((min_plr == 0) 7386 || (min_plr > 0xf)) { 7387 warnx("%s: invalid link rate %x", 7388 __func__, min_plr); 7389 retval = 1; 7390 goto bailout; 7391 } 7392 break; 7393 case 'M': 7394 /* 7395 * We don't do extensive checking here, so this 7396 * will continue to work when new speeds come out. 7397 */ 7398 max_plr = strtoul(optarg, NULL, 0); 7399 if ((max_plr == 0) 7400 || (max_plr > 0xf)) { 7401 warnx("%s: invalid link rate %x", 7402 __func__, max_plr); 7403 retval = 1; 7404 goto bailout; 7405 } 7406 break; 7407 case 'o': { 7408 camcontrol_optret optreturn; 7409 cam_argmask argnums; 7410 const char *subopt; 7411 7412 if (phy_op_set != 0) { 7413 warnx("%s: only one phy operation argument " 7414 "(-o) allowed", __func__); 7415 retval = 1; 7416 goto bailout; 7417 } 7418 7419 phy_op_set = 1; 7420 7421 /* 7422 * Allow the user to specify the phy operation 7423 * numerically, as well as with a name. This will 7424 * future-proof it a bit, so options that are added 7425 * in future specs can be used. 7426 */ 7427 if (isdigit(optarg[0])) { 7428 phy_operation = strtoul(optarg, NULL, 0); 7429 if ((phy_operation == 0) 7430 || (phy_operation > 0xff)) { 7431 warnx("%s: invalid phy operation %#x", 7432 __func__, phy_operation); 7433 retval = 1; 7434 goto bailout; 7435 } 7436 break; 7437 } 7438 optreturn = getoption(phy_ops, optarg, &phy_operation, 7439 &argnums, &subopt); 7440 7441 if (optreturn == CC_OR_AMBIGUOUS) { 7442 warnx("%s: ambiguous option %s", __func__, 7443 optarg); 7444 usage(0); 7445 retval = 1; 7446 goto bailout; 7447 } else if (optreturn == CC_OR_NOT_FOUND) { 7448 warnx("%s: option %s not found", __func__, 7449 optarg); 7450 usage(0); 7451 retval = 1; 7452 goto bailout; 7453 } 7454 break; 7455 } 7456 case 'p': 7457 phy = atoi(optarg); 7458 break; 7459 case 'T': 7460 pp_timeout_val = strtoul(optarg, NULL, 0); 7461 if (pp_timeout_val > 15) { 7462 warnx("%s: invalid partial pathway timeout " 7463 "value %u, need a value less than 16", 7464 __func__, pp_timeout_val); 7465 retval = 1; 7466 goto bailout; 7467 } 7468 set_pp_timeout_val = 1; 7469 break; 7470 default: 7471 break; 7472 } 7473 } 7474 7475 if (phy == -1) { 7476 warnx("%s: a PHY (-p phy) argument is required",__func__); 7477 retval = 1; 7478 goto bailout; 7479 } 7480 7481 if (((dev_name_set != 0) 7482 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME)) 7483 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME) 7484 && (dev_name_set == 0))) { 7485 warnx("%s: -d name and -o setdevname arguments both " 7486 "required to set device name", __func__); 7487 retval = 1; 7488 goto bailout; 7489 } 7490 7491 request = malloc(sizeof(*request)); 7492 if (request == NULL) { 7493 warn("%s: unable to allocate %zd bytes", __func__, 7494 sizeof(*request)); 7495 retval = 1; 7496 goto bailout; 7497 } 7498 7499 response = malloc(sizeof(*response)); 7500 if (response == NULL) { 7501 warn("%s: unable to allocate %zd bytes", __func__, 7502 sizeof(*response)); 7503 retval = 1; 7504 goto bailout; 7505 } 7506 7507 smp_phy_control(&ccb->smpio, 7508 retry_count, 7509 /*cbfcnp*/ NULL, 7510 request, 7511 sizeof(*request), 7512 (uint8_t *)response, 7513 sizeof(*response), 7514 long_response, 7515 /*expected_exp_change_count*/ 0, 7516 phy, 7517 phy_operation, 7518 (set_pp_timeout_val != 0) ? 1 : 0, 7519 attached_dev_name, 7520 min_plr, 7521 max_plr, 7522 slumber_partial, 7523 pp_timeout_val, 7524 timeout); 7525 7526 if (((retval = cam_send_ccb(device, ccb)) < 0) 7527 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 7528 const char warnstr[] = "error sending command"; 7529 7530 if (retval < 0) 7531 warn(warnstr); 7532 else 7533 warnx(warnstr); 7534 7535 if (arglist & CAM_ARG_VERBOSE) { 7536 /* 7537 * Use CAM_EPF_NORMAL so we only get one line of 7538 * SMP command decoding. 7539 */ 7540 cam_error_print(device, ccb, CAM_ESF_ALL, 7541 CAM_EPF_NORMAL, stderr); 7542 } 7543 retval = 1; 7544 goto bailout; 7545 } 7546 7547 /* XXX KDM print out something here for success? */ 7548bailout: 7549 if (ccb != NULL) 7550 cam_freeccb(ccb); 7551 7552 if (request != NULL) 7553 free(request); 7554 7555 if (response != NULL) 7556 free(response); 7557 7558 return (retval); 7559} 7560 7561static int 7562smpmaninfo(struct cam_device *device, int argc, char **argv, 7563 char *combinedopt, int retry_count, int timeout) 7564{ 7565 union ccb *ccb; 7566 struct smp_report_manuf_info_request request; 7567 struct smp_report_manuf_info_response response; 7568 struct sbuf *sb = NULL; 7569 int long_response = 0; 7570 int retval = 0; 7571 int c; 7572 7573 /* 7574 * Note that at the moment we don't support sending SMP CCBs to 7575 * devices that aren't probed by CAM. 7576 */ 7577 ccb = cam_getccb(device); 7578 if (ccb == NULL) { 7579 warnx("%s: error allocating CCB", __func__); 7580 return (1); 7581 } 7582 7583 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio); 7584 7585 while ((c = getopt(argc, argv, combinedopt)) != -1) { 7586 switch (c) { 7587 case 'l': 7588 long_response = 1; 7589 break; 7590 default: 7591 break; 7592 } 7593 } 7594 bzero(&request, sizeof(request)); 7595 bzero(&response, sizeof(response)); 7596 7597 smp_report_manuf_info(&ccb->smpio, 7598 retry_count, 7599 /*cbfcnp*/ NULL, 7600 &request, 7601 sizeof(request), 7602 (uint8_t *)&response, 7603 sizeof(response), 7604 long_response, 7605 timeout); 7606 7607 if (((retval = cam_send_ccb(device, ccb)) < 0) 7608 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 7609 const char warnstr[] = "error sending command"; 7610 7611 if (retval < 0) 7612 warn(warnstr); 7613 else 7614 warnx(warnstr); 7615 7616 if (arglist & CAM_ARG_VERBOSE) { 7617 cam_error_print(device, ccb, CAM_ESF_ALL, 7618 CAM_EPF_ALL, stderr); 7619 } 7620 retval = 1; 7621 goto bailout; 7622 } 7623 7624 sb = sbuf_new_auto(); 7625 if (sb == NULL) { 7626 warnx("%s: error allocating sbuf", __func__); 7627 goto bailout; 7628 } 7629 7630 smp_report_manuf_info_sbuf(&response, sizeof(response), sb); 7631 7632 if (sbuf_finish(sb) != 0) { 7633 warnx("%s: sbuf_finish", __func__); 7634 goto bailout; 7635 } 7636 7637 printf("%s", sbuf_data(sb)); 7638 7639bailout: 7640 7641 if (ccb != NULL) 7642 cam_freeccb(ccb); 7643 7644 if (sb != NULL) 7645 sbuf_delete(sb); 7646 7647 return (retval); 7648} 7649 7650static int 7651getdevid(struct cam_devitem *item) 7652{ 7653 int retval = 0; 7654 union ccb *ccb = NULL; 7655 7656 struct cam_device *dev; 7657 7658 dev = cam_open_btl(item->dev_match.path_id, 7659 item->dev_match.target_id, 7660 item->dev_match.target_lun, O_RDWR, NULL); 7661 7662 if (dev == NULL) { 7663 warnx("%s", cam_errbuf); 7664 retval = 1; 7665 goto bailout; 7666 } 7667 7668 item->device_id_len = 0; 7669 7670 ccb = cam_getccb(dev); 7671 if (ccb == NULL) { 7672 warnx("%s: error allocating CCB", __func__); 7673 retval = 1; 7674 goto bailout; 7675 } 7676 7677 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai); 7678 7679 /* 7680 * On the first try, we just probe for the size of the data, and 7681 * then allocate that much memory and try again. 7682 */ 7683retry: 7684 ccb->ccb_h.func_code = XPT_DEV_ADVINFO; 7685 ccb->ccb_h.flags = CAM_DIR_IN; 7686 ccb->cdai.flags = CDAI_FLAG_NONE; 7687 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID; 7688 ccb->cdai.bufsiz = item->device_id_len; 7689 if (item->device_id_len != 0) 7690 ccb->cdai.buf = (uint8_t *)item->device_id; 7691 7692 if (cam_send_ccb(dev, ccb) < 0) { 7693 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__); 7694 retval = 1; 7695 goto bailout; 7696 } 7697 7698 if (ccb->ccb_h.status != CAM_REQ_CMP) { 7699 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status); 7700 retval = 1; 7701 goto bailout; 7702 } 7703 7704 if (item->device_id_len == 0) { 7705 /* 7706 * This is our first time through. Allocate the buffer, 7707 * and then go back to get the data. 7708 */ 7709 if (ccb->cdai.provsiz == 0) { 7710 warnx("%s: invalid .provsiz field returned with " 7711 "XPT_GDEV_ADVINFO CCB", __func__); 7712 retval = 1; 7713 goto bailout; 7714 } 7715 item->device_id_len = ccb->cdai.provsiz; 7716 item->device_id = malloc(item->device_id_len); 7717 if (item->device_id == NULL) { 7718 warn("%s: unable to allocate %d bytes", __func__, 7719 item->device_id_len); 7720 retval = 1; 7721 goto bailout; 7722 } 7723 ccb->ccb_h.status = CAM_REQ_INPROG; 7724 goto retry; 7725 } 7726 7727bailout: 7728 if (dev != NULL) 7729 cam_close_device(dev); 7730 7731 if (ccb != NULL) 7732 cam_freeccb(ccb); 7733 7734 return (retval); 7735} 7736 7737/* 7738 * XXX KDM merge this code with getdevtree()? 7739 */ 7740static int 7741buildbusdevlist(struct cam_devlist *devlist) 7742{ 7743 union ccb ccb; 7744 int bufsize, fd = -1; 7745 struct dev_match_pattern *patterns; 7746 struct cam_devitem *item = NULL; 7747 int skip_device = 0; 7748 int retval = 0; 7749 7750 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { 7751 warn("couldn't open %s", XPT_DEVICE); 7752 return(1); 7753 } 7754 7755 bzero(&ccb, sizeof(union ccb)); 7756 7757 ccb.ccb_h.path_id = CAM_XPT_PATH_ID; 7758 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 7759 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 7760 7761 ccb.ccb_h.func_code = XPT_DEV_MATCH; 7762 bufsize = sizeof(struct dev_match_result) * 100; 7763 ccb.cdm.match_buf_len = bufsize; 7764 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); 7765 if (ccb.cdm.matches == NULL) { 7766 warnx("can't malloc memory for matches"); 7767 close(fd); 7768 return(1); 7769 } 7770 ccb.cdm.num_matches = 0; 7771 ccb.cdm.num_patterns = 2; 7772 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) * 7773 ccb.cdm.num_patterns; 7774 7775 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len); 7776 if (patterns == NULL) { 7777 warnx("can't malloc memory for patterns"); 7778 retval = 1; 7779 goto bailout; 7780 } 7781 7782 ccb.cdm.patterns = patterns; 7783 bzero(patterns, ccb.cdm.pattern_buf_len); 7784 7785 patterns[0].type = DEV_MATCH_DEVICE; 7786 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH; 7787 patterns[0].pattern.device_pattern.path_id = devlist->path_id; 7788 patterns[1].type = DEV_MATCH_PERIPH; 7789 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH; 7790 patterns[1].pattern.periph_pattern.path_id = devlist->path_id; 7791 7792 /* 7793 * We do the ioctl multiple times if necessary, in case there are 7794 * more than 100 nodes in the EDT. 7795 */ 7796 do { 7797 unsigned int i; 7798 7799 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 7800 warn("error sending CAMIOCOMMAND ioctl"); 7801 retval = 1; 7802 goto bailout; 7803 } 7804 7805 if ((ccb.ccb_h.status != CAM_REQ_CMP) 7806 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) 7807 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { 7808 warnx("got CAM error %#x, CDM error %d\n", 7809 ccb.ccb_h.status, ccb.cdm.status); 7810 retval = 1; 7811 goto bailout; 7812 } 7813 7814 for (i = 0; i < ccb.cdm.num_matches; i++) { 7815 switch (ccb.cdm.matches[i].type) { 7816 case DEV_MATCH_DEVICE: { 7817 struct device_match_result *dev_result; 7818 7819 dev_result = 7820 &ccb.cdm.matches[i].result.device_result; 7821 7822 if (dev_result->flags & 7823 DEV_RESULT_UNCONFIGURED) { 7824 skip_device = 1; 7825 break; 7826 } else 7827 skip_device = 0; 7828 7829 item = malloc(sizeof(*item)); 7830 if (item == NULL) { 7831 warn("%s: unable to allocate %zd bytes", 7832 __func__, sizeof(*item)); 7833 retval = 1; 7834 goto bailout; 7835 } 7836 bzero(item, sizeof(*item)); 7837 bcopy(dev_result, &item->dev_match, 7838 sizeof(*dev_result)); 7839 STAILQ_INSERT_TAIL(&devlist->dev_queue, item, 7840 links); 7841 7842 if (getdevid(item) != 0) { 7843 retval = 1; 7844 goto bailout; 7845 } 7846 break; 7847 } 7848 case DEV_MATCH_PERIPH: { 7849 struct periph_match_result *periph_result; 7850 7851 periph_result = 7852 &ccb.cdm.matches[i].result.periph_result; 7853 7854 if (skip_device != 0) 7855 break; 7856 item->num_periphs++; 7857 item->periph_matches = realloc( 7858 item->periph_matches, 7859 item->num_periphs * 7860 sizeof(struct periph_match_result)); 7861 if (item->periph_matches == NULL) { 7862 warn("%s: error allocating periph " 7863 "list", __func__); 7864 retval = 1; 7865 goto bailout; 7866 } 7867 bcopy(periph_result, &item->periph_matches[ 7868 item->num_periphs - 1], 7869 sizeof(*periph_result)); 7870 break; 7871 } 7872 default: 7873 fprintf(stderr, "%s: unexpected match " 7874 "type %d\n", __func__, 7875 ccb.cdm.matches[i].type); 7876 retval = 1; 7877 goto bailout; 7878 break; /*NOTREACHED*/ 7879 } 7880 } 7881 } while ((ccb.ccb_h.status == CAM_REQ_CMP) 7882 && (ccb.cdm.status == CAM_DEV_MATCH_MORE)); 7883bailout: 7884 7885 if (fd != -1) 7886 close(fd); 7887 7888 free(patterns); 7889 7890 free(ccb.cdm.matches); 7891 7892 if (retval != 0) 7893 freebusdevlist(devlist); 7894 7895 return (retval); 7896} 7897 7898static void 7899freebusdevlist(struct cam_devlist *devlist) 7900{ 7901 struct cam_devitem *item, *item2; 7902 7903 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) { 7904 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem, 7905 links); 7906 free(item->device_id); 7907 free(item->periph_matches); 7908 free(item); 7909 } 7910} 7911 7912static struct cam_devitem * 7913findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr) 7914{ 7915 struct cam_devitem *item; 7916 7917 STAILQ_FOREACH(item, &devlist->dev_queue, links) { 7918 struct scsi_vpd_id_descriptor *idd; 7919 7920 /* 7921 * XXX KDM look for LUN IDs as well? 7922 */ 7923 idd = scsi_get_devid(item->device_id, 7924 item->device_id_len, 7925 scsi_devid_is_sas_target); 7926 if (idd == NULL) 7927 continue; 7928 7929 if (scsi_8btou64(idd->identifier) == sasaddr) 7930 return (item); 7931 } 7932 7933 return (NULL); 7934} 7935 7936static int 7937smpphylist(struct cam_device *device, int argc, char **argv, 7938 char *combinedopt, int retry_count, int timeout) 7939{ 7940 struct smp_report_general_request *rgrequest = NULL; 7941 struct smp_report_general_response *rgresponse = NULL; 7942 struct smp_discover_request *disrequest = NULL; 7943 struct smp_discover_response *disresponse = NULL; 7944 struct cam_devlist devlist; 7945 union ccb *ccb; 7946 int long_response = 0; 7947 int num_phys = 0; 7948 int quiet = 0; 7949 int retval; 7950 int i, c; 7951 7952 /* 7953 * Note that at the moment we don't support sending SMP CCBs to 7954 * devices that aren't probed by CAM. 7955 */ 7956 ccb = cam_getccb(device); 7957 if (ccb == NULL) { 7958 warnx("%s: error allocating CCB", __func__); 7959 return (1); 7960 } 7961 7962 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio); 7963 STAILQ_INIT(&devlist.dev_queue); 7964 7965 rgrequest = malloc(sizeof(*rgrequest)); 7966 if (rgrequest == NULL) { 7967 warn("%s: unable to allocate %zd bytes", __func__, 7968 sizeof(*rgrequest)); 7969 retval = 1; 7970 goto bailout; 7971 } 7972 7973 rgresponse = malloc(sizeof(*rgresponse)); 7974 if (rgresponse == NULL) { 7975 warn("%s: unable to allocate %zd bytes", __func__, 7976 sizeof(*rgresponse)); 7977 retval = 1; 7978 goto bailout; 7979 } 7980 7981 while ((c = getopt(argc, argv, combinedopt)) != -1) { 7982 switch (c) { 7983 case 'l': 7984 long_response = 1; 7985 break; 7986 case 'q': 7987 quiet = 1; 7988 break; 7989 default: 7990 break; 7991 } 7992 } 7993 7994 smp_report_general(&ccb->smpio, 7995 retry_count, 7996 /*cbfcnp*/ NULL, 7997 rgrequest, 7998 /*request_len*/ sizeof(*rgrequest), 7999 (uint8_t *)rgresponse, 8000 /*response_len*/ sizeof(*rgresponse), 8001 /*long_response*/ long_response, 8002 timeout); 8003 8004 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 8005 8006 if (((retval = cam_send_ccb(device, ccb)) < 0) 8007 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 8008 const char warnstr[] = "error sending command"; 8009 8010 if (retval < 0) 8011 warn(warnstr); 8012 else 8013 warnx(warnstr); 8014 8015 if (arglist & CAM_ARG_VERBOSE) { 8016 cam_error_print(device, ccb, CAM_ESF_ALL, 8017 CAM_EPF_ALL, stderr); 8018 } 8019 retval = 1; 8020 goto bailout; 8021 } 8022 8023 num_phys = rgresponse->num_phys; 8024 8025 if (num_phys == 0) { 8026 if (quiet == 0) 8027 fprintf(stdout, "%s: No Phys reported\n", __func__); 8028 retval = 1; 8029 goto bailout; 8030 } 8031 8032 devlist.path_id = device->path_id; 8033 8034 retval = buildbusdevlist(&devlist); 8035 if (retval != 0) 8036 goto bailout; 8037 8038 if (quiet == 0) { 8039 fprintf(stdout, "%d PHYs:\n", num_phys); 8040 fprintf(stdout, "PHY Attached SAS Address\n"); 8041 } 8042 8043 disrequest = malloc(sizeof(*disrequest)); 8044 if (disrequest == NULL) { 8045 warn("%s: unable to allocate %zd bytes", __func__, 8046 sizeof(*disrequest)); 8047 retval = 1; 8048 goto bailout; 8049 } 8050 8051 disresponse = malloc(sizeof(*disresponse)); 8052 if (disresponse == NULL) { 8053 warn("%s: unable to allocate %zd bytes", __func__, 8054 sizeof(*disresponse)); 8055 retval = 1; 8056 goto bailout; 8057 } 8058 8059 for (i = 0; i < num_phys; i++) { 8060 struct cam_devitem *item; 8061 struct device_match_result *dev_match; 8062 char vendor[16], product[48], revision[16]; 8063 char tmpstr[256]; 8064 int j; 8065 8066 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio); 8067 8068 ccb->ccb_h.status = CAM_REQ_INPROG; 8069 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 8070 8071 smp_discover(&ccb->smpio, 8072 retry_count, 8073 /*cbfcnp*/ NULL, 8074 disrequest, 8075 sizeof(*disrequest), 8076 (uint8_t *)disresponse, 8077 sizeof(*disresponse), 8078 long_response, 8079 /*ignore_zone_group*/ 0, 8080 /*phy*/ i, 8081 timeout); 8082 8083 if (((retval = cam_send_ccb(device, ccb)) < 0) 8084 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 8085 && (disresponse->function_result != SMP_FR_PHY_VACANT))) { 8086 const char warnstr[] = "error sending command"; 8087 8088 if (retval < 0) 8089 warn(warnstr); 8090 else 8091 warnx(warnstr); 8092 8093 if (arglist & CAM_ARG_VERBOSE) { 8094 cam_error_print(device, ccb, CAM_ESF_ALL, 8095 CAM_EPF_ALL, stderr); 8096 } 8097 retval = 1; 8098 goto bailout; 8099 } 8100 8101 if (disresponse->function_result == SMP_FR_PHY_VACANT) { 8102 if (quiet == 0) 8103 fprintf(stdout, "%3d <vacant>\n", i); 8104 continue; 8105 } 8106 8107 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) { 8108 item = NULL; 8109 } else { 8110 item = findsasdevice(&devlist, 8111 scsi_8btou64(disresponse->attached_sas_address)); 8112 } 8113 8114 if ((quiet == 0) 8115 || (item != NULL)) { 8116 fprintf(stdout, "%3d 0x%016jx", i, 8117 (uintmax_t)scsi_8btou64( 8118 disresponse->attached_sas_address)); 8119 if (item == NULL) { 8120 fprintf(stdout, "\n"); 8121 continue; 8122 } 8123 } else if (quiet != 0) 8124 continue; 8125 8126 dev_match = &item->dev_match; 8127 8128 if (dev_match->protocol == PROTO_SCSI) { 8129 cam_strvis(vendor, dev_match->inq_data.vendor, 8130 sizeof(dev_match->inq_data.vendor), 8131 sizeof(vendor)); 8132 cam_strvis(product, dev_match->inq_data.product, 8133 sizeof(dev_match->inq_data.product), 8134 sizeof(product)); 8135 cam_strvis(revision, dev_match->inq_data.revision, 8136 sizeof(dev_match->inq_data.revision), 8137 sizeof(revision)); 8138 sprintf(tmpstr, "<%s %s %s>", vendor, product, 8139 revision); 8140 } else if ((dev_match->protocol == PROTO_ATA) 8141 || (dev_match->protocol == PROTO_SATAPM)) { 8142 cam_strvis(product, dev_match->ident_data.model, 8143 sizeof(dev_match->ident_data.model), 8144 sizeof(product)); 8145 cam_strvis(revision, dev_match->ident_data.revision, 8146 sizeof(dev_match->ident_data.revision), 8147 sizeof(revision)); 8148 sprintf(tmpstr, "<%s %s>", product, revision); 8149 } else { 8150 sprintf(tmpstr, "<>"); 8151 } 8152 fprintf(stdout, " %-33s ", tmpstr); 8153 8154 /* 8155 * If we have 0 periphs, that's a bug... 8156 */ 8157 if (item->num_periphs == 0) { 8158 fprintf(stdout, "\n"); 8159 continue; 8160 } 8161 8162 fprintf(stdout, "("); 8163 for (j = 0; j < item->num_periphs; j++) { 8164 if (j > 0) 8165 fprintf(stdout, ","); 8166 8167 fprintf(stdout, "%s%d", 8168 item->periph_matches[j].periph_name, 8169 item->periph_matches[j].unit_number); 8170 8171 } 8172 fprintf(stdout, ")\n"); 8173 } 8174bailout: 8175 if (ccb != NULL) 8176 cam_freeccb(ccb); 8177 8178 free(rgrequest); 8179 8180 free(rgresponse); 8181 8182 free(disrequest); 8183 8184 free(disresponse); 8185 8186 freebusdevlist(&devlist); 8187 8188 return (retval); 8189} 8190 8191static int 8192atapm(struct cam_device *device, int argc, char **argv, 8193 char *combinedopt, int retry_count, int timeout) 8194{ 8195 union ccb *ccb; 8196 int retval = 0; 8197 int t = -1; 8198 int c; 8199 u_char cmd, sc; 8200 8201 ccb = cam_getccb(device); 8202 8203 if (ccb == NULL) { 8204 warnx("%s: error allocating ccb", __func__); 8205 return (1); 8206 } 8207 8208 while ((c = getopt(argc, argv, combinedopt)) != -1) { 8209 switch (c) { 8210 case 't': 8211 t = atoi(optarg); 8212 break; 8213 default: 8214 break; 8215 } 8216 } 8217 if (strcmp(argv[1], "idle") == 0) { 8218 if (t == -1) 8219 cmd = ATA_IDLE_IMMEDIATE; 8220 else 8221 cmd = ATA_IDLE_CMD; 8222 } else if (strcmp(argv[1], "standby") == 0) { 8223 if (t == -1) 8224 cmd = ATA_STANDBY_IMMEDIATE; 8225 else 8226 cmd = ATA_STANDBY_CMD; 8227 } else { 8228 cmd = ATA_SLEEP; 8229 t = -1; 8230 } 8231 8232 if (t < 0) 8233 sc = 0; 8234 else if (t <= (240 * 5)) 8235 sc = (t + 4) / 5; 8236 else if (t <= (252 * 5)) 8237 /* special encoding for 21 minutes */ 8238 sc = 252; 8239 else if (t <= (11 * 30 * 60)) 8240 sc = (t - 1) / (30 * 60) + 241; 8241 else 8242 sc = 253; 8243 8244 retval = ata_do_28bit_cmd(device, 8245 ccb, 8246 /*retries*/retry_count, 8247 /*flags*/CAM_DIR_NONE, 8248 /*protocol*/AP_PROTO_NON_DATA, 8249 /*tag_action*/MSG_SIMPLE_Q_TAG, 8250 /*command*/cmd, 8251 /*features*/0, 8252 /*lba*/0, 8253 /*sector_count*/sc, 8254 /*data_ptr*/NULL, 8255 /*dxfer_len*/0, 8256 /*timeout*/timeout ? timeout : 30 * 1000, 8257 /*quiet*/1); 8258 8259 cam_freeccb(ccb); 8260 return (retval); 8261} 8262 8263static int 8264ataaxm(struct cam_device *device, int argc, char **argv, 8265 char *combinedopt, int retry_count, int timeout) 8266{ 8267 union ccb *ccb; 8268 int retval = 0; 8269 int l = -1; 8270 int c; 8271 u_char cmd, sc; 8272 8273 ccb = cam_getccb(device); 8274 8275 if (ccb == NULL) { 8276 warnx("%s: error allocating ccb", __func__); 8277 return (1); 8278 } 8279 8280 while ((c = getopt(argc, argv, combinedopt)) != -1) { 8281 switch (c) { 8282 case 'l': 8283 l = atoi(optarg); 8284 break; 8285 default: 8286 break; 8287 } 8288 } 8289 sc = 0; 8290 if (strcmp(argv[1], "apm") == 0) { 8291 if (l == -1) 8292 cmd = 0x85; 8293 else { 8294 cmd = 0x05; 8295 sc = l; 8296 } 8297 } else /* aam */ { 8298 if (l == -1) 8299 cmd = 0xC2; 8300 else { 8301 cmd = 0x42; 8302 sc = l; 8303 } 8304 } 8305 8306 retval = ata_do_28bit_cmd(device, 8307 ccb, 8308 /*retries*/retry_count, 8309 /*flags*/CAM_DIR_NONE, 8310 /*protocol*/AP_PROTO_NON_DATA, 8311 /*tag_action*/MSG_SIMPLE_Q_TAG, 8312 /*command*/ATA_SETFEATURES, 8313 /*features*/cmd, 8314 /*lba*/0, 8315 /*sector_count*/sc, 8316 /*data_ptr*/NULL, 8317 /*dxfer_len*/0, 8318 /*timeout*/timeout ? timeout : 30 * 1000, 8319 /*quiet*/1); 8320 8321 cam_freeccb(ccb); 8322 return (retval); 8323} 8324 8325int 8326scsigetopcodes(struct cam_device *device, int opcode_set, int opcode, 8327 int show_sa_errors, int sa_set, int service_action, 8328 int timeout_desc, int task_attr, int retry_count, int timeout, 8329 int verbosemode, uint32_t *fill_len, uint8_t **data_ptr) 8330{ 8331 union ccb *ccb = NULL; 8332 uint8_t *buf = NULL; 8333 uint32_t alloc_len = 0, num_opcodes; 8334 uint32_t valid_len = 0; 8335 uint32_t avail_len = 0; 8336 struct scsi_report_supported_opcodes_all *all_hdr; 8337 struct scsi_report_supported_opcodes_one *one; 8338 int options = 0; 8339 int retval = 0; 8340 8341 /* 8342 * Make it clear that we haven't yet allocated or filled anything. 8343 */ 8344 *fill_len = 0; 8345 *data_ptr = NULL; 8346 8347 ccb = cam_getccb(device); 8348 if (ccb == NULL) { 8349 warnx("couldn't allocate CCB"); 8350 retval = 1; 8351 goto bailout; 8352 } 8353 8354 /* cam_getccb cleans up the header, caller has to zero the payload */ 8355 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 8356 8357 if (opcode_set != 0) { 8358 options |= RSO_OPTIONS_OC; 8359 num_opcodes = 1; 8360 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN; 8361 } else { 8362 num_opcodes = 256; 8363 alloc_len = sizeof(*all_hdr) + (num_opcodes * 8364 sizeof(struct scsi_report_supported_opcodes_descr)); 8365 } 8366 8367 if (timeout_desc != 0) { 8368 options |= RSO_RCTD; 8369 alloc_len += num_opcodes * 8370 sizeof(struct scsi_report_supported_opcodes_timeout); 8371 } 8372 8373 if (sa_set != 0) { 8374 options |= RSO_OPTIONS_OC_SA; 8375 if (show_sa_errors != 0) 8376 options &= ~RSO_OPTIONS_OC; 8377 } 8378 8379retry_alloc: 8380 if (buf != NULL) { 8381 free(buf); 8382 buf = NULL; 8383 } 8384 8385 buf = malloc(alloc_len); 8386 if (buf == NULL) { 8387 warn("Unable to allocate %u bytes", alloc_len); 8388 retval = 1; 8389 goto bailout; 8390 } 8391 bzero(buf, alloc_len); 8392 8393 scsi_report_supported_opcodes(&ccb->csio, 8394 /*retries*/ retry_count, 8395 /*cbfcnp*/ NULL, 8396 /*tag_action*/ task_attr, 8397 /*options*/ options, 8398 /*req_opcode*/ opcode, 8399 /*req_service_action*/ service_action, 8400 /*data_ptr*/ buf, 8401 /*dxfer_len*/ alloc_len, 8402 /*sense_len*/ SSD_FULL_SIZE, 8403 /*timeout*/ timeout ? timeout : 10000); 8404 8405 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 8406 8407 if (retry_count != 0) 8408 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 8409 8410 if (cam_send_ccb(device, ccb) < 0) { 8411 perror("error sending REPORT SUPPORTED OPERATION CODES"); 8412 retval = 1; 8413 goto bailout; 8414 } 8415 8416 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 8417 if (verbosemode != 0) 8418 cam_error_print(device, ccb, CAM_ESF_ALL, 8419 CAM_EPF_ALL, stderr); 8420 8421 retval = 1; 8422 goto bailout; 8423 } 8424 8425 valid_len = ccb->csio.dxfer_len - ccb->csio.resid; 8426 8427 if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL) 8428 && (valid_len >= sizeof(*all_hdr))) { 8429 all_hdr = (struct scsi_report_supported_opcodes_all *)buf; 8430 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr); 8431 } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL) 8432 && (valid_len >= sizeof(*one))) { 8433 uint32_t cdb_length; 8434 8435 one = (struct scsi_report_supported_opcodes_one *)buf; 8436 cdb_length = scsi_2btoul(one->cdb_length); 8437 avail_len = sizeof(*one) + cdb_length; 8438 if (one->support & RSO_ONE_CTDP) { 8439 struct scsi_report_supported_opcodes_timeout *td; 8440 8441 td = (struct scsi_report_supported_opcodes_timeout *) 8442 &buf[avail_len]; 8443 if (valid_len >= (avail_len + sizeof(td->length))) { 8444 avail_len += scsi_2btoul(td->length) + 8445 sizeof(td->length); 8446 } else { 8447 avail_len += sizeof(*td); 8448 } 8449 } 8450 } 8451 8452 /* 8453 * avail_len could be zero if we didn't get enough data back from 8454 * thet target to determine 8455 */ 8456 if ((avail_len != 0) 8457 && (avail_len > valid_len)) { 8458 alloc_len = avail_len; 8459 goto retry_alloc; 8460 } 8461 8462 *fill_len = valid_len; 8463 *data_ptr = buf; 8464bailout: 8465 if (retval != 0) 8466 free(buf); 8467 8468 cam_freeccb(ccb); 8469 8470 return (retval); 8471} 8472 8473static int 8474scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set, 8475 int req_sa, uint8_t *buf, uint32_t valid_len) 8476{ 8477 struct scsi_report_supported_opcodes_one *one; 8478 struct scsi_report_supported_opcodes_timeout *td; 8479 uint32_t cdb_len = 0, td_len = 0; 8480 const char *op_desc = NULL; 8481 unsigned int i; 8482 int retval = 0; 8483 8484 one = (struct scsi_report_supported_opcodes_one *)buf; 8485 8486 /* 8487 * If we don't have the full single opcode descriptor, no point in 8488 * continuing. 8489 */ 8490 if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one, 8491 cdb_length)) { 8492 warnx("Only %u bytes returned, not enough to verify support", 8493 valid_len); 8494 retval = 1; 8495 goto bailout; 8496 } 8497 8498 op_desc = scsi_op_desc(req_opcode, &device->inq_data); 8499 8500 printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN", 8501 req_opcode); 8502 if (sa_set != 0) 8503 printf(", SA 0x%x", req_sa); 8504 printf(": "); 8505 8506 switch (one->support & RSO_ONE_SUP_MASK) { 8507 case RSO_ONE_SUP_UNAVAIL: 8508 printf("No command support information currently available\n"); 8509 break; 8510 case RSO_ONE_SUP_NOT_SUP: 8511 printf("Command not supported\n"); 8512 retval = 1; 8513 goto bailout; 8514 break; /*NOTREACHED*/ 8515 case RSO_ONE_SUP_AVAIL: 8516 printf("Command is supported, complies with a SCSI standard\n"); 8517 break; 8518 case RSO_ONE_SUP_VENDOR: 8519 printf("Command is supported, vendor-specific " 8520 "implementation\n"); 8521 break; 8522 default: 8523 printf("Unknown command support flags 0x%#x\n", 8524 one->support & RSO_ONE_SUP_MASK); 8525 break; 8526 } 8527 8528 /* 8529 * If we don't have the CDB length, it isn't exactly an error, the 8530 * command probably isn't supported. 8531 */ 8532 if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one, 8533 cdb_usage)) 8534 goto bailout; 8535 8536 cdb_len = scsi_2btoul(one->cdb_length); 8537 8538 /* 8539 * If our valid data doesn't include the full reported length, 8540 * return. The caller should have detected this and adjusted his 8541 * allocation length to get all of the available data. 8542 */ 8543 if (valid_len < sizeof(*one) + cdb_len) { 8544 retval = 1; 8545 goto bailout; 8546 } 8547 8548 /* 8549 * If all we have is the opcode, there is no point in printing out 8550 * the usage bitmap. 8551 */ 8552 if (cdb_len <= 1) { 8553 retval = 1; 8554 goto bailout; 8555 } 8556 8557 printf("CDB usage bitmap:"); 8558 for (i = 0; i < cdb_len; i++) { 8559 printf(" %02x", one->cdb_usage[i]); 8560 } 8561 printf("\n"); 8562 8563 /* 8564 * If we don't have a timeout descriptor, we're done. 8565 */ 8566 if ((one->support & RSO_ONE_CTDP) == 0) 8567 goto bailout; 8568 8569 /* 8570 * If we don't have enough valid length to include the timeout 8571 * descriptor length, we're done. 8572 */ 8573 if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length))) 8574 goto bailout; 8575 8576 td = (struct scsi_report_supported_opcodes_timeout *) 8577 &buf[sizeof(*one) + cdb_len]; 8578 td_len = scsi_2btoul(td->length); 8579 td_len += sizeof(td->length); 8580 8581 /* 8582 * If we don't have the full timeout descriptor, we're done. 8583 */ 8584 if (td_len < sizeof(*td)) 8585 goto bailout; 8586 8587 /* 8588 * If we don't have enough valid length to contain the full timeout 8589 * descriptor, we're done. 8590 */ 8591 if (valid_len < (sizeof(*one) + cdb_len + td_len)) 8592 goto bailout; 8593 8594 printf("Timeout information:\n"); 8595 printf("Command-specific: 0x%02x\n", td->cmd_specific); 8596 printf("Nominal timeout: %u seconds\n", 8597 scsi_4btoul(td->nominal_time)); 8598 printf("Recommended timeout: %u seconds\n", 8599 scsi_4btoul(td->recommended_time)); 8600 8601bailout: 8602 return (retval); 8603} 8604 8605static int 8606scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf, 8607 uint32_t valid_len) 8608{ 8609 struct scsi_report_supported_opcodes_all *hdr; 8610 struct scsi_report_supported_opcodes_descr *desc; 8611 uint32_t avail_len = 0, used_len = 0; 8612 uint8_t *cur_ptr; 8613 int retval = 0; 8614 8615 if (valid_len < sizeof(*hdr)) { 8616 warnx("%s: not enough returned data (%u bytes) opcode list", 8617 __func__, valid_len); 8618 retval = 1; 8619 goto bailout; 8620 } 8621 hdr = (struct scsi_report_supported_opcodes_all *)buf; 8622 avail_len = scsi_4btoul(hdr->length); 8623 avail_len += sizeof(hdr->length); 8624 /* 8625 * Take the lesser of the amount of data the drive claims is 8626 * available, and the amount of data the HBA says was returned. 8627 */ 8628 avail_len = MIN(avail_len, valid_len); 8629 8630 used_len = sizeof(hdr->length); 8631 8632 printf("%-6s %4s %8s ", 8633 "Opcode", "SA", "CDB len" ); 8634 8635 if (td_req != 0) 8636 printf("%5s %6s %6s ", "CS", "Nom", "Rec"); 8637 printf(" Description\n"); 8638 8639 while ((avail_len - used_len) > sizeof(*desc)) { 8640 struct scsi_report_supported_opcodes_timeout *td; 8641 uint32_t td_len; 8642 const char *op_desc = NULL; 8643 8644 cur_ptr = &buf[used_len]; 8645 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr; 8646 8647 op_desc = scsi_op_desc(desc->opcode, &device->inq_data); 8648 if (op_desc == NULL) 8649 op_desc = "UNKNOWN"; 8650 8651 printf("0x%02x %#4x %8u ", desc->opcode, 8652 scsi_2btoul(desc->service_action), 8653 scsi_2btoul(desc->cdb_length)); 8654 8655 used_len += sizeof(*desc); 8656 8657 if ((desc->flags & RSO_CTDP) == 0) { 8658 printf(" %s\n", op_desc); 8659 continue; 8660 } 8661 8662 /* 8663 * If we don't have enough space to fit a timeout 8664 * descriptor, then we're done. 8665 */ 8666 if (avail_len - used_len < sizeof(*td)) { 8667 used_len = avail_len; 8668 printf(" %s\n", op_desc); 8669 continue; 8670 } 8671 cur_ptr = &buf[used_len]; 8672 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr; 8673 td_len = scsi_2btoul(td->length); 8674 td_len += sizeof(td->length); 8675 8676 used_len += td_len; 8677 /* 8678 * If the given timeout descriptor length is less than what 8679 * we understand, skip it. 8680 */ 8681 if (td_len < sizeof(*td)) { 8682 printf(" %s\n", op_desc); 8683 continue; 8684 } 8685 8686 printf(" 0x%02x %6u %6u %s\n", td->cmd_specific, 8687 scsi_4btoul(td->nominal_time), 8688 scsi_4btoul(td->recommended_time), op_desc); 8689 } 8690bailout: 8691 return (retval); 8692} 8693 8694static int 8695scsiopcodes(struct cam_device *device, int argc, char **argv, 8696 char *combinedopt, int task_attr, int retry_count, int timeout, 8697 int verbosemode) 8698{ 8699 int c; 8700 uint32_t opcode = 0, service_action = 0; 8701 int td_set = 0, opcode_set = 0, sa_set = 0; 8702 int show_sa_errors = 1; 8703 uint32_t valid_len = 0; 8704 uint8_t *buf = NULL; 8705 char *endptr; 8706 int retval = 0; 8707 8708 while ((c = getopt(argc, argv, combinedopt)) != -1) { 8709 switch (c) { 8710 case 'N': 8711 show_sa_errors = 0; 8712 break; 8713 case 'o': 8714 opcode = strtoul(optarg, &endptr, 0); 8715 if (*endptr != '\0') { 8716 warnx("Invalid opcode \"%s\", must be a number", 8717 optarg); 8718 retval = 1; 8719 goto bailout; 8720 } 8721 if (opcode > 0xff) { 8722 warnx("Invalid opcode 0x%#x, must be between" 8723 "0 and 0xff inclusive", opcode); 8724 retval = 1; 8725 goto bailout; 8726 } 8727 opcode_set = 1; 8728 break; 8729 case 's': 8730 service_action = strtoul(optarg, &endptr, 0); 8731 if (*endptr != '\0') { 8732 warnx("Invalid service action \"%s\", must " 8733 "be a number", optarg); 8734 retval = 1; 8735 goto bailout; 8736 } 8737 if (service_action > 0xffff) { 8738 warnx("Invalid service action 0x%#x, must " 8739 "be between 0 and 0xffff inclusive", 8740 service_action); 8741 retval = 1; 8742 } 8743 sa_set = 1; 8744 break; 8745 case 'T': 8746 td_set = 1; 8747 break; 8748 default: 8749 break; 8750 } 8751 } 8752 8753 if ((sa_set != 0) 8754 && (opcode_set == 0)) { 8755 warnx("You must specify an opcode with -o if a service " 8756 "action is given"); 8757 retval = 1; 8758 goto bailout; 8759 } 8760 retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors, 8761 sa_set, service_action, td_set, task_attr, 8762 retry_count, timeout, verbosemode, &valid_len, 8763 &buf); 8764 if (retval != 0) 8765 goto bailout; 8766 8767 if ((opcode_set != 0) 8768 || (sa_set != 0)) { 8769 retval = scsiprintoneopcode(device, opcode, sa_set, 8770 service_action, buf, valid_len); 8771 } else { 8772 retval = scsiprintopcodes(device, td_set, buf, valid_len); 8773 } 8774 8775bailout: 8776 free(buf); 8777 8778 return (retval); 8779} 8780 8781#endif /* MINIMALISTIC */ 8782 8783static int 8784scsireprobe(struct cam_device *device) 8785{ 8786 union ccb *ccb; 8787 int retval = 0; 8788 8789 ccb = cam_getccb(device); 8790 8791 if (ccb == NULL) { 8792 warnx("%s: error allocating ccb", __func__); 8793 return (1); 8794 } 8795 8796 CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 8797 8798 ccb->ccb_h.func_code = XPT_REPROBE_LUN; 8799 8800 if (cam_send_ccb(device, ccb) < 0) { 8801 warn("error sending XPT_REPROBE_LUN CCB"); 8802 retval = 1; 8803 goto bailout; 8804 } 8805 8806 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 8807 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 8808 retval = 1; 8809 goto bailout; 8810 } 8811 8812bailout: 8813 cam_freeccb(ccb); 8814 8815 return (retval); 8816} 8817 8818void 8819usage(int printlong) 8820{ 8821 8822 fprintf(printlong ? stdout : stderr, 8823"usage: camcontrol <command> [device id][generic args][command args]\n" 8824" camcontrol devlist [-b] [-v]\n" 8825#ifndef MINIMALISTIC 8826" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n" 8827" camcontrol tur [dev_id][generic args]\n" 8828" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n" 8829" camcontrol identify [dev_id][generic args] [-v]\n" 8830" camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n" 8831" camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n" 8832" [-q] [-s]\n" 8833" camcontrol start [dev_id][generic args]\n" 8834" camcontrol stop [dev_id][generic args]\n" 8835" camcontrol load [dev_id][generic args]\n" 8836" camcontrol eject [dev_id][generic args]\n" 8837" camcontrol reprobe [dev_id][generic args]\n" 8838#endif /* MINIMALISTIC */ 8839" camcontrol rescan <all | bus[:target:lun] | dev_id>\n" 8840" camcontrol reset <all | bus[:target:lun] | dev_id>\n" 8841#ifndef MINIMALISTIC 8842" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n" 8843" [-q][-s][-S offset][-X]\n" 8844" camcontrol modepage [dev_id][generic args] <-m page | -l>\n" 8845" [-P pagectl][-e | -b][-d]\n" 8846" camcontrol cmd [dev_id][generic args]\n" 8847" <-a cmd [args] | -c cmd [args]>\n" 8848" [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n" 8849" camcontrol smpcmd [dev_id][generic args]\n" 8850" <-r len fmt [args]> <-R len fmt [args]>\n" 8851" camcontrol smprg [dev_id][generic args][-l]\n" 8852" camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n" 8853" [-o operation][-d name][-m rate][-M rate]\n" 8854" [-T pp_timeout][-a enable|disable]\n" 8855" [-A enable|disable][-s enable|disable]\n" 8856" [-S enable|disable]\n" 8857" camcontrol smpphylist [dev_id][generic args][-l][-q]\n" 8858" camcontrol smpmaninfo [dev_id][generic args][-l]\n" 8859" camcontrol debug [-I][-P][-T][-S][-X][-c]\n" 8860" <all|bus[:target[:lun]]|off>\n" 8861" camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n" 8862" camcontrol negotiate [dev_id][generic args] [-a][-c]\n" 8863" [-D <enable|disable>][-M mode][-O offset]\n" 8864" [-q][-R syncrate][-v][-T <enable|disable>]\n" 8865" [-U][-W bus_width]\n" 8866" camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n" 8867" camcontrol sanitize [dev_id][generic args]\n" 8868" [-a overwrite|block|crypto|exitfailure]\n" 8869" [-c passes][-I][-P pattern][-q][-U][-r][-w]\n" 8870" [-y]\n" 8871" camcontrol idle [dev_id][generic args][-t time]\n" 8872" camcontrol standby [dev_id][generic args][-t time]\n" 8873" camcontrol sleep [dev_id][generic args]\n" 8874" camcontrol apm [dev_id][generic args][-l level]\n" 8875" camcontrol aam [dev_id][generic args][-l level]\n" 8876" camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n" 8877" [-s][-y]\n" 8878" camcontrol security [dev_id][generic args]\n" 8879" <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n" 8880" [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n" 8881" [-U <user|master>] [-y]\n" 8882" camcontrol hpa [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n" 8883" [-q] [-s max_sectors] [-U pwd] [-y]\n" 8884" camcontrol persist [dev_id][generic args] <-i action|-o action>\n" 8885" [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n" 8886" [-s scope][-S][-T type][-U]\n" 8887" camcontrol attrib [dev_id][generic args] <-r action|-w attr>\n" 8888" [-a attr_num][-c][-e elem][-F form1,form1]\n" 8889" [-p part][-s start][-T type][-V vol]\n" 8890" camcontrol opcodes [dev_id][generic args][-o opcode][-s SA]\n" 8891" [-N][-T]\n" 8892#endif /* MINIMALISTIC */ 8893" camcontrol help\n"); 8894 if (!printlong) 8895 return; 8896#ifndef MINIMALISTIC 8897 fprintf(stdout, 8898"Specify one of the following options:\n" 8899"devlist list all CAM devices\n" 8900"periphlist list all CAM peripheral drivers attached to a device\n" 8901"tur send a test unit ready to the named device\n" 8902"inquiry send a SCSI inquiry command to the named device\n" 8903"identify send a ATA identify command to the named device\n" 8904"reportluns send a SCSI report luns command to the device\n" 8905"readcap send a SCSI read capacity command to the device\n" 8906"start send a Start Unit command to the device\n" 8907"stop send a Stop Unit command to the device\n" 8908"load send a Start Unit command to the device with the load bit set\n" 8909"eject send a Stop Unit command to the device with the eject bit set\n" 8910"reprobe update capacity information of the given device\n" 8911"rescan rescan all buses, the given bus, bus:target:lun or device\n" 8912"reset reset all buses, the given bus, bus:target:lun or device\n" 8913"defects read the defect list of the specified device\n" 8914"modepage display or edit (-e) the given mode page\n" 8915"cmd send the given SCSI command, may need -i or -o as well\n" 8916"smpcmd send the given SMP command, requires -o and -i\n" 8917"smprg send the SMP Report General command\n" 8918"smppc send the SMP PHY Control command, requires -p\n" 8919"smpphylist display phys attached to a SAS expander\n" 8920"smpmaninfo send the SMP Report Manufacturer Info command\n" 8921"debug turn debugging on/off for a bus, target, or lun, or all devices\n" 8922"tags report or set the number of transaction slots for a device\n" 8923"negotiate report or set device negotiation parameters\n" 8924"format send the SCSI FORMAT UNIT command to the named device\n" 8925"sanitize send the SCSI SANITIZE command to the named device\n" 8926"idle send the ATA IDLE command to the named device\n" 8927"standby send the ATA STANDBY command to the named device\n" 8928"sleep send the ATA SLEEP command to the named device\n" 8929"fwdownload program firmware of the named device with the given image\n" 8930"security report or send ATA security commands to the named device\n" 8931"persist send the SCSI PERSISTENT RESERVE IN or OUT commands\n" 8932"attrib send the SCSI READ or WRITE ATTRIBUTE commands\n" 8933"opcodes send the SCSI REPORT SUPPORTED OPCODES command\n" 8934"help this message\n" 8935"Device Identifiers:\n" 8936"bus:target specify the bus and target, lun defaults to 0\n" 8937"bus:target:lun specify the bus, target and lun\n" 8938"deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n" 8939"Generic arguments:\n" 8940"-v be verbose, print out sense information\n" 8941"-t timeout command timeout in seconds, overrides default timeout\n" 8942"-n dev_name specify device name, e.g. \"da\", \"cd\"\n" 8943"-u unit specify unit number, e.g. \"0\", \"5\"\n" 8944"-E have the kernel attempt to perform SCSI error recovery\n" 8945"-C count specify the SCSI command retry count (needs -E to work)\n" 8946"-Q task_attr specify ordered, simple or head tag type for SCSI cmds\n" 8947"modepage arguments:\n" 8948"-l list all available mode pages\n" 8949"-m page specify the mode page to view or edit\n" 8950"-e edit the specified mode page\n" 8951"-b force view to binary mode\n" 8952"-d disable block descriptors for mode sense\n" 8953"-P pgctl page control field 0-3\n" 8954"defects arguments:\n" 8955"-f format specify defect list format (block, bfi or phys)\n" 8956"-G get the grown defect list\n" 8957"-P get the permanent defect list\n" 8958"inquiry arguments:\n" 8959"-D get the standard inquiry data\n" 8960"-S get the serial number\n" 8961"-R get the transfer rate, etc.\n" 8962"reportluns arguments:\n" 8963"-c only report a count of available LUNs\n" 8964"-l only print out luns, and not a count\n" 8965"-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n" 8966"readcap arguments\n" 8967"-b only report the blocksize\n" 8968"-h human readable device size, base 2\n" 8969"-H human readable device size, base 10\n" 8970"-N print the number of blocks instead of last block\n" 8971"-q quiet, print numbers only\n" 8972"-s only report the last block/device size\n" 8973"cmd arguments:\n" 8974"-c cdb [args] specify the SCSI CDB\n" 8975"-i len fmt specify input data and input data format\n" 8976"-o len fmt [args] specify output data and output data fmt\n" 8977"smpcmd arguments:\n" 8978"-r len fmt [args] specify the SMP command to be sent\n" 8979"-R len fmt [args] specify SMP response format\n" 8980"smprg arguments:\n" 8981"-l specify the long response format\n" 8982"smppc arguments:\n" 8983"-p phy specify the PHY to operate on\n" 8984"-l specify the long request/response format\n" 8985"-o operation specify the phy control operation\n" 8986"-d name set the attached device name\n" 8987"-m rate set the minimum physical link rate\n" 8988"-M rate set the maximum physical link rate\n" 8989"-T pp_timeout set the partial pathway timeout value\n" 8990"-a enable|disable enable or disable SATA slumber\n" 8991"-A enable|disable enable or disable SATA partial phy power\n" 8992"-s enable|disable enable or disable SAS slumber\n" 8993"-S enable|disable enable or disable SAS partial phy power\n" 8994"smpphylist arguments:\n" 8995"-l specify the long response format\n" 8996"-q only print phys with attached devices\n" 8997"smpmaninfo arguments:\n" 8998"-l specify the long response format\n" 8999"debug arguments:\n" 9000"-I CAM_DEBUG_INFO -- scsi commands, errors, data\n" 9001"-T CAM_DEBUG_TRACE -- routine flow tracking\n" 9002"-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n" 9003"-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n" 9004"tags arguments:\n" 9005"-N tags specify the number of tags to use for this device\n" 9006"-q be quiet, don't report the number of tags\n" 9007"-v report a number of tag-related parameters\n" 9008"negotiate arguments:\n" 9009"-a send a test unit ready after negotiation\n" 9010"-c report/set current negotiation settings\n" 9011"-D <arg> \"enable\" or \"disable\" disconnection\n" 9012"-M mode set ATA mode\n" 9013"-O offset set command delay offset\n" 9014"-q be quiet, don't report anything\n" 9015"-R syncrate synchronization rate in MHz\n" 9016"-T <arg> \"enable\" or \"disable\" tagged queueing\n" 9017"-U report/set user negotiation settings\n" 9018"-W bus_width set the bus width in bits (8, 16 or 32)\n" 9019"-v also print a Path Inquiry CCB for the controller\n" 9020"format arguments:\n" 9021"-q be quiet, don't print status messages\n" 9022"-r run in report only mode\n" 9023"-w don't send immediate format command\n" 9024"-y don't ask any questions\n" 9025"sanitize arguments:\n" 9026"-a operation operation mode: overwrite, block, crypto or exitfailure\n" 9027"-c passes overwrite passes to perform (1 to 31)\n" 9028"-I invert overwrite pattern after each pass\n" 9029"-P pattern path to overwrite pattern file\n" 9030"-q be quiet, don't print status messages\n" 9031"-r run in report only mode\n" 9032"-U run operation in unrestricted completion exit mode\n" 9033"-w don't send immediate sanitize command\n" 9034"-y don't ask any questions\n" 9035"idle/standby arguments:\n" 9036"-t <arg> number of seconds before respective state.\n" 9037"fwdownload arguments:\n" 9038"-f fw_image path to firmware image file\n" 9039"-q don't print informational messages, only errors\n" 9040"-s run in simulation mode\n" 9041"-v print info for every firmware segment sent to device\n" 9042"-y don't ask any questions\n" 9043"security arguments:\n" 9044"-d pwd disable security using the given password for the selected\n" 9045" user\n" 9046"-e pwd erase the device using the given pwd for the selected user\n" 9047"-f freeze the security configuration of the specified device\n" 9048"-h pwd enhanced erase the device using the given pwd for the\n" 9049" selected user\n" 9050"-k pwd unlock the device using the given pwd for the selected\n" 9051" user\n" 9052"-l <high|maximum> specifies which security level to set: high or maximum\n" 9053"-q be quiet, do not print any status messages\n" 9054"-s pwd password the device (enable security) using the given\n" 9055" pwd for the selected user\n" 9056"-T timeout overrides the timeout (seconds) used for erase operation\n" 9057"-U <user|master> specifies which user to set: user or master\n" 9058"-y don't ask any questions\n" 9059"hpa arguments:\n" 9060"-f freeze the HPA configuration of the device\n" 9061"-l lock the HPA configuration of the device\n" 9062"-P make the HPA max sectors persist\n" 9063"-p pwd Set the HPA configuration password required for unlock\n" 9064" calls\n" 9065"-q be quiet, do not print any status messages\n" 9066"-s sectors configures the maximum user accessible sectors of the\n" 9067" device\n" 9068"-U pwd unlock the HPA configuration of the device\n" 9069"-y don't ask any questions\n" 9070"persist arguments:\n" 9071"-i action specify read_keys, read_reservation, report_cap, or\n" 9072" read_full_status\n" 9073"-o action specify register, register_ignore, reserve, release,\n" 9074" clear, preempt, preempt_abort, register_move, replace_lost\n" 9075"-a set the All Target Ports (ALL_TG_PT) bit\n" 9076"-I tid specify a Transport ID, e.g.: sas,0x1234567812345678\n" 9077"-k key specify the Reservation Key\n" 9078"-K sa_key specify the Service Action Reservation Key\n" 9079"-p set the Activate Persist Through Power Loss bit\n" 9080"-R rtp specify the Relative Target Port\n" 9081"-s scope specify the scope: lun, extent, element or a number\n" 9082"-S specify Transport ID for register, requires -I\n" 9083"-T res_type specify the reservation type: read_shared, wr_ex, rd_ex,\n" 9084" ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n" 9085"-U unregister the current initiator for register_move\n" 9086"attrib arguments:\n" 9087"-r action specify attr_values, attr_list, lv_list, part_list, or\n" 9088" supp_attr\n" 9089"-w attr specify an attribute to write, one -w argument per attr\n" 9090"-a attr_num only display this attribute number\n" 9091"-c get cached attributes\n" 9092"-e elem_addr request attributes for the given element in a changer\n" 9093"-F form1,form2 output format, comma separated list: text_esc, text_raw,\n" 9094" nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n" 9095" field_none, field_desc, field_num, field_size, field_rw\n" 9096"-p partition request attributes for the given partition\n" 9097"-s start_attr request attributes starting at the given number\n" 9098"-T elem_type specify the element type (used with -e)\n" 9099"-V logical_vol specify the logical volume ID\n" 9100"opcodes arguments:\n" 9101"-o opcode specify the individual opcode to list\n" 9102"-s service_action specify the service action for the opcode\n" 9103"-N do not return SCSI error for unsupported SA\n" 9104"-T request nominal and recommended timeout values\n" 9105); 9106#endif /* MINIMALISTIC */ 9107} 9108 9109int 9110main(int argc, char **argv) 9111{ 9112 int c; 9113 char *device = NULL; 9114 int unit = 0; 9115 struct cam_device *cam_dev = NULL; 9116 int timeout = 0, retry_count = 1; 9117 camcontrol_optret optreturn; 9118 char *tstr; 9119 const char *mainopt = "C:En:Q:t:u:v"; 9120 const char *subopt = NULL; 9121 char combinedopt[256]; 9122 int error = 0, optstart = 2; 9123 int task_attr = MSG_SIMPLE_Q_TAG; 9124 int devopen = 1; 9125#ifndef MINIMALISTIC 9126 path_id_t bus; 9127 target_id_t target; 9128 lun_id_t lun; 9129#endif /* MINIMALISTIC */ 9130 9131 cmdlist = CAM_CMD_NONE; 9132 arglist = CAM_ARG_NONE; 9133 9134 if (argc < 2) { 9135 usage(0); 9136 exit(1); 9137 } 9138 9139 /* 9140 * Get the base option. 9141 */ 9142 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt); 9143 9144 if (optreturn == CC_OR_AMBIGUOUS) { 9145 warnx("ambiguous option %s", argv[1]); 9146 usage(0); 9147 exit(1); 9148 } else if (optreturn == CC_OR_NOT_FOUND) { 9149 warnx("option %s not found", argv[1]); 9150 usage(0); 9151 exit(1); 9152 } 9153 9154 /* 9155 * Ahh, getopt(3) is a pain. 9156 * 9157 * This is a gross hack. There really aren't many other good 9158 * options (excuse the pun) for parsing options in a situation like 9159 * this. getopt is kinda braindead, so you end up having to run 9160 * through the options twice, and give each invocation of getopt 9161 * the option string for the other invocation. 9162 * 9163 * You would think that you could just have two groups of options. 9164 * The first group would get parsed by the first invocation of 9165 * getopt, and the second group would get parsed by the second 9166 * invocation of getopt. It doesn't quite work out that way. When 9167 * the first invocation of getopt finishes, it leaves optind pointing 9168 * to the argument _after_ the first argument in the second group. 9169 * So when the second invocation of getopt comes around, it doesn't 9170 * recognize the first argument it gets and then bails out. 9171 * 9172 * A nice alternative would be to have a flag for getopt that says 9173 * "just keep parsing arguments even when you encounter an unknown 9174 * argument", but there isn't one. So there's no real clean way to 9175 * easily parse two sets of arguments without having one invocation 9176 * of getopt know about the other. 9177 * 9178 * Without this hack, the first invocation of getopt would work as 9179 * long as the generic arguments are first, but the second invocation 9180 * (in the subfunction) would fail in one of two ways. In the case 9181 * where you don't set optreset, it would fail because optind may be 9182 * pointing to the argument after the one it should be pointing at. 9183 * In the case where you do set optreset, and reset optind, it would 9184 * fail because getopt would run into the first set of options, which 9185 * it doesn't understand. 9186 * 9187 * All of this would "sort of" work if you could somehow figure out 9188 * whether optind had been incremented one option too far. The 9189 * mechanics of that, however, are more daunting than just giving 9190 * both invocations all of the expect options for either invocation. 9191 * 9192 * Needless to say, I wouldn't mind if someone invented a better 9193 * (non-GPL!) command line parsing interface than getopt. I 9194 * wouldn't mind if someone added more knobs to getopt to make it 9195 * work better. Who knows, I may talk myself into doing it someday, 9196 * if the standards weenies let me. As it is, it just leads to 9197 * hackery like this and causes people to avoid it in some cases. 9198 * 9199 * KDM, September 8th, 1998 9200 */ 9201 if (subopt != NULL) 9202 sprintf(combinedopt, "%s%s", mainopt, subopt); 9203 else 9204 sprintf(combinedopt, "%s", mainopt); 9205 9206 /* 9207 * For these options we do not parse optional device arguments and 9208 * we do not open a passthrough device. 9209 */ 9210 if ((cmdlist == CAM_CMD_RESCAN) 9211 || (cmdlist == CAM_CMD_RESET) 9212 || (cmdlist == CAM_CMD_DEVTREE) 9213 || (cmdlist == CAM_CMD_USAGE) 9214 || (cmdlist == CAM_CMD_DEBUG)) 9215 devopen = 0; 9216 9217#ifndef MINIMALISTIC 9218 if ((devopen == 1) 9219 && (argc > 2 && argv[2][0] != '-')) { 9220 char name[30]; 9221 int rv; 9222 9223 if (isdigit(argv[2][0])) { 9224 /* device specified as bus:target[:lun] */ 9225 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist); 9226 if (rv < 2) 9227 errx(1, "numeric device specification must " 9228 "be either bus:target, or " 9229 "bus:target:lun"); 9230 /* default to 0 if lun was not specified */ 9231 if ((arglist & CAM_ARG_LUN) == 0) { 9232 lun = 0; 9233 arglist |= CAM_ARG_LUN; 9234 } 9235 optstart++; 9236 } else { 9237 if (cam_get_device(argv[2], name, sizeof name, &unit) 9238 == -1) 9239 errx(1, "%s", cam_errbuf); 9240 device = strdup(name); 9241 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT; 9242 optstart++; 9243 } 9244 } 9245#endif /* MINIMALISTIC */ 9246 /* 9247 * Start getopt processing at argv[2/3], since we've already 9248 * accepted argv[1..2] as the command name, and as a possible 9249 * device name. 9250 */ 9251 optind = optstart; 9252 9253 /* 9254 * Now we run through the argument list looking for generic 9255 * options, and ignoring options that possibly belong to 9256 * subfunctions. 9257 */ 9258 while ((c = getopt(argc, argv, combinedopt))!= -1){ 9259 switch(c) { 9260 case 'C': 9261 retry_count = strtol(optarg, NULL, 0); 9262 if (retry_count < 0) 9263 errx(1, "retry count %d is < 0", 9264 retry_count); 9265 arglist |= CAM_ARG_RETRIES; 9266 break; 9267 case 'E': 9268 arglist |= CAM_ARG_ERR_RECOVER; 9269 break; 9270 case 'n': 9271 arglist |= CAM_ARG_DEVICE; 9272 tstr = optarg; 9273 while (isspace(*tstr) && (*tstr != '\0')) 9274 tstr++; 9275 device = (char *)strdup(tstr); 9276 break; 9277 case 'Q': { 9278 char *endptr; 9279 int table_entry = 0; 9280 9281 tstr = optarg; 9282 while (isspace(*tstr) && (*tstr != '\0')) 9283 tstr++; 9284 if (isdigit(*tstr)) { 9285 task_attr = strtol(tstr, &endptr, 0); 9286 if (*endptr != '\0') { 9287 errx(1, "Invalid queue option " 9288 "%s", tstr); 9289 } 9290 } else { 9291 size_t table_size; 9292 scsi_nv_status status; 9293 9294 table_size = sizeof(task_attrs) / 9295 sizeof(task_attrs[0]); 9296 status = scsi_get_nv(task_attrs, 9297 table_size, tstr, &table_entry, 9298 SCSI_NV_FLAG_IG_CASE); 9299 if (status == SCSI_NV_FOUND) 9300 task_attr = task_attrs[ 9301 table_entry].value; 9302 else { 9303 errx(1, "%s option %s", 9304 (status == SCSI_NV_AMBIGUOUS)? 9305 "ambiguous" : "invalid", 9306 tstr); 9307 } 9308 } 9309 break; 9310 } 9311 case 't': 9312 timeout = strtol(optarg, NULL, 0); 9313 if (timeout < 0) 9314 errx(1, "invalid timeout %d", timeout); 9315 /* Convert the timeout from seconds to ms */ 9316 timeout *= 1000; 9317 arglist |= CAM_ARG_TIMEOUT; 9318 break; 9319 case 'u': 9320 arglist |= CAM_ARG_UNIT; 9321 unit = strtol(optarg, NULL, 0); 9322 break; 9323 case 'v': 9324 arglist |= CAM_ARG_VERBOSE; 9325 break; 9326 default: 9327 break; 9328 } 9329 } 9330 9331#ifndef MINIMALISTIC 9332 /* 9333 * For most commands we'll want to open the passthrough device 9334 * associated with the specified device. In the case of the rescan 9335 * commands, we don't use a passthrough device at all, just the 9336 * transport layer device. 9337 */ 9338 if (devopen == 1) { 9339 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0) 9340 && (((arglist & CAM_ARG_DEVICE) == 0) 9341 || ((arglist & CAM_ARG_UNIT) == 0))) { 9342 errx(1, "subcommand \"%s\" requires a valid device " 9343 "identifier", argv[1]); 9344 } 9345 9346 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))? 9347 cam_open_btl(bus, target, lun, O_RDWR, NULL) : 9348 cam_open_spec_device(device,unit,O_RDWR,NULL))) 9349 == NULL) 9350 errx(1,"%s", cam_errbuf); 9351 } 9352#endif /* MINIMALISTIC */ 9353 9354 /* 9355 * Reset optind to 2, and reset getopt, so these routines can parse 9356 * the arguments again. 9357 */ 9358 optind = optstart; 9359 optreset = 1; 9360 9361 switch(cmdlist) { 9362#ifndef MINIMALISTIC 9363 case CAM_CMD_DEVLIST: 9364 error = getdevlist(cam_dev); 9365 break; 9366 case CAM_CMD_HPA: 9367 error = atahpa(cam_dev, retry_count, timeout, 9368 argc, argv, combinedopt); 9369 break; 9370#endif /* MINIMALISTIC */ 9371 case CAM_CMD_DEVTREE: 9372 error = getdevtree(argc, argv, combinedopt); 9373 break; 9374#ifndef MINIMALISTIC 9375 case CAM_CMD_TUR: 9376 error = testunitready(cam_dev, task_attr, retry_count, 9377 timeout, 0); 9378 break; 9379 case CAM_CMD_INQUIRY: 9380 error = scsidoinquiry(cam_dev, argc, argv, combinedopt, 9381 task_attr, retry_count, timeout); 9382 break; 9383 case CAM_CMD_IDENTIFY: 9384 error = ataidentify(cam_dev, retry_count, timeout); 9385 break; 9386 case CAM_CMD_STARTSTOP: 9387 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT, 9388 arglist & CAM_ARG_EJECT, task_attr, 9389 retry_count, timeout); 9390 break; 9391#endif /* MINIMALISTIC */ 9392 case CAM_CMD_RESCAN: 9393 error = dorescan_or_reset(argc, argv, 1); 9394 break; 9395 case CAM_CMD_RESET: 9396 error = dorescan_or_reset(argc, argv, 0); 9397 break; 9398#ifndef MINIMALISTIC 9399 case CAM_CMD_READ_DEFECTS: 9400 error = readdefects(cam_dev, argc, argv, combinedopt, 9401 task_attr, retry_count, timeout); 9402 break; 9403 case CAM_CMD_MODE_PAGE: 9404 modepage(cam_dev, argc, argv, combinedopt, 9405 task_attr, retry_count, timeout); 9406 break; 9407 case CAM_CMD_SCSI_CMD: 9408 error = scsicmd(cam_dev, argc, argv, combinedopt, 9409 task_attr, retry_count, timeout); 9410 break; 9411 case CAM_CMD_SMP_CMD: 9412 error = smpcmd(cam_dev, argc, argv, combinedopt, 9413 retry_count, timeout); 9414 break; 9415 case CAM_CMD_SMP_RG: 9416 error = smpreportgeneral(cam_dev, argc, argv, 9417 combinedopt, retry_count, 9418 timeout); 9419 break; 9420 case CAM_CMD_SMP_PC: 9421 error = smpphycontrol(cam_dev, argc, argv, combinedopt, 9422 retry_count, timeout); 9423 break; 9424 case CAM_CMD_SMP_PHYLIST: 9425 error = smpphylist(cam_dev, argc, argv, combinedopt, 9426 retry_count, timeout); 9427 break; 9428 case CAM_CMD_SMP_MANINFO: 9429 error = smpmaninfo(cam_dev, argc, argv, combinedopt, 9430 retry_count, timeout); 9431 break; 9432 case CAM_CMD_DEBUG: 9433 error = camdebug(argc, argv, combinedopt); 9434 break; 9435 case CAM_CMD_TAG: 9436 error = tagcontrol(cam_dev, argc, argv, combinedopt); 9437 break; 9438 case CAM_CMD_RATE: 9439 error = ratecontrol(cam_dev, task_attr, retry_count, 9440 timeout, argc, argv, combinedopt); 9441 break; 9442 case CAM_CMD_FORMAT: 9443 error = scsiformat(cam_dev, argc, argv, 9444 combinedopt, task_attr, retry_count, 9445 timeout); 9446 break; 9447 case CAM_CMD_REPORTLUNS: 9448 error = scsireportluns(cam_dev, argc, argv, 9449 combinedopt, task_attr, 9450 retry_count, timeout); 9451 break; 9452 case CAM_CMD_READCAP: 9453 error = scsireadcapacity(cam_dev, argc, argv, 9454 combinedopt, task_attr, 9455 retry_count, timeout); 9456 break; 9457 case CAM_CMD_IDLE: 9458 case CAM_CMD_STANDBY: 9459 case CAM_CMD_SLEEP: 9460 error = atapm(cam_dev, argc, argv, 9461 combinedopt, retry_count, timeout); 9462 break; 9463 case CAM_CMD_APM: 9464 case CAM_CMD_AAM: 9465 error = ataaxm(cam_dev, argc, argv, 9466 combinedopt, retry_count, timeout); 9467 break; 9468 case CAM_CMD_SECURITY: 9469 error = atasecurity(cam_dev, retry_count, timeout, 9470 argc, argv, combinedopt); 9471 break; 9472 case CAM_CMD_DOWNLOAD_FW: 9473 error = fwdownload(cam_dev, argc, argv, combinedopt, 9474 arglist & CAM_ARG_VERBOSE, task_attr, retry_count, 9475 timeout); 9476 break; 9477 case CAM_CMD_SANITIZE: 9478 error = scsisanitize(cam_dev, argc, argv, 9479 combinedopt, task_attr, 9480 retry_count, timeout); 9481 break; 9482 case CAM_CMD_PERSIST: 9483 error = scsipersist(cam_dev, argc, argv, combinedopt, 9484 task_attr, retry_count, timeout, 9485 arglist & CAM_ARG_VERBOSE, 9486 arglist & CAM_ARG_ERR_RECOVER); 9487 break; 9488 case CAM_CMD_ATTRIB: 9489 error = scsiattrib(cam_dev, argc, argv, combinedopt, 9490 task_attr, retry_count, timeout, 9491 arglist & CAM_ARG_VERBOSE, 9492 arglist & CAM_ARG_ERR_RECOVER); 9493 break; 9494 case CAM_CMD_OPCODES: 9495 error = scsiopcodes(cam_dev, argc, argv, combinedopt, 9496 task_attr, retry_count, timeout, 9497 arglist & CAM_ARG_VERBOSE); 9498 break; 9499 case CAM_CMD_REPROBE: 9500 error = scsireprobe(cam_dev); 9501 break; 9502 9503#endif /* MINIMALISTIC */ 9504 case CAM_CMD_USAGE: 9505 usage(1); 9506 break; 9507 default: 9508 usage(0); 9509 error = 1; 9510 break; 9511 } 9512 9513 if (cam_dev != NULL) 9514 cam_close_device(cam_dev); 9515 9516 exit(error); 9517} 9518