/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* rspc72X src/bos/kernel/sys/nvme.h 1.8                                  */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2017,2021              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef _H_NVME
#define _H_NVME

/*
 * COMPONENT_NAME: sysxnvme
 *
 * FUNCTIONS:   NONE
 *
 * NAME:        nvme.h
 *
 * FUNCTION:    
 *              NVMe adapter and disk driver user ioctls.
 */

#include <sys/types.h>

#define NVME_DELETE_IO_SQ         0x00 /* Admin cmd set */
#define NVME_CREATE_IO_SQ         0x01
#define NVME_GET_LOG_PAGE         0x02
#define NVME_DELETE_IO_CQ         0x04
#define NVME_CREATE_IO_CQ         0x05
#define NVME_IDENTIFY             0x06
#define NVME_SET_FEATURES         0x09
#define NVME_GET_FEATURES         0x0A
#define NVME_ASYNC_EVENT_REQUEST  0x0C
#define NVME_NAMESPACE_MGMT       0x0D
#define NVME_FIRMWARE_COMMIT      0x10
#define NVME_FIRMWARE_DNLD        0x11
#define NVME_NAMESPACE_ATTACH     0x15
#define NVME_KEEP_ALIVE           0x18 
#define NVME_FORMAT_NVM           0x80 /* Admin cmds specific to NVM */

#define NVME_WRITE                0x01 /* NVM cmd set */
#define NVME_READ                 0x02
#define NVME_DSM                  0x09

#define NVME_FABRIC_CMD           0x7F /* Fabric cmd set */


#define NVME_SMART_HEALTH_LOG     0x02 /* Log page IDs */


#define NVME_IDENT_CONTROLLER     0x01 /* CNS field in Identify */
#define NVME_IDENT_NAMESPACE      0x00
#define NVME_QUERY_NAMESPACE      0x02
#define NVME_DESC_NAMESPACE       0x03

#define NVME_FID_TMPTH            0x04 /* Feature IDs */
#define NVME_FID_NUM_QUEUES       0x07
#define NVME_FID_EVENT_CONFIG     0x0B

#define EVENT_FW_ACT_NOTICE           (1u << 9) /* Events in set features */
#define EVENT_NS_ATTR_NOTICE          (1u << 8)
#define EVENT_SMART_SPARE_TH          (1u << 0)
#define EVENT_SMART_TEMP_TH           (1u << 1)
#define EVENT_SMART_SUBSYS_DEGRADED   (1u << 2)
#define EVENT_SMART_MEDIA_READ_ONLY   (1u << 3)
#define EVENT_SMART_MEM_BACKUP_FAILED (1u << 4)

/******************************************************************
 *                                                                *
 *      newer defines for un.nvme in devinfo.h are placed here    *
 *                                                                *
 ******************************************************************/
#define NVME_CAP_DSM   0x2 /* 'capability' following NVME_CAP_SGL */
                           /* Data Set Management is supported    */
#define NVME_CAP_SPIO  0x4 /* single path(AIX MPIO is turned off) */

/******************************************************************
 *                                                                *
 *                       NVMe ioctls                              *
 *                                                                *
 ******************************************************************/

#define NVME_PASSTHRU       0x1000 /* valid on adapter devno.
                                      disk devno in the future
                                   */
#define NVME_CNTL           0x1001 /* valid on adapter devno only */

#define NVME_STAT           0x1200 /* valid on adapter devno only 
                                    * For internal use, arg is a 
                                    * private struct.
                                    */

#ifdef _KERNEL
#define NVME_RCHN_OPEN      0x1FFF /* kernel ioctl on adapter devno */
#define NVME_RCHN_CLOSE     0x1FFE /* kernel ioctl on adapter devno */
#endif

/*
 * NVME_PASSTHRU ioctl structure 
 *
 * The user must be careful to send 
 *   - a admin command only to the adapter device
 *   - a NVM command only to the disk device
 *
 * Failure to do so can produce undefined behavior including data
 * corruption. Note that NVMe command opcodes are unique only
 * within a command set and the opcode value can perform different
 * operations in different command sets.
 *
 * dword_10 to dword_15 are written by the user in host native endian
 * such that (leftmost) bit 31 is the most significant bit and 
 * (rightmost) bit 0 is least significant as shown in the NVMe
 * specification. For example, to read 0xAC blocks and set
 * FUA, dword_10 in the passthru structure will be set to 0x400000AB.
 *
 * The user must byte swap any fields in the "data" being transferred 
 * by the command. For example, to read the name space size (NSZE)
 * from data returned by Identify Namespace, bytes 0-7 in the data
 * buffer would need to be byte reversed.
 *
 * The passthru is unsuccessful if the ioctl returns -1 which means
 * the driver failed to send the command to the controller or the 
 * controller did not respond before the timeout expired. If errno 
 * is set to EINVAL, resp.status contains a code indicating which 
 * field is invalid.
 * 
 * The passthru is successful if the ioctl returns 0. resp.status 
 * contains NVMe status and can be non-zero.
 *
 * The NVMe command is successful if the ioctl returns 0 && 
 * resp.status == 0.
 *
 * The passthru command executes in parallel with commands from
 * other initiators such as another user doing read/write via
 * strategy.
 * 
 */
struct nvme_passthru { /* all fields are in host native endian.
                        * Users are not required to zero out the 
                        * reserved padding but doing so is recommended.
                        */
    ushort version;    /* Must be 0 for this struct 
                        * The version must be incremented when new fields 
                        * are added at the end even if the total size of 
                        * the struct does not change.
                        */
    ushort rsvd;
    ushort flags;
#define NVME_PATH_PASSTHRU   0x0001
    ushort path_id;     /* valid on disk devno when
                         * NVME_PATH_PASSTHRU is set in flags
                         */
    union {
        struct {
            uchar  opc;       /* dword_0[07:00] */
            uchar  flag;      /* dword_0[15:08] */
            ushort timeout;   /* desired timeout in secs within which 
                               * the controller must return a response. 
                               * 0 means use default timeout
                               */
            uint   nsid;      /* 0 if the command is not to a namespace.
                               * 0xFFFFFFFF if the command is to all 
                               * namespaces.
                               */
            uint data_length; /* must be 0 if opc does not transfer data */
            char *data;       /* pointer to user buffer
                               * User must byte swap fields in the data.
                               */

            /* command specific dwords (see NVMe specification) */
            uint dword_10;
            uint dword_11;
            uint dword_12;
            uint dword_13;
            uint dword_14;
            uint dword_15;
        } cmd;

        struct {
            uint rsvd[32];
        } cmd_pad;
    };

    union {
        struct {
            ushort status;  /* contains either NVMe status or 
                             * driver error code when errno is EINVAL.
                             * For NVMe status, the phase bit is cleared.
                             */
            ushort rsvd;
            uint   dword_0; /* from CQ in host native endian
                             * This field is command specific.
                             */
        } resp;

        struct {
            uint rsvd[8];
        } resp_pad;
    };

/* driver error code in resp.status when errno is EINVAL */
#define NVME_PASSTHRU_INVAL_DATA_LENGTH   0xFF00
#define NVME_PASSTHRU_BLOCKED_OP_CODE     0xFF01
#define NVME_PASSTHRU_CMD_HAS_NO_DATA     0xFF02
};

#ifdef _KERNEL
struct nvme_passthru32 { 
    ushort version;
    ushort rsvd;
    ushort flags;
    ushort path_id;

    union {
        struct {
            uchar  opc;
            uchar  flag;
            ushort timeout;
            uint   nsid;
            uint   data_length;
            ptr32  data;

            uint dword_10;
            uint dword_11;
            uint dword_12;
            uint dword_13;
            uint dword_14;
            uint dword_15;
        } cmd;

        struct {
            uint rsvd[32];
        } cmd_pad;
    };

    union {
        struct {
            ushort status;
            ushort rsvd;
            uint   dword_0;
        } resp;

        struct {
            uint rsvd[8];
        } resp_pad;
    };
};
#endif /* _KERNEL */

/*
 * NVME_CNTL ioctl structure 
 * Unlike a passthru, the control is request to the driver as 
 * opposed to a device.
 */
struct nvme_cntl {  /*
                     * Users are not required to zero out the 
                     * reserved padding but doing so is recommended.
                     */

    ushort version; /* Must be 0 for this struct 
                     *   
                     * The version must be incremented when new fields 
                     * are added at the end even if the total size of 
                     * the struct does not change.
                     */
    ushort rsvd;
    
    uint action;    /* control action, see defines below.
                     * the cmd/resp fields depends on action 
                     * 0x10000 and above are rsvd for internal use.
                     */

#define NVME_RESET       0x1u /* Request a reset of the type specified
                               * in the cmd and restart the controller.
                               * When the call returns, the controller
                               * has been reset and re-IPLed. The call
                               * blocks until the controller IPL is
                               * complete as long as the controller was
                               * not in the dead state at the time of the
                               * call. If it was in dead state, meaning
                               * in a non-functional state, the ioctl may
                               * return before IPL completes.
                               *
                               * Any association with the controller is
                               * terminated and re-established if the
                               * controller is remote (over fabric) as
                               * long as the controller remains reachable
                               * and healthy.
                               */

#define NVME_QUERY_PCI   0x2u /* Read PCIe parms */

#define NVME_ARESET      0x3u /* Do an async reset of the type specified
                               * in the cmd and restart the controller.
                               * The call returns as soon as the request
                               , has been queued and possibly before or 
                               * during the controller IPL. The controller
                               * can be deemed operational even though it 
                               * may still be on it's way up and commands
                               * can be submitted. However, ioctls may
                               * be failed by the impending IPL and therefore
                               * should be retried at least 3 times in user
                               * code. Note that it is strongly advised to
                               * always retry ioctls regardless of this
                               * particular behavior.
                               *
                               * Any association with the controller is
                               * terminated and re-established if the
                               * controller is remote (over fabric) as
                               * long as the controller remains reachable
                               * and healthy.
                               */

#define NVME_CTLR_OFFLINE     0x1000 /* restricted action */
#define NVME_CTLR_ONLINE      0x1001 /* restricted action */

    union {
        struct {
            ushort    reset_type;
#define NVME_CTLR_RESET         0x0u  /* CC.EN reset */
        } reset; /* used by: NVME_RESET & NVME_ARESET/DRESET actions */

        struct {
            uint      path_addr[2];   /* the path to query
                                         avoid ptr/ulong */
        } query_path;

        struct {
            uint            pad[6];
        } rsvd;
    } cmd;

    union {
        struct {
            uchar    max_link_speed;
            uchar    max_link_width;
            uchar    cur_link_speed;
            uchar    neg_link_width;
        } query_pci; /* used by: NVME_QUERY_PCI action */

        struct {
            uint     num_ops; /* queued, pending or active ops 
                                 in the adapter (all channels) */
        } query_chn; /* used by: NVME_QUERY_CHN action */

        struct {
            uint     num_ops; /* queued, pending or active ops 
                                 in the adapter from a given path */
        } query_path; /* used by: NVME_QUERY_PATH action */

        struct {
            uint     failed:1;  /* 0 - good, 1 - failed */
            uint     rsvd:31;   /* future expansion */
        } query_ctlr; /* used by: NVME_QUERY_CTLR action */

        struct {
            uint pad[6];
        } rsvd;
    } resp;
};


#ifdef _KERNEL
#define NVME_QUERY_CHN        0x10001 /* kernel action */
#define NVME_QUERY_PATH       0x10002 /* kernel action */
#define NVME_QUERY_CTLR       0x10003 /* kernel action */


#define NVME_RESET_WAIT       0x20000 /* internal action */
#define NVME_DRESET           0x20001 /* internal action 
                                         acts like NVME_ARESET if dead, 
                                         else NOP
                                        */

#define nvme_cntl32 nvme_cntl   /* there being no pointers in nvme_cntl */
#endif

#endif /* _H_NVME */