/* aacraid.h
 * Copyright (C) 2014 Raghava Aditya <Raghava.Aditya@pmcs.com>
 * Copyright (C) 2015 Nidhi Malhotra <Nidhi.Malhotra@pmcs.com>
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

// Check windows
#if defined(_WIN32) || defined(_WIN64)
#ifdef _WIN64
  #define ENVIRONMENT64
#else
  #define ENVIRONMENT32
#endif
#endif

// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
  #define ENVIRONMENT64
#else
  #define ENVIRONMENT32
#endif
#endif

#define METHOD_BUFFERED 0
#define METHOD_NEITHER  3

#if defined(_WIN32) || defined(_WIN64)
#define FSAMPCTL_SCSI_BASE          IOCTL_SCSI_BASE
#define ARCIOCTL_SEND_RAW_SRB       CTL_CODE(FSAMPCTL_SCSI_BASE, 2201, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define AACRAID_SAS_SIGNATURE       "ARCSAS"
#define SRB_FLAGS_DATA_IN           0x00000040
#define SRB_FLAGS_DATA_OUT          0x00000080
#define SRB_FLAGS_NO_DATA_TRANSFER  0x00000000
#else
#define CTL_CODE(function, method) ((4<< 16) | ((function) << 2) | (method) )

#define FSACTL_SEND_RAW_SRB  CTL_CODE(2067, METHOD_BUFFERED)
#endif
#define  SRB_FUNCTION_EXECUTE_SCSI 0X00

#define  SRB_DataIn      0x0040
#define  SRB_DataOut     0x0080
#define  SRB_NoDataXfer  0x0000

typedef struct {
  uint32_t lo32;
  uint32_t hi32;
  }  address64;

typedef struct {
  address64 addr64;
  uint32_t length;  /* Length. */
  }  user_sgentry64;

typedef struct {
  uint32_t addr32;
  uint32_t length;
  }  user_sgentry32;

typedef struct {
  uint32_t         count;
  user_sgentry64   sg64[1];
  }  user_sgmap64;

typedef struct {
  uint32_t         count;
  user_sgentry32   sg32[1];
  }  user_sgmap32;

#if defined(_WIN32) || defined(_WIN64)
typedef struct _SCSI_REQUEST_BLOCK {
    USHORT Length;                  // offset 0
    UCHAR Function;                 // offset 2
    UCHAR SrbStatus;                // offset 3
    UCHAR ScsiStatus;               // offset 4
    UCHAR PathId;                   // offset 5
    UCHAR TargetId;                 // offset 6
    UCHAR Lun;                      // offset 7
    UCHAR QueueTag;                 // offset 8
    UCHAR QueueAction;              // offset 9
    UCHAR CdbLength;                // offset a
    UCHAR SenseInfoBufferLength;    // offset b
    ULONG SrbFlags;                 // offset c
    ULONG DataTransferLength;       // offset 10
    ULONG TimeOutValue;             // offset 14
    PVOID DataBuffer;               // offset 18
    PVOID SenseInfoBuffer;          // offset 1c
    struct _SCSI_REQUEST_BLOCK *NextSrb; // offset 20
    PVOID OriginalRequest;          // offset 24
    PVOID SrbExtension;             // offset 28
    union {
        ULONG InternalStatus;       // offset 2c
        ULONG QueueSortKey;         // offset 2c
    };

#if defined(_WIN64)
    //
    // Force PVOID alignment of Cdb
    //
    ULONG Reserved;
#endif

    UCHAR Cdb[16];                  // offset 30
} SCSI_REQUEST_BLOCK, *PSCSI_REQUEST_BLOCK;

#define SCSI_REQUEST_BLOCK_SIZE sizeof(SCSI_REQUEST_BLOCK)

#else
typedef struct {
  uint32_t function;           //SRB_FUNCTION_EXECUTE_SCSI 0x00
  uint32_t channel;            //bus
  uint32_t id;                 //use the ID number this is wrong
  uint32_t lun;                //Logical unit number
  uint32_t timeout;
  uint32_t flags;              //Interesting stuff I must say
  uint32_t count;              // Data xfer size
  uint32_t retry_limit;        // We shall see
  uint32_t cdb_size;           // Length of CDB
  uint8_t  cdb[16];            // The actual cdb command
  user_sgmap64 sg64;           // pDatabuffer and address of Databuffer
  }  user_aac_srb64;

typedef struct {
  uint32_t function;           //SRB_FUNCTION_EXECUTE_SCSI 0x00
  uint32_t channel;            //bus
  uint32_t id;                 //use the ID number this is wrong
  uint32_t lun;                //Logical unit number
  uint32_t timeout;
  uint32_t flags;              //Interesting stuff I must say
  uint32_t count;              // Data xfer size
  uint32_t retry_limit;        // We shall see
  uint32_t cdb_size;           // Length of CDB
  uint8_t  cdb[16];            // The actual cdb command
  user_sgmap32 sg32;           // pDatabuffer and address of Databuffer
  }  user_aac_srb32;

typedef struct {
  uint32_t status;
  uint32_t srb_status;
  uint32_t scsi_status;
  uint32_t data_xfer_length;
  uint32_t sense_data_size;
  uint8_t  sense_data[30];
  }  user_aac_reply;
#endif