1 #ifndef SG_PT_LINUX_H 2 #define SG_PT_LINUX_H 3 4 /* 5 * Copyright (c) 2017-2018 Douglas Gilbert. 6 * All rights reserved. 7 * Use of this source code is governed by a BSD-style 8 * license that can be found in the BSD_LICENSE file. 9 * 10 * SPDX-License-Identifier: BSD-2-Clause 11 */ 12 13 #include <stdint.h> 14 #include <stdbool.h> 15 16 #include <linux/types.h> 17 18 #include "sg_pt_nvme.h" 19 20 /* This header is for internal use by the sg3_utils library (libsgutils) 21 * and is Linux specific. Best not to include it directly in code that 22 * is meant to be OS independent. */ 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 #ifndef HAVE_LINUX_BSG_H 29 30 #define BSG_PROTOCOL_SCSI 0 31 32 #define BSG_SUB_PROTOCOL_SCSI_CMD 0 33 #define BSG_SUB_PROTOCOL_SCSI_TMF 1 34 #define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2 35 36 /* 37 * For flag constants below: 38 * sg.h sg_io_hdr also has bits defined for it's flags member. These 39 * two flag values (0x10 and 0x20) have the same meaning in sg.h . For 40 * bsg the BSG_FLAG_Q_AT_HEAD flag is ignored since it is the default. 41 */ 42 #define BSG_FLAG_Q_AT_TAIL 0x10 /* default is Q_AT_HEAD */ 43 #define BSG_FLAG_Q_AT_HEAD 0x20 44 45 #ifndef SGV4_FLAG_YIELD_TAG 46 #define SGV4_FLAG_YIELD_TAG 0x8 47 #endif 48 #ifndef SGV4_FLAG_FIND_BY_TAG 49 #define SGV4_FLAG_FIND_BY_TAG 0x100 50 #endif 51 #ifndef SGV4_FLAG_IMMED 52 #define SGV4_FLAG_IMMED 0x400 53 #endif 54 #ifndef SGV4_FLAG_IMMED 55 #define SGV4_FLAG_IMMED 0x400 56 #endif 57 #ifndef SGV4_FLAG_DEV_SCOPE 58 #define SGV4_FLAG_DEV_SCOPE 0x1000 59 #endif 60 #ifndef SGV4_FLAG_SHARE 61 #define SGV4_FLAG_SHARE 0x2000 62 #endif 63 64 struct sg_io_v4 { 65 __s32 guard; /* [i] 'Q' to differentiate from v3 */ 66 __u32 protocol; /* [i] 0 -> SCSI , .... */ 67 __u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task 68 management function, .... */ 69 70 __u32 request_len; /* [i] in bytes */ 71 __u64 request; /* [i], [*i] {SCSI: cdb} */ 72 __u64 request_tag; /* [i] {in sg 4.0+ this is out parameter} */ 73 __u32 request_attr; /* [i] {SCSI: task attribute} */ 74 __u32 request_priority; /* [i] {SCSI: task priority} */ 75 __u32 request_extra; /* [i] {used for pack_id} */ 76 __u32 max_response_len; /* [i] in bytes */ 77 __u64 response; /* [i], [*o] {SCSI: (auto)sense data} */ 78 79 /* "dout_": data out (to device); "din_": data in (from device) */ 80 __u32 dout_iovec_count; /* [i] 0 -> "flat" dout transfer else 81 dout_xfer points to array of iovec */ 82 __u32 dout_xfer_len; /* [i] bytes to be transferred to device */ 83 __u32 din_iovec_count; /* [i] 0 -> "flat" din transfer */ 84 __u32 din_xfer_len; /* [i] bytes to be transferred from device */ 85 __u64 dout_xferp; /* [i], [*i] */ 86 __u64 din_xferp; /* [i], [*o] */ 87 88 __u32 timeout; /* [i] units: millisecond */ 89 __u32 flags; /* [i] bit mask */ 90 __u64 usr_ptr; /* [i->o] unused internally */ 91 __u32 spare_in; /* [i] */ 92 93 __u32 driver_status; /* [o] 0 -> ok */ 94 __u32 transport_status; /* [o] 0 -> ok */ 95 __u32 device_status; /* [o] {SCSI: command completion status} */ 96 __u32 retry_delay; /* [o] {SCSI: status auxiliary information} */ 97 __u32 info; /* [o] additional information */ 98 __u32 duration; /* [o] time to complete, in milliseconds */ 99 __u32 response_len; /* [o] bytes of response actually written */ 100 __s32 din_resid; /* [o] din_xfer_len - actual_din_xfer_len */ 101 __s32 dout_resid; /* [o] dout_xfer_len - actual_dout_xfer_len */ 102 __u64 generated_tag; /* [o] {SCSI: transport generated task tag} */ 103 __u32 spare_out; /* [o] */ 104 105 __u32 padding; 106 }; 107 108 #else 109 110 #include <linux/bsg.h> 111 112 #endif 113 114 115 struct sg_pt_linux_scsi { 116 struct sg_io_v4 io_hdr; /* use v4 header as it is more general */ 117 /* Leave io_hdr in first place of this structure */ 118 bool is_sg; 119 bool is_bsg; 120 bool is_nvme; /* OS device type, if false ignore nvme_our_sntl */ 121 bool nvme_our_sntl; /* true: our SNTL; false: received NVMe command */ 122 bool nvme_stat_dnr; /* Do No Retry, part of completion status field */ 123 bool nvme_stat_more; /* More, part of completion status field */ 124 bool mdxfer_out; /* direction of metadata xfer, true->data-out */ 125 int dev_fd; /* -1 if not given (yet) */ 126 int in_err; 127 int os_err; 128 int sg_version; /* for deciding whether to use v3 or v4 interface */ 129 uint32_t nvme_nsid; /* 1 to 0xfffffffe are possibly valid, 0 130 * implies dev_fd is not a NVMe device 131 * (is_nvme=false) or it is a NVMe char 132 * device (e.g. /dev/nvme0 ) */ 133 uint32_t nvme_result; /* DW0 from completion queue */ 134 uint32_t nvme_status; /* SCT|SC: DW3 27:17 from completion queue, 135 * note: the DNR+More bit are not there. 136 * The whole 16 byte completion q entry is 137 * sent back as sense data */ 138 uint32_t mdxfer_len; 139 struct sg_sntl_dev_state_t dev_stat; 140 void * mdxferp; 141 uint8_t * nvme_id_ctlp; /* cached response to controller IDENTIFY */ 142 uint8_t * free_nvme_id_ctlp; 143 uint8_t tmf_request[4]; 144 }; 145 146 struct sg_pt_base { 147 struct sg_pt_linux_scsi impl; 148 }; 149 150 151 #ifndef sg_nvme_admin_cmd 152 #define sg_nvme_admin_cmd sg_nvme_passthru_cmd 153 #endif 154 155 /* Linux NVMe related ioctls */ 156 #ifndef NVME_IOCTL_ID 157 #define NVME_IOCTL_ID _IO('N', 0x40) 158 #endif 159 #ifndef NVME_IOCTL_ADMIN_CMD 160 #define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct sg_nvme_admin_cmd) 161 #endif 162 #ifndef NVME_IOCTL_SUBMIT_IO 163 #define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct sg_nvme_user_io) 164 #endif 165 #ifndef NVME_IOCTL_IO_CMD 166 #define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct sg_nvme_passthru_cmd) 167 #endif 168 #ifndef NVME_IOCTL_RESET 169 #define NVME_IOCTL_RESET _IO('N', 0x44) 170 #endif 171 #ifndef NVME_IOCTL_SUBSYS_RESET 172 #define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45) 173 #endif 174 #ifndef NVME_IOCTL_RESCAN 175 #define NVME_IOCTL_RESCAN _IO('N', 0x46) 176 #endif 177 #if 0 178 #define NVME_IOCTL_ADMIN64_CMD _IOWR('N', 0x47, struct nvme_passthru_cmd64) 179 #define NVME_IOCTL_IO64_CMD _IOWR('N', 0x48, struct nvme_passthru_cmd64) 180 #endif 181 182 extern bool sg_bsg_nvme_char_major_checked; 183 extern int sg_bsg_major; 184 extern volatile int sg_nvme_char_major; 185 extern long sg_lin_page_size; 186 187 void sg_find_bsg_nvme_char_major(int verbose); 188 int sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int time_secs, int vb); 189 int sg_linux_get_sg_version(const struct sg_pt_base * vp); 190 191 /* This trims given NVMe block device name in Linux (e.g. /dev/nvme0n1p5) 192 * to the name of its associated char device (e.g. /dev/nvme0). If this 193 * occurs true is returned and the char device name is placed in 'b' (as 194 * long as b_len is sufficient). Otherwise false is returned. */ 195 bool sg_get_nvme_char_devname(const char * nvme_block_devname, uint32_t b_len, 196 char * b); 197 198 #ifdef __cplusplus 199 } 200 #endif 201 202 #endif /* end of SG_PT_LINUX_H */ 203