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