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