• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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