Home | History | Annotate | Download | only in include
      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