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