Blob Blame History Raw
#ifndef iprlib_h
#define iprlib_h
/**
 * IBM IPR adapter utility library
 *
 * (C) Copyright 2000, 2004
 * International Business Machines Corporation and others.
 * All Rights Reserved. This program and the accompanying
 * materials are made available under the terms of the
 * Common Public License v1.0 which accompanies this distribution.
 *
 */

/*
 * $Header: /cvsroot/iprdd/iprutils/iprlib.h,v 1.107 2009/06/30 23:32:40 wboyer Exp $
 */

#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mount.h>
#include <sys/utsname.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <scsi/scsi.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/file.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <ctype.h>
#include <syslog.h>
#include <term.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <asm/byteorder.h>
#include <sys/mman.h>
#include <paths.h>
#include <linux/netlink.h>
#include <time.h>
#include <limits.h>
#include <zlib.h>
#include <sys/param.h>

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

#define IPR_DASD_UCODE_USRLIB                0
#define IPR_DASD_UCODE_ETC                   1

#define IPR_DASD_UCODE_NOT_FOUND             -1
#define IPR_DASD_UCODE_NO_HDR                1
#define IPR_DASD_UCODE_HDR                   2

#define UCODE_BASE_DIR                       "/usr/lib/microcode"
#define LINUX_UCODE_BASE_DIR                 "/lib/firmware"

#define FIRMWARE_HOTPLUG_DIR_TAG             "FIRMWARE_DIR"
#define FIRMWARE_HOTPLUG_CONFIG_FILE         "/etc/hotplug/firmware.agent"
#define FIRMWARE_HOTPLUG_DEFAULT_DIR         LINUX_UCODE_BASE_DIR

#define IPRDUMP_DIR "/var/log/"

#define IPR_JBOD_BLOCK_SIZE                  512
#define IPR_DEFAULT_AF_BLOCK_SIZE            522
#define IPR_JBOD_4K_BLOCK_SIZE               4096
#define IPR_AF_4K_BLOCK_SIZE                 4224
#define IOCTL_BUFFER_SIZE                    512
#define IPR_MAX_NUM_BUSES                    4
#define IPR_VENDOR_ID_LEN                    8
#define IPR_PROD_ID_LEN                      16
#define IPR_SERIAL_NUM_LEN                   8
#define ESM_SERIAL_NUM_LEN                   12
#define YL_SERIAL_NUM_LEN                    12
#define IPR_DESCRIPTION_LEN                  16
#define IPR_VPD_PLANT_CODE_LEN               4
#define IPR_VPD_CACHE_SIZE_LEN               3
#define IPR_VPD_DRAM_SIZE_LEN                3
#define IPR_VPD_PART_NUM_LEN                 12
#define IPR_CCB_CDB_LEN                      16
#define IPR_QAC_BUFFER_SIZE                  200000
#define IPR_SIS32_QAC_BUFFER_SIZE            16000
#define IPR_INVALID_ARRAY_ID                 0xFF
#define IPR_IOA_RESOURCE_HANDLE              0xffffffff
#define IPR_RECLAIM_NUM_BLOCKS_MULTIPLIER    256
#define IPR_SDB_CHECK_AND_QUIESCE            0x00
#define IPR_SDB_CHECK_ONLY                   0x40
#define IPR_SDB_CHECK_AND_QUIESCE_ENC        0x0e
#define IPR_RDB_UNQUIESCE_AND_REBALANCE      0x20
#define IPR_MAX_NUM_SUPP_INQ_PAGES           36
#define SES_MAX_NUM_SUPP_INQ_PAGES           7
#define IPR_DUMP_TRACE_ENTRY_SIZE            8192
#define IPR_MODE_SENSE_LENGTH                255
#define IPR_DEFECT_LIST_HDR_LEN              4
#define IPR_FORMAT_DATA                      0x10
#define IPR_FORMAT_IMMED                     2
#define IPR_ARRAY_CMD_TIMEOUT                (2 * 60)      /* 2 minutes */
#define IPR_INTERNAL_DEV_TIMEOUT             (2 * 60)      /* 2 minutes */
#define IPR_FORMAT_UNIT_TIMEOUT              (3 * 60 * 60) /* 3 hours */
#define IPR_INTERNAL_TIMEOUT                 (30)          /* 30 seconds */
#define IPR_SUSPEND_DEV_BUS_TIMEOUT          (35)          /* 35 seconds */
#define IPR_EVALUATE_DEVICE_TIMEOUT          (2 * 60)      /* 2 minutes */
#define IPR_WRITE_BUFFER_TIMEOUT             (8 * 60)      /* 8 minutes */
#define IPR_CACHE_RECLAIM_TIMEOUT            (10 * 60)     /* 10 minutes */
#define SET_DASD_TIMEOUTS_TIMEOUT            (2 * 60)
#define IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES    50
#define IPR_DRIVE_ELEM_STATUS_EMPTY          5
#define IPR_DRIVE_ELEM_STATUS_POPULATED      1
#define IPR_DRIVE_ELEM_STATUS_UNSUPP         0
#define IPR_DRIVE_ELEM_STATUS_NO_ACCESS      8
#define IPR_TIMEOUT_SECOND_RADIX             0x0000
#define IPR_TIMEOUT_MINUTE_RADIX             0x4000
#define IPR_TIMEOUT_RADIX_MASK               0xC000
#define IPR_TIMEOUT_RADIX_IS_MINUTE(to) \
        (((to) & IPR_TIMEOUT_RADIX_MASK) == IPR_TIMEOUT_MINUTE_RADIX)
#define IPR_TIMEOUT_RADIX_IS_SECONDS(to) \
        (((to) & IPR_TIMEOUT_RADIX_MASK) == IPR_TIMEOUT_SECOND_RADIX)
#define IPR_TIMEOUT_MASK                     0x3FFF

#define IPR_IOA_DEBUG                        0xDDu
#define   IPR_IOA_DEBUG_READ_IOA_MEM         0x00u
#define   IPR_IOA_DEBUG_WRITE_IOA_MEM        0x01u
#define   IPR_IOA_DEBUG_READ_FLIT            0x03u
#define   IPR_IOA_DEBUG_ENABLE_DBG_FUNC      0x0Au
#define   IPR_IOA_DEBUG_DISABLE_DBG_FUNC     0x0Bu

#define IPR_STD_INQ_Z0_TERM_LEN              8
#define IPR_STD_INQ_Z1_TERM_LEN              12
#define IPR_STD_INQ_Z2_TERM_LEN              4
#define IPR_STD_INQ_Z3_TERM_LEN              5
#define IPR_STD_INQ_Z4_TERM_LEN              4
#define IPR_STD_INQ_Z5_TERM_LEN              2
#define IPR_STD_INQ_Z6_TERM_LEN              10
#define IPR_STD_INQ_PART_NUM_LEN             12
#define IPR_STD_INQ_EC_LEVEL_LEN             10
#define IPR_STD_INQ_FRU_NUM_LEN              12

#define IPR_START_STOP_STOP                  0x00
#define IPR_START_STOP_START                 0x01
#define IPR_READ_CAPACITY_16                 0x10
#define IPR_SERVICE_ACTION_IN                0x9E
#define IPR_MAINTENANCE_IN                   0xA3
#define IPR_QUERY_MULTI_ADAPTER_STATUS       0x01
#define IPR_MAINTENANCE_OUT                  0xA4
#define IPR_CHANGE_MULTI_ADAPTER_ASSIGNMENT  0x02
#define IPR_QUERY_RESOURCE_STATE             0xC2
#define IPR_QUERY_COMMAND_STATUS             0xCB
#define IPR_SUSPEND_DEV_BUS                  0xC8
#define IPR_RESUME_DEV_BUS                   0xC9
#define IPR_IOA_SERVICE_ACTION               0xD2
#define IPR_QUERY_RES_ADDR_ALIASES           0x10
#define IPR_QUERY_RES_PATH_ALIASES           0x20
#define IPR_DISRUPT_DEVICE                   0x11
#define IPR_QUERY_SAS_EXPANDER_INFO          0x12
#define IPR_QUERY_RES_REDUNDANCY_INFO        0x13
#define IPR_QUERY_RES_REDUNDANCY_INFO64      0x23
#define IPR_CHANGE_CACHE_PARAMETERS          0x14
#define IPR_QUERY_CACHE_PARAMETERS           0x16
#define IPR_LIVE_DUMP                        0x31
#define IPR_QUERY_IOA_DEV_PORT               0x32
#define IPR_EVALUATE_DEVICE                  0xE4
#define SKIP_READ                            0xE8
#define SKIP_WRITE                           0xEA
#define QUERY_DASD_TIMEOUTS                  0xEB
#define SET_DASD_TIMEOUTS                    0xEC
#define IPR_MIGRATE_ARRAY_PROTECTION         0xEF
#define IPR_QUERY_ARRAY_CONFIG               0xF0
#define IPR_START_ARRAY_PROTECTION           0xF1
#define IPR_STOP_ARRAY_PROTECTION            0xF2
#define IPR_RESYNC_ARRAY_PROTECTION          0xF3
#define IPR_ADD_ARRAY_DEVICE                 0xF4
#define IPR_REMOVE_ARRAY_DEVICE              0xF5
#define IPR_REBUILD_DEVICE_DATA              0xF6
#define IPR_RECLAIM_CACHE_STORE              0xF8
#define IPR_SET_ARRAY_ASYMMETRIC_ACCESS      0xFA
#define IPR_RECLAIM_ACTION                   0x68
#define IPR_RECLAIM_PERFORM                  0x00
#define IPR_RECLAIM_RESET_BATTERY_ERROR      0x08
#define IPR_RECLAIM_EXTENDED_INFO            0x10
#define IPR_RECLAIM_QUERY                    0x20
#define IPR_RECLAIM_RESET                    0x40
#define IPR_RECLAIM_FORCE_BATTERY_ERROR      0x60
#define IPR_RECLAIM_UNKNOWN_PERM             0x80
#define SET_SUPPORTED_DEVICES                0xFB
#define IPR_STD_INQUIRY                      0xFF
#ifndef REPORT_LUNS
#define REPORT_LUNS                          0xA0
#endif

#define IPR_XLATE_DEV_FMT_RC(rc)	((((rc) & 127) == 51) ? -EIO : 0)
#define IPR_TYPE_AF_DISK                     0xC
#define IPR_TYPE_ADAPTER                     0x1f
#define IPR_TYPE_ARRAY				   0x1f
#define IPR_TYPE_EMPTY_SLOT                  0xff

#define IPR_ACTIVE_OPTIMIZED                 0x0
#define IPR_ACTIVE_NON_OPTIMIZED             0x1
#define IPR_ACTIVE_STANDBY                   0x2
#define IPR_CLEAR_ASYMMETRIC_STATE           0x0
#define IPR_PRESERVE_ASYMMETRIC_STATE        0x80

#define IPR_IOA_CACHING_DUAL_FAILURE_DISABLED  0x0
#define IPR_IOA_CACHING_DUAL_FAILURE_ENABLED   0x1
#define IPR_IOA_REQUESTED_CACHING_DEFAULT    0x0
#define IPR_IOA_REQUESTED_CACHING_DISABLED   0x1

#define IPR_IOA_CACHING_DEFAULT_DUAL_ENABLED   0x2
#define IPR_IOA_CACHING_DISABLED_DUAL_ENABLED  0x3

#define IPR_IOA_VSET_CACHE_ENABLED		0x4

#define IPR_IOA_SET_CACHING_DEFAULT          0x0
#define IPR_IOA_SET_CACHING_DISABLED         0x10
#define IPR_IOA_SET_CACHING_DUAL_DISABLED    0x20
#define IPR_IOA_SET_CACHING_DUAL_ENABLED     0x30
#define IPR_IOA_SET_VSET_CACHE_ENABLED	     0x40
#define IPR_IOA_SET_VSET_CACHE_DISABLED      0x50

#define PHYSICAL_LOCATION_LENGTH	1024

#define IPR_HDD                              0x0
#define IPR_SSD                              0x1
#define IPR_BLK_DEV_CLASS_4K                 0x4
#define IPR_RI				     0x1

#define IPR_ARRAY_VIRTUAL_BUS			0x1
#define IPR_VSET_VIRTUAL_BUS			0x2
#define IPR_IOAFP_VIRTUAL_BUS			0x3

#define IPR_SAS_STD_INQ_UCODE_ID		12
#define IPR_SAS_STD_INQ_VENDOR_UNIQ		40
#define IPR_SAS_STD_INQ_PLANT_MAN		4
#define IPR_SAS_STD_INQ_DATE_MAN		5
#define IPR_SAS_STD_INQ_FRU_COUNT		4
#define IPR_SAS_STD_INQ_FRU_FIELD_LEN		2
#define IPR_SAS_STD_INQ_FRU_PN			12
#define IPR_SAS_STD_INQ_ASM_EC_LVL		10
#define IPR_SAS_STD_INQ_ASM_PART_NUM		12
#define IPR_SAS_STD_INQ_FRU_ASM_EC		10
#define IPR_SAS_INQ_BYTES_WARRANTY_LEN		3

/* Device write cache policies. */
enum {IPR_DEV_CACHE_WRITE_THROUGH = 0, IPR_DEV_CACHE_WRITE_BACK};

/* System P Operating modes */
enum system_p_mode {POWER_VM, POWER_KVM, POWER_BAREMETAL} ;

#define  IPR_IS_DASD_DEVICE(std_inq_data) \
((((std_inq_data).peri_dev_type) == TYPE_DISK) && !((std_inq_data).removeable_medium))

#define IPR_SET_MODE(change_mask, cur_val, new_val)  \
{                                                       \
int mod_bits = (cur_val ^ new_val);                     \
if ((change_mask & mod_bits) == mod_bits)               \
{                                                       \
cur_val = new_val;                                      \
}                                                       \
}

#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
#define IPR_RECORD_ID_SUPPORTED_ARRAYS       __constant_be16_to_cpu((u16)0)
#define IPR_RECORD_ID_COMP_RECORD            __constant_be16_to_cpu((u16)3)
#define IPR_RECORD_ID_ARRAY_RECORD           __constant_be16_to_cpu((u16)4)
#define IPR_RECORD_ID_DEVICE_RECORD          __constant_be16_to_cpu((u16)5)
#define IPR_RECORD_ID_ARRAY_RECORD_3         __constant_be16_to_cpu((u16)6)
#define IPR_RECORD_ID_VSET_RECORD_3          __constant_be16_to_cpu((u16)7)
#define IPR_RECORD_ID_DEVICE_RECORD_3        __constant_be16_to_cpu((u16)8)

extern struct ipr_array_query_data *ipr_array_query_data;
extern int num_ioas;
extern struct ipr_ioa *ipr_ioa_head;
extern struct ipr_ioa *ipr_ioa_tail;
extern int runtime;
extern void (*exit_func) (void);
extern int daemonize;
extern int ipr_debug;
extern int ipr_force;
extern int ipr_sg_required;
extern int polling_mode;
extern int ipr_fast;
extern int format_done;
extern char *tool_name;
extern struct sysfs_dev *head_zdev;
extern struct sysfs_dev *tail_zdev;
extern enum system_p_mode power_cur_mode;
extern int tool_init_retry;

struct sysfs_dev {
	u64 device_id;
	char ioa_pci_addr[16];
	struct sysfs_dev *next, *prev;
};

struct ipr_phy {
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 box:3;
	u8 phy:5;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 phy:5;
	u8 box:3;
#endif
};

struct ipr_phy_2bit_hop {
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 box:2;
	u8 phy:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 phy:6;
	u8 box:2;
#endif
};

struct ipr_res_addr {
	u8 host;
	u8 bus;
	union {
		u8 target;
		struct ipr_phy phy;
		struct ipr_phy_2bit_hop phy_2bit_hop;
	};
	u8 lun;
#define IPR_GET_PHYSICAL_LOCATOR(res_addr) \
	(((res_addr)->bus << 16) | ((res_addr)->target << 8) | (res_addr)->lun)
};

struct ipr_res_path {
	u8 res_path_bytes[8];
};

struct ipr_std_inq_vpids {
	u8 vendor_id[IPR_VENDOR_ID_LEN];          /* Vendor ID */
	u8 product_id[IPR_PROD_ID_LEN];           /* Product ID */
};

struct ipr_common_record {
	u16 record_id;
	u16 record_len;
};

struct ipr_vset_res_state {
	u16 stripe_size;
	u8 prot_level;
	u8 num_devices_in_vset;
	u32 reserved6;
	u32 ilid;
	u32 failing_dev_ioasc;
	struct ipr_res_addr failing_dev_res_addr;
	u32 failing_dev_res_handle;
	u8 prot_level_str[8];
};

struct ipr_dasd_res_state {
	u32 data_path_width;  /* bits */
	u32 data_xfer_rate;   /* 100 KBytes/second */
	u32 ilid;
	u32 failing_dev_ioasc;
	struct ipr_res_addr failing_dev_res_addr;
	u32 failing_dev_res_handle;
};

struct ipr_gscsi_res_state {
	u32 data_path_width;  /* bits */
	u32 data_xfer_rate;   /* 100 KBytes/second */
};

struct ipr_supported_device {
	u16 data_length;
	u8 reserved;
	u8 num_records;
	struct ipr_std_inq_vpids vpids;
	u8 reserved2[16];
};

struct ipr_mode_page_hdr {
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 parms_saveable:1;
	u8 reserved1:1;
	u8 page_code:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 page_code:6;
	u8 reserved1:1;
	u8 parms_saveable:1;
#endif
	u8 page_length;
};

struct ipr_vendor_mode_page {
	/* Mode page 0x00 */
	struct ipr_mode_page_hdr hdr;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 qpe:1;
	u8 uqe:1;
	u8 dwd:1;
	u8 reserved1:4;
	u8 arhes:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 arhes:1;
	u8 reserved1:4;
	u8 dwd:1;
	u8 uqe:1;
	u8 qpe:1;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 asdpe:1;
	u8 reserved2:1;
	u8 cmdac:1;
	u8 rpfae:1;
	u8 dotf:1;
	u8 reserved3:1;
	u8 rrnde:1;
	u8 cpe:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 cpe:1;
	u8 rrnde:1;
	u8 reserved3:1;
	u8 dotf:1;
	u8 rpfae:1;
	u8 cmdac:1;
	u8 reserved2:1;
	u8 asdpe:1;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved4:6;
	u8 dwlro:1;
	u8 dlro:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 dlro:1;
	u8 dwlro:1;
	u8 reserved4:6;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved5:2;
	u8 dsn:1;
	u8 frdd:1;
	u8 dpsdp:1;
	u8 wpen:1;
	u8 caen:1;
	u8 ovple:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 ovple:1;
	u8 caen:1;
	u8 wpen:1;
	u8 dpsdp:1;
	u8 frdd:1;
	u8 dsn:1;
	u8 reserved5:2;
#endif

	u8 reserved7[2];

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved8:1;
	u8 adc:1;
	u8 qemc:1;
	u8 drd:1;
	u8 led_mode:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 led_mode:4;
	u8 drd:1;
	u8 qemc:1;
	u8 adc:1;
	u8 reserved8:1;
#endif

	u8 temp_threshold;
	u8 cmd_aging_limit_hi;
	u8 cmd_aging_limit_lo;
	u8 qpe_read_threshold;
	u8 reserved10;

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 drrt:1;
	u8 dnr:1;
	u8 reserved11:1;
	u8 rarr:1;
	u8 ffmt:1;
	u8 reserved12:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved12:3;
	u8 ffmt:1;
	u8 rarr:1;
	u8 reserved11:1;
	u8 dnr:1;
	u8 drrt:1;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 rtp:1;
	u8 rrc:1;
	u8 fcert:1;
	u8 reserved13:1;
	u8 drpdv:1;
	u8 dsf:1;
	u8 irt:1;
	u8 ivr:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 ivr:1;
	u8 irt:1;
	u8 dsf:1;
	u8 drpdv:1;
	u8 reserved13:1;
	u8 fcert:1;
	u8 rrc:1;
	u8 rtp:1;
#endif
};

struct ipr_caching_parameters_page {
	/* Mode page 0x08 */
	struct ipr_mode_page_hdr hdr;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 ic:1;
	u8 abpf:1;
	u8 cap:1;
	u8 disc:1;
	u8 size:1;
	u8 wce:1;
	u8 mf:1;
	u8 rcd:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 rcd:1;
	u8 mf:1;
	u8 wce:1;
	u8 size:1;
	u8 disc:1;
	u8 cap:1;
	u8 abpf:1;
	u8 ic:1;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 demand_read_retention_priority:4;
	u8 write_retention_priority:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 write_retention_priority:4;
	u8 demand_read_retention_priority:4;
#endif

	u16 disable_prefetch_transfer_length;
	u16 minimum_prefetch;
	u16 maximum_prefetch;
	u16 maximum_prefetch_ceiling;

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 fsw:1;
	u8 lbcss:1;
	u8 dra:1;
	u8 reserved:5;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved:5;
	u8 dra:1;
	u8 lbcss:1;
	u8 fsw:1;
#endif

	u8 cache_segments;
	u16 cache_segment_size;
	u8 reserved1;
	u8 non_cache_segment_size[3];
};

struct ipr_control_mode_page {
	/* Mode page 0x0A */
	struct ipr_mode_page_hdr hdr;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 tst:3;
	u8 reserved1:3;
	u8 gltsd:1;
	u8 rlec:1;
	u8 queue_algorithm_modifier:4;
	u8 reserved2:1;
	u8 qerr:2;
	u8 dque:1;
	u8 reserved3:1;
	u8 rac:1;
	u8 reserved4:2;
	u8 swp:1;
	u8 raerp:1;
	u8 uaaerp:1;
	u8 eaerp:1;
	u8 ato:1;
	u8 tas:1;
	u8 reserved5:3;
	u8 autoload_mode:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 rlec:1;
	u8 gltsd:1;
	u8 reserved1:3;
	u8 tst:3;
	u8 dque:1;
	u8 qerr:2;
	u8 reserved2:1;
	u8 queue_algorithm_modifier:4;
	u8 eaerp:1;
	u8 uaaerp:1;
	u8 raerp:1;
	u8 swp:1;
	u8 reserved4:2;
	u8 rac:1;
	u8 reserved3:1;
	u8 autoload_mode:3;
	u8 reserved5:3;
	u8 tas:1;
	u8 ato:1;
#endif
	u16 ready_aen_holdoff_period;
	u16 busy_timeout_period;
	u16 reserved6;
};

struct ipr_rw_err_mode_page {
	/* Page code 0x01 */
	struct ipr_mode_page_hdr hdr;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 awre:1;
	u8 arre:1;
	u8 tb:1;
	u8 rc:1;
	u8 eer:1;
	u8 per:1;
	u8 dte:1;
	u8 dcr:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 dcr:1;
	u8 dte:1;
	u8 per:1;
	u8 eer:1;
	u8 rc:1;
	u8 tb:1;
	u8 arre:1;
	u8 awre:1;
#endif
	u8 read_retry_count;
	u8 correction_span;
	u8 head_offset_count;
	u8 data_strobe_offset_count;
	u8 reserved1;
	u8 write_retry_count;
	u8 reserved2;
	u16 recovery_time_limit;
};

struct ipr_reclaim_query_data {
	u8 action_status;
#define IPR_ACTION_SUCCESSFUL               0
#define IPR_ACTION_NOT_REQUIRED             1
#define IPR_ACTION_NOT_PERFORMED            2

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reclaim_known_needed:1;
	u8 reclaim_unknown_needed:1;
	u8 reserved2:2;
	u8 reclaim_known_performed:1;
	u8 reclaim_unknown_performed:1;
	u8 reserved3:1;
	u8 num_blocks_needs_multiplier:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 num_blocks_needs_multiplier:1;
	u8 reserved3:1;
	u8 reclaim_unknown_performed:1;
	u8 reclaim_known_performed:1;
	u8 reserved2:2;
	u8 reclaim_unknown_needed:1;
	u8 reclaim_known_needed:1;
#endif
	u16 num_blocks;

	u8 rechargeable_battery_type;
#define IPR_BATTERY_TYPE_NO_BATTERY          0
#define IPR_BATTERY_TYPE_NICD                1
#define IPR_BATTERY_TYPE_NIMH                2
#define IPR_BATTERY_TYPE_LIION               3

	u8 rechargeable_battery_error_state;
#define IPR_BATTERY_NO_ERROR_STATE           0
#define IPR_BATTERY_WARNING_STATE            1
#define IPR_BATTERY_ERROR_STATE              2

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 conc_maint_battery:1;
	u8 battery_replace_allowed:1;
	u8 reserved4:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved4:6;
	u8 battery_replace_allowed:1;
	u8 conc_maint_battery:1;
#endif

	u8 reserved5;

	u16 raw_power_on_time;
	u16 adjusted_power_on_time;
	u16 estimated_time_to_battery_warning;
	u16 estimated_time_to_battery_failure;

	u8 reserved6[240];
};

struct ipr_sdt_entry {
	u32 bar_str_offset;
	u32 end_offset;
	u8  entry_byte;
	u8  reserved[3];
#if defined (__BIG_ENDIAN_BITFIELD)
	u8  endian:1;
	u8  reserved1:1;
	u8  valid_entry:1;
	u8  reserved2:5;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8  reserved2:5;
	u8  valid_entry:1;
	u8  reserved1:1;
	u8  endian:1;
#endif
	u8  resv;
	u16 priority;
};

struct ipr_query_res_state {
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved1:1;
	u8 not_oper:1;
	u8 not_ready:1;
	u8 not_func:1;
	u8 reserved2:4;

	u8 read_write_prot:1;
	u8 reserved3:7;

	u8 prot_dev_failed:1;
	u8 prot_suspended:1;
	u8 prot_resuming:1;
	u8 degraded_oper:1;
	u8 service_req:1;
	u8 reserved4:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved2:4;
	u8 not_func:1;
	u8 not_ready:1;
	u8 not_oper:1;
	u8 reserved1:1;

	u8 reserved3:7;
	u8 read_write_prot:1;

	u8 reserved4:3;
	u8 service_req:1;
	u8 degraded_oper:1;
	u8 prot_resuming:1;
	u8 prot_suspended:1;
	u8 prot_dev_failed:1;
#endif
	u8 reserved5;

	union {
		struct ipr_vset_res_state vset;
		struct ipr_dasd_res_state dasd;
		struct ipr_gscsi_res_state gscsi;
	};
};

struct ipr_query_io_port {
	u32 length;
#define IOA_DEV_PORT_ACTIVE	0x0
#define IOA_DEV_PORT_SUSPEND	0x1
#define IOA_DEV_PORT_PARTIAL_SUSPEND	0x2
#define IOA_DEV_PORT_UNKNOWN	0xFF
	u8 port_state;
	u8 reserved1;
	u8 reserved2;
	u8 reserved3;
};

struct ipr_res_addr_aliases {
	u32 length;
	struct ipr_res_addr res_addr[10];
};

#define for_each_ra_alias(ra, aliases) \
          for (ra = (aliases)->res_addr; \
               ra < ((aliases)->res_addr + (ntohl((aliases)->length) / sizeof(struct ipr_res_addr))) && \
               ra < ((aliases)->res_addr + ARRAY_SIZE((aliases)->res_addr)); \
               ra++)

struct ipr_res_path_aliases {
	u32 length;
	u32 reserved1;
	struct ipr_res_path res_path[10];
};

#define for_each_rp_alias(rp, aliases) \
          for (rp = (aliases)->res_path; \
               rp < ((aliases)->res_path + ((ntohl((aliases)->length)- 4) / sizeof(struct ipr_res_path))) && \
               rp < ((aliases)->res_path + ARRAY_SIZE((aliases)->res_path)); \
               rp++)

struct ipr_array_cap_entry {
	u8   prot_level;
#define IPR_DEFAULT_RAID_LVL "5"

#if defined (__BIG_ENDIAN_BITFIELD)
	u8   include_allowed:1;
	u8   reserved:5;
	u8   format_overlay_type:2;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8   format_overlay_type:2;
	u8   reserved:5;
	u8   include_allowed:1;
#endif
#define IPR_FORMAT_ADD_DEVICES 1
#define IPR_FORMAT_REMOVE_DEVICES 2

	u16  reserved2;
	u8   reserved3;
	u8   max_num_array_devices;
	u8   min_num_array_devices;
	u8   min_mult_array_devices;
	u8   min_num_per_tier;
	u8   reserved4;
	u16  supported_stripe_sizes;
	u16  reserved5;
	u16  recommended_stripe_size;
	u8   prot_level_str[8];
};

#define for_each_cap_entry(cap, supp) \
        for (cap = (supp)->entry; \
             (unsigned long)cap < ((unsigned long)((supp)->entry) + (ntohs((supp)->num_entries) * ntohs((supp)->entry_length))); \
             cap = (struct ipr_array_cap_entry *)((unsigned long)cap + ntohs((supp)->entry_length)))

struct ipr_array_record {
	struct ipr_common_record common;

#if defined (__BIG_ENDIAN_BITFIELD)
	u8  issue_cmd:1;
	u8  known_zeroed:1;
	u8  reserved1:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8  reserved1:6;
	u8  known_zeroed:1;
	u8  issue_cmd:1;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8  saved_asym_access_state:4;
	u8  current_asym_access_state:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8  current_asym_access_state:4;
	u8  saved_asym_access_state:4;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8  established:1;
	u8  exposed:1;
	u8  non_func:1;
	u8  high_avail:1;
	u8  no_config_entry:1;
	u8  reserved3:3;

	u8  start_cand:1;
	u8  stop_cand:1;
	u8  resync_cand:1;
	u8  migrate_cand:1;
	u8  asym_access_cand:1;
	u8  reserved4:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8  reserved3:3;
	u8  no_config_entry:1;
	u8  high_avail:1;
	u8  non_func:1;
	u8  exposed:1;
	u8  established:1;

	u8  reserved4:3;
	u8  asym_access_cand:1;
	u8  migrate_cand:1;
	u8  resync_cand:1;
	u8  stop_cand:1;
	u8  start_cand:1;
#endif
	union {
		struct {
			u16 stripe_size;

			u8  raid_level;
			u8  array_id;
			u32 resource_handle;
			struct ipr_res_addr resource_addr;
			struct ipr_res_addr last_resource_addr;
			u8  vendor_id[IPR_VENDOR_ID_LEN];
			u8  product_id[IPR_PROD_ID_LEN];
			u8  serial_number[8];
#if defined (__BIG_ENDIAN_BITFIELD)
			u8  block_dev_class:3;
			u8  reserved51:1;
			u8  read_intensive:1;
			u8  reserved5:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
			u8  reserved5:3;
			u8  read_intensive:1;
			u8  reserved51:1;
			u8  block_dev_class:3;
#endif
			u8  reserved6;
			u8  reserved7;
			u8  reserved8;
		}__attribute__((packed, aligned (4))) type2;

		struct {
			u8  reserved5;
			u8  raid_level;
			u16 stripe_size;
			u8  reserved6[4];
			u8  reserved7[16];

			u8  last_func_res_path[8];

			u8  reserved8[2];

			u8  array_id;
#if defined (__BIG_ENDIAN_BITFIELD)
			u8  block_dev_class:3;
			u8  reserved91:1;
			u8  read_intensive:1;
			u8  reserved9:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
			u8  reserved9:3;
			u8  read_intensive:1;
			u8  reserved91:1;
			u8  block_dev_class:3;
#endif
			u32 resource_handle;
			u8  dev_id[8];
			u8  lun[8];
			u8  wwn[16];
			u8  res_path[8];
			u8  vendor_id[IPR_VENDOR_ID_LEN];
			u8  product_id[IPR_PROD_ID_LEN];
			u8  serial_number[IPR_SERIAL_NUM_LEN];
			u8  desc[IPR_DESCRIPTION_LEN];

			u8  total_arr_size[8];
			u8  total_size_inuse[8];
			u8  max_size_to_use[8];
			u8  total_size_enc[8];
			u8  total_inuse_enc[8];
			u8  max_size_enc[8];
		}__attribute__((packed, aligned (4))) type3;
	};
}__attribute__((packed, aligned (4)));

struct ipr_dev_record {
	struct ipr_common_record common;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8  issue_cmd:1;
	u8  known_zeroed:1;
	u8  reserved:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8  reserved:6;
	u8  known_zeroed:1;
	u8  issue_cmd:1;
#endif
#if defined (__BIG_ENDIAN_BITFIELD)
	u8  saved_asym_access_state:4;
	u8  current_asym_access_state:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8  current_asym_access_state:4;
	u8  saved_asym_access_state:4;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8  array_member:1;
	u8  has_parity:1;
	u8  is_exposed_device:1;
	u8  is_hot_spare:1;
	u8  no_cfgte_vol:1;
	u8  no_cfgte_dev:1;
	u8  reserved2:2;

	u8  start_cand:1;
	u8  parity_cand:1;
	u8  stop_cand:1;
	u8  resync_cand:1;
	u8  include_cand:1;
	u8  exclude_cand:1;
	u8  rebuild_cand:1;
	u8  zero_cand:1;

	u8  add_hot_spare_cand:1;
	u8  rmv_hot_spare_cand:1;
	u8  migrate_array_prot_cand:1;
	u8  reserved3:5;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8  reserved2:2;
	u8  no_cfgte_dev:1;
	u8  no_cfgte_vol:1;
	u8  is_hot_spare:1;
	u8  is_exposed_device:1;
	u8  has_parity:1;
	u8  array_member:1;

	u8  zero_cand:1;
	u8  rebuild_cand:1;
	u8  exclude_cand:1;
	u8  include_cand:1;
	u8  resync_cand:1;
	u8  stop_cand:1;
	u8  parity_cand:1;
	u8  start_cand:1;

	u8  reserved3:5;
	u8  migrate_array_prot_cand:1;
	u8  rmv_hot_spare_cand:1;
	u8  add_hot_spare_cand:1;
#endif
	union {
		struct {
			u8  reserved4[2];
			u8  array_id;
			u32 resource_handle;
			struct ipr_res_addr resource_addr;
			struct ipr_res_addr last_resource_addr;

			u8  vendor_id[IPR_VENDOR_ID_LEN];
			u8  product_id[IPR_PROD_ID_LEN];
			u8  serial_number[IPR_SERIAL_NUM_LEN];

#if defined (__BIG_ENDIAN_BITFIELD)
			u8  block_dev_class:3;
			u8  reserved51:1;
			u8  read_intensive:1;
			u8  reserved5:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
			u8  reserved5:3;
			u8  read_intensive:1;
			u8  reserved51:1;
			u8  block_dev_class:3;
#endif
			u8  reserved6;
			u8  reserved7;
			u8  reserved8;
		}__attribute__((packed, aligned (4))) type2;
		struct {
			u8  reserved4[3];
			u8  reserved5[4];
			u8  reserved6[16];
			u8  last_func_res_path[8];
			u8  reserved7[2];
			u8  array_id;

#if defined (__BIG_ENDIAN_BITFIELD)
			u8  block_dev_class:3;
			u8  reserved81:1;
			u8  read_intensive:1;
			u8  reserved8:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
			u8  reserved8:3;
			u8  read_intensive:1;
			u8  reserved81:1;
			u8  block_dev_class:3;
#endif
			u32 resource_handle;
			u8  dev_id[8];
			u8  lun[8];
			u8  wwn[16];
			u8  res_path[8];
			u8  vendor_id[IPR_VENDOR_ID_LEN];
			u8  product_id[IPR_PROD_ID_LEN];
			u8  serial_number[IPR_SERIAL_NUM_LEN];
			u8  desc[IPR_DESCRIPTION_LEN];
			u8  reserved9[8];
			u8  reserved10[2];
			u8  reserved11[6];
			u8  reserved12[8];
		}__attribute__((packed, aligned (4))) type3;
	};
}__attribute__((packed, aligned (4)));

#define __for_each_qac_entry(rcd, qac, type) \
      if ((qac)->num_records) \
          for (rcd = (type *)(qac)->data; \
               ((unsigned long)rcd) < ((unsigned long)((qac)->u.buf + (qac)->resp_len)) && \
               ((unsigned long)rcd) < ((unsigned long)((qac)->u.buf + IPR_QAC_BUFFER_SIZE)); \
               rcd = (type *)((unsigned long)rcd + ntohs(((struct ipr_common_record *)rcd)->record_len)))

#define for_each_supported_arrays_rcd(rcd, qac) \
      __for_each_qac_entry(rcd, qac, struct ipr_supported_arrays) \
              if (rcd->common.record_id == IPR_RECORD_ID_SUPPORTED_ARRAYS)

#define for_each_qac_entry(rcd, qac) \
      __for_each_qac_entry(rcd, qac, struct ipr_common_record)

#define for_each_dev_rcd(rcd, qac) \
      __for_each_qac_entry(rcd, qac, struct ipr_dev_record) \
              if (ipr_is_device_record(rcd->common.record_id))

#define for_each_array_rcd(rcd, qac) \
      __for_each_qac_entry(rcd, qac, struct ipr_array_record) \
              if (ipr_is_array_record(rcd->common.record_id))

struct ipr_std_inq_data {
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 peri_qual:3;
	u8 peri_dev_type:5;

	u8 removeable_medium:1;
	u8 reserved1:7;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 peri_dev_type:5;
	u8 peri_qual:3;

	u8 reserved1:7;
	u8 removeable_medium:1;
#endif

	u8 version;

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 aen:1;
	u8 obsolete1:1;
	u8 norm_aca:1;
	u8 hi_sup:1;
	u8 resp_data_fmt:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 resp_data_fmt:4;
	u8 hi_sup:1;
	u8 norm_aca:1;
	u8 obsolete1:1;
	u8 aen:1;
#endif

	u8 additional_len;

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 sccs:1;
	u8 reserved2:7;

	u8 bque:1;
	u8 enc_serv:1;
	u8 vs:1;
	u8 multi_port:1;
	u8 mchngr:1;
	u8 obsolete2:2;
	u8 addr16:1;

	u8 rel_adr:1;
	u8 obsolete3:1;
	u8 wbus16:1;
	u8 sync:1;
	u8 linked:1;
	u8 trans_dis:1;
	u8 cmd_que:1;
	u8 vs2:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved2:7;
	u8 sccs:1;

	u8 addr16:1;
	u8 obsolete2:2;
	u8 mchngr:1;
	u8 multi_port:1;
	u8 vs:1;
	u8 enc_serv:1;
	u8 bque:1;

	u8 vs2:1;
	u8 cmd_que:1;
	u8 trans_dis:1;
	u8 linked:1;
	u8 sync:1;
	u8 wbus16:1;
	u8 obsolete3:1;
	u8 rel_adr:1;
#endif
	struct ipr_std_inq_vpids vpids;
	u8 ros_rsvd_ram_rsvd[4];
	u8 serial_num[IPR_SERIAL_NUM_LEN];
};

struct ipr_std_inq_data_long {
	struct ipr_std_inq_data std_inq_data;
	u8 z1_term[IPR_STD_INQ_Z1_TERM_LEN];
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved:4;
	u8 clocking:2;
	u8 qas:1;
	u8 ius:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 ius:1;
	u8 qas:1;
	u8 clocking:2;
	u8 reserved:4;
#endif
	u8 reserved1[41];
	u8 z2_term[IPR_STD_INQ_Z2_TERM_LEN];
	u8 z3_term[IPR_STD_INQ_Z3_TERM_LEN];
	u8 as400_service_level;
	u8 z4_term[IPR_STD_INQ_Z4_TERM_LEN];
	u8 z5_term[IPR_STD_INQ_Z5_TERM_LEN];
	u8 fru_number[IPR_STD_INQ_FRU_NUM_LEN];
	u8 ec_level[IPR_STD_INQ_EC_LEVEL_LEN];
	u8 part_number[IPR_STD_INQ_PART_NUM_LEN];
	u8 z6_term[IPR_STD_INQ_Z6_TERM_LEN];
};

struct ipr_sas_std_inq_data {
	struct ipr_std_inq_data std_inq_data;
	u8 microcode_id[IPR_SAS_STD_INQ_UCODE_ID];
	u8 reserved1;
	u8 vendor_unique[IPR_SAS_STD_INQ_VENDOR_UNIQ];

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved2:5;
	u8 is_ssd:1;
	u8 near_line:1;
	u8 unlock:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 unlock:1;
	u8 near_line:1;
	u8 is_ssd:1;
	u8 reserved2:5;
#endif

	u8 plant_manufacture[IPR_SAS_STD_INQ_PLANT_MAN];
	u8 date_manufacture[IPR_SAS_STD_INQ_DATE_MAN];
	u8 vendor_unique_pn;
	u8 fru_count[IPR_SAS_STD_INQ_FRU_COUNT];
	u8 fru_field_len[IPR_SAS_STD_INQ_FRU_FIELD_LEN];
	u8 fru_pn[IPR_SAS_STD_INQ_FRU_PN];
	u8 asm_ec_level[IPR_SAS_STD_INQ_ASM_EC_LVL];
	u8 asm_part_num[IPR_SAS_STD_INQ_ASM_PART_NUM];
	u8 fru_asm_ec[IPR_SAS_STD_INQ_FRU_ASM_EC];
	u8 reserved3[6];
};

struct ipr_mode_page_28_scsi_dev_bus_attr {
	struct ipr_res_addr res_addr;

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 qas_capability:2;
	u8 enable_target_mode:1;
	u8 term_power_absent:1;
	u8 target_mode_supported:1;
	u8 lvd_to_se_transition_not_allowed:1;
	u8 reserved2:2;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved2:2;
	u8 lvd_to_se_transition_not_allowed:1;
	u8 target_mode_supported:1;
	u8 term_power_absent:1;
	u8 enable_target_mode:1;
	u8 qas_capability:2;
#endif
#define IPR_MODEPAGE28_QAS_CAPABILITY_NO_CHANGE      0  
#define IPR_MODEPAGE28_QAS_CAPABILITY_DISABLE_ALL    1        
#define IPR_MODEPAGE28_QAS_CAPABILITY_ENABLE_ALL     2
	/* NOTE:   Due to current operation conditions QAS should
	 never be enabled so the change mask will be set to 0 */
#define IPR_MODEPAGE28_QAS_CAPABILITY_CHANGE_MASK    0

	u8 scsi_id;
#define IPR_MODEPAGE28_SCSI_ID_NO_CHANGE             0x80u
#define IPR_MODEPAGE28_SCSI_ID_NO_ID                 0xFFu

	u8 bus_width;
#define IPR_MODEPAGE28_BUS_WIDTH_NO_CHANGE           0

	u8 extended_reset_delay;
#define IPR_EXTENDED_RESET_DELAY                     7

	u32 max_xfer_rate;
#define IPR_MODEPAGE28_MAX_XFR_RATE_NO_CHANGE        0

	u8  min_time_delay;
#define IPR_DEFAULT_SPINUP_DELAY                     0xFFu
#define IPR_INIT_SPINUP_DELAY                        5
	u8  reserved3;
	u16 reserved4;
};

#define IPR_BUS_XFER_RATE_TO_THRUPUT(rate, width) \
        (((rate) * ((width) / 8)) / 10)
#define IPR_BUS_THRUPUT_TO_XFER_RATE(thruput, width) \
        (((thruput) * 10) / ((width) / 8))

#define IPR_CONFIG_DIR "/etc/ipr/"

#define IPR_CATEGORY_IOA "Adapter"
#define IPR_GSCSI_HA_ONLY "JBOD_ONLY_HA"
#define IPR_DUAL_ADAPTER_ACTIVE_ACTIVE "DUAL_ADAPTER_ACTIVE_ACTIVE"
#define IPR_ARRAY_REBUILD_RATE "ARRAY_REBUILD_RATE"
#define IPR_ARRAY_DISABLE_REBUILD_VERIFY "DISABLE_ARRAY_REBUILD_VERIFY"

#define IPR_CATEGORY_BUS "Bus"
#define IPR_QAS_CAPABILITY "QAS_CAPABILITY"
#define IPR_HOST_SCSI_ID "HOST_SCSI_ID"
#define IPR_BUS_WIDTH "BUS_WIDTH"
#define IPR_MAX_XFER_RATE_STR "MAX_BUS_SPEED"
#define IPR_MIN_TIME_DELAY "MIN_TIME_DELAY"

/* Disk is the old format which is only here for backwards compatibility */
#define IPR_CATEGORY_DISK "Disk"
/* Device is the new format which should be used for all new attributes */
#define IPR_CATEGORY_DEVICE "Device"
#define IPR_QUEUE_DEPTH "QUEUE_DEPTH"
#define IPR_TCQ_ENABLED "TCQ_ENABLED"
#define IPR_FORMAT_TIMEOUT "FORMAT_UNIT_TIMEOUT"
#define IPR_WRITE_CACHE_POLICY "WRITE_CACHE_POLICY"

#define IPR_MAX_XFER_RATE 320
#define IPR_SAFE_XFER_RATE 160

#define IPR_JBOD_SYSFS_UNBIND 0
#define IPR_JBOD_SYSFS_BIND   1

/* Internal return codes */
#define RC_SUCCESS          0
#define RC_FAILED          -1
#define RC_NOOP		   -2
#define RC_NOT_PERFORMED   -3
#define RC_IN_USE          -4
#define RC_CANCEL          12
#define RC_REFRESH          1
#define RC_EXIT             3

struct scsi_dev_data {
	int host;
	int channel;
	union {
		u8 id;
		struct ipr_phy phy;
		struct ipr_phy_2bit_hop phy_2bit_hop;
	};
	int lun;
	int type;
	int opens;
	int qdepth;
	int busy;
	int online;
	u32 handle;
	char vendor_id[IPR_VENDOR_ID_LEN + 1];
	char product_id[IPR_PROD_ID_LEN + 1];
	char sysfs_device_name[PATH_MAX];
	char dev_name[64];
	char gen_name[64];
#define IPR_MAX_RES_PATH_LEN		24
	char res_path[IPR_MAX_RES_PATH_LEN];
	u64 device_id;
};

struct ipr_path_entry {
	u8 state;
#define IPR_PATH_FUNCTIONAL		0
#define IPR_PATH_NOT_FUNCTIONAL		1
	u8 local_bus_num;
	u8 remote_bus_num;
	u8 reserved;
	u8 local_connection_id[8];
	u8 remote_connection_id[8];
};

struct ipr_path_entries {
	u32 num_path_entries;
	struct ipr_path_entry path[0]; /* variable length */
};

struct ipr_dual_ioa_entry {
	u32 length;
	u8 link_state;
#define IPR_IOA_LINK_STATE_NOT_OPER	0
#define IPR_IOA_LINK_STATE_OPER		1
	u8 cur_state;
#define IPR_IOA_STATE_NO_CHANGE 	0
#define IPR_IOA_STATE_PRIMARY		2
#define IPR_IOA_STATE_SECONDARY		3
#define IPR_IOA_STATE_NO_PREFERENCE	4
	u8 fmt;
	u8 multi_adapter_type;
#define IPR_IOA_MA_TYPE_UNDEFINED	0
#define IPR_IOA_MA_TYPE_DUAL_IOA	1
#define IPR_IOA_MA_TYPE_AUX_CACHE	2
	u8 reserved[2];
	u16 add_len;
	union {
		struct {
			u8 remote_vendor_id[IPR_VENDOR_ID_LEN];
			u8 remote_prod_id[IPR_PROD_ID_LEN];
			u8 remote_sn[IPR_SERIAL_NUM_LEN];
		} fmt0;

		struct {
			u8 remote_vendor_id[IPR_VENDOR_ID_LEN];
			u8 remote_prod_id[IPR_PROD_ID_LEN];
			u8 remote_sn[IPR_SERIAL_NUM_LEN];
			u8 wwid[8];
		} fmt1;
	};
};

struct ipr_phys_bus_entry {
	u8 bus_num;
	u8 reserved[3];
	u8 conn_id[8];
};

struct ipr_ioa_cap_entry {
	u32 length;
	u8 reserved;
	u8 preferred_role;
	u8 token;
	u8 reserved2[4];
	u8 num_bus_entries;
	struct ipr_phys_bus_entry bus[0];
};

struct ipr_multi_ioa_status {
	u32 length;
	u32 num_entries;
	struct ipr_ioa_cap_entry cap;
	u8 buf[16 * 1024];
/*
 *	struct ipr_dual_ioa_entry ioa[0];
 */
};

struct ipr_disk_attr {
	int queue_depth;
	int tcq_enabled;
	int format_timeout;
	int write_cache_policy;
};

struct ipr_vset_attr {
	int queue_depth;
};

struct ipr_ioa_attr {
	int preferred_primary;
	int gscsi_only_ha;
	int active_active;
	int caching;
	int rebuild_rate;
	int disable_rebuild_verify;
	int vset_write_cache;
};

#define IPR_DEV_MAX_PATHS	2
struct ipr_dev {
	char dev_name[64];
	char gen_name[64];
	char prot_level_str[8];
	u8  *vendor_id;
	u8  *product_id;
	u8  *serial_number;
	u8  array_id;
	u8  raid_level;
	u16 stripe_size;
	u32 resource_handle;
	u8  block_dev_class;
	u8  read_intensive;
	u32 is_reclaim_cand:1;
	u32 should_init:1;
	u32 init_not_allowed:1;
	u32 local_flag:1;
	u32 rescan:1;
	u8 active_suspend;
	u32 is_suspend_cand:1;
	u32 is_resume_cand:1;
	u8 supports_4k:1;
	u8 supports_5xx:1;
	u8 read_c7:1;
	u8 locked:1;
	int lock_fd;
	u32 format_timeout;
	struct scsi_dev_data *scsi_dev_data;
	struct ipr_dev *ses[IPR_DEV_MAX_PATHS];
	struct ipr_res_addr res_addr[IPR_DEV_MAX_PATHS];
	struct ipr_res_path res_path[IPR_DEV_MAX_PATHS];
	char res_path_name[IPR_MAX_RES_PATH_LEN];
	struct ipr_disk_attr attr;
	char physical_location[PHYSICAL_LOCATION_LENGTH];
	union {
		struct ipr_common_record *qac_entry;
		struct ipr_dev_record *dev_rcd;
		struct ipr_array_record *array_rcd;
	};
	struct ipr_dev *alt_path;
	struct ipr_ioa *ioa;
};

#define for_each_ra(ra, dev) \
           for(ra = (dev)->res_addr; \
                (ra - ((dev)->res_addr)) < IPR_DEV_MAX_PATHS; ra++)

#define for_each_rp(rp, dev) \
           for(rp = (dev)->res_path; \
                (rp - ((dev)->res_path)) < IPR_DEV_MAX_PATHS; rp++)

enum ipr_tcq_mode {
	IPR_TCQ_DISABLE = 0,
	IPR_TCQ_FROZEN = 1,
	IPR_TCQ_NACA = 2
};

#define IPR_MAX_IOA_DEVICES        (IPR_MAX_NUM_BUSES * 45 * 2 + 1)
struct ipr_ioa {
	struct ipr_dev ioa;
	u16 ccin;
	u16 af_block_size;
	u32 host_addr;
	u32 num_raid_cmds;
	u32 msl;
	u16 num_devices;
	u8 ioa_dead:1;
	u8 nr_ioa_microcode:1;
	u8 scsi_id_changeable:1;
	u8 dual_raid_support:1;
	u8 is_secondary:1;
	u8 should_init:1;
	u8 is_aux_cache:1;
	u8 protect_last_bus:1;
	u8 gscsi_only_ha:1;
	u8 in_gscsi_only_ha:1;
	u8 asymmetric_access:1;
	u8 asymmetric_access_enabled:1;
	u8 has_cache:1;
	u8 sis64:1;
	u8 rebuild_rate:4;
	u8 disable_rebuild_verify:1;
	u8 configure_rebuild_verify:1;
	u8 has_vset_write_cache:1;
	u8 vset_write_cache:1;

#define IPR_SIS32		0x00
#define IPR_SIS64		0x01
	u8 support_4k:1;
	int can_queue;
	enum ipr_tcq_mode tcq_mode;
	u16 pci_vendor;
	u16 pci_device;
	u16 subsystem_vendor;
	u16 subsystem_device;
	u16 hop_count;
#define IPR_NOHOP            0x00
#define IPR_2BIT_HOP         0x01
#define IPR_3BIT_HOP         0x02
	char dual_state[16];
	char preferred_dual_state[16];
	int host_num;
	char pci_address[16];
	char host_name[16];
	char physical_location[1024];
	u8 yl_serial_num[YL_SERIAL_NUM_LEN];
	struct ipr_dev dev[IPR_MAX_IOA_DEVICES];
	struct ipr_multi_ioa_status ioa_status;
	struct ipr_array_query_data *qac_data;
	struct ipr_array_record *start_array_qac_entry;
	struct ipr_supported_arrays *supported_arrays;
	struct ipr_reclaim_query_data *reclaim_data;
	struct ipr_ioa *next;
	struct ipr_ioa *cmd_next;
};

#define __for_each_ioa(ioa, head) for (ioa = head; ioa; ioa = ioa->next)
#define for_each_ioa(ioa) __for_each_ioa(ioa, ipr_ioa_head)
#define for_each_primary_ioa(ioa) \
        __for_each_ioa(ioa, ipr_ioa_head) \
           if (!ioa->is_secondary)

#define for_each_secondary_ioa(ioa) \
        __for_each_ioa(ioa, ipr_ioa_head) \
           if (ioa->is_secondary)

#define for_each_sas_ioa(ioa) \
        __for_each_ioa(ioa, ipr_ioa_head) \
           if (!__ioa_is_spi(ioa))

#define for_each_dev(i, d) for (d = (i)->dev; (d - (i)->dev) < (i)->num_devices; d++)

#define for_ioa_and_each_dev(i, d) for (d = &((i)->ioa); \
                                       (d == &((i)->ioa)) || ((d - (i)->dev) < (i)->num_devices); \
                                       d = (d == &((i)->ioa)) ? (i)->dev : d + 1)

#define for_each_hotplug_dev(i, d) \
      for_each_dev(i, d) \
           if (ipr_is_af_dasd_device(d) || ipr_is_gscsi(d))

#define for_each_af_dasd(i, d) \
      for_each_dev(i, d) \
           if (ipr_is_af_dasd_device(d))

#define for_each_dev_in_vset(v, d) \
      for_each_af_dasd((v)->ioa, d) \
           if (ipr_is_array_member(d) && d->array_id == (v)->array_id)

#define for_each_vset(i, d) \
      for_each_dev(i, d) \
           if (ipr_is_volume_set(d) && !d->array_rcd->start_cand)

#define for_each_array(i, d) \
      for_each_dev(i, d) \
           if (ipr_is_array(d) && !d->array_rcd->start_cand)

#define for_each_dvd_tape(i, d) \
      for_each_dev(i, d) \
           if (d->scsi_dev_data && (d->scsi_dev_data->type == TYPE_ROM || \
		d->scsi_dev_data->type == TYPE_TAPE))

#define for_each_ses(i, d) \
      for_each_dev(i, d) \
           if (d->scsi_dev_data && d->scsi_dev_data->type == TYPE_ENCLOSURE)

#define for_each_hot_spare(i, d) \
      for_each_dev(i, d) \
           if (ipr_is_hot_spare(d))

#define for_each_disk(i, d) \
      for_each_dev(i, d) \
          if ((d)->scsi_dev_data && (ipr_is_af_dasd_device(d) || ipr_is_gscsi(d)))

#define __for_each_disk(i, d) \
      for_each_dev(i, d) \
          if ((d)->scsi_dev_data && ((d)->scsi_dev_data->type == TYPE_DISK || \
              (d)->scsi_dev_data->type == IPR_TYPE_AF_DISK))

#define for_each_standalone_disk(i, d) \
      for_each_disk(i, d) \
           if (!ipr_is_hot_spare(d) && !ipr_is_array_member(d))

#define __for_each_standalone_disk(i, d) \
      __for_each_disk(i, d) \
           if (!ipr_is_hot_spare(d) && !ipr_is_volume_set(d) && \
               !ipr_is_array_member(d))
           
#define for_each_standalone_af_disk(i, d) \
      for_each_standalone_disk(i, d) \
          if (ipr_is_af_dasd_device(d))

#define for_each_jbod_disk(i, d) \
      for_each_disk(i, d) \
          if (ipr_is_gscsi(d))

struct ipr_dasd_inquiry_page3 {
	u8 peri_qual_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
	u8 ascii_len;
	u8 reserved2[3];
	u8 load_id[4];
	u8 release_level[4];
	u8 ptf_number[4];
	u8 patch_number[4];
};

struct ipr_array_query32_data {
	u16 resp_len;
	u8 reserved;
	u8 num_records;
	u8 data[0];
};

struct ipr_array_query64_data {
	u32 resp_len;
	u32 num_records;
	u8 data[0];
};

struct ipr_array_query_data {
	u32 resp_len;
	u32 num_records;
	u32 hdr_len;
	u8 *data;
	union {
		u8 buf[IPR_QAC_BUFFER_SIZE];
		struct ipr_array_query32_data buf32;
		struct ipr_array_query64_data buf64;
	} u;
};

struct ipr_block_desc {
	u8 num_blocks[4];
	u8 density_code;
	u8 block_length[3];
};

struct ipr_mode_parm_hdr {
	u8 length;
	u8 medium_type;
	u8 device_spec_parms;
	u8 block_desc_len;
};

struct ipr_mode_pages {
	struct ipr_mode_parm_hdr hdr;
	u8 data[255 - sizeof(struct ipr_mode_parm_hdr)];
};

struct sense_data_t {
	u8 error_code;
	u8 segment_numb;
	u8 sense_key;
	u8 info[4];
	u8 add_sense_len;
	u8 cmd_spec_info[4];
	u8 add_sense_code;
	u8 add_sense_code_qual;
	u8 field_rep_unit_code;
	u8 sense_key_spec[3];
	u8 add_sense_bytes[0];
};

/* Structure for Descriptive Format Sense Data */
struct df_sense_data_t {
	u8 error_code;
	u8 sense_key;
	u8 add_sense_code;
	u8 add_sense_code_qual;
	u8 rfield;
	u8 rsrvd[2];
	u8 add_sense_len;
};

struct ipr_ioa_mode_page {
	struct ipr_mode_page_hdr hdr;
	u8 reserved;
	u8 max_tcq_depth;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved1:1;
	u8 format_completed:1;
	u8 reserved2:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved2:6;
	u8 format_completed:1;
	u8 reserved1:1;
#endif
};

struct ipr_mode_page24 {
	struct ipr_mode_page_hdr hdr;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 dual_adapter_af:2;
	u8 reserved:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved:6;
	u8 dual_adapter_af:2;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 rebuild_without_verify:1;
	u8 reserved1:3;
	u8 rebuild_rate:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 rebuild_rate:4;
	u8 reserved1:3;
	u8 rebuild_without_verify:1;
#endif

#define MIN_ARRAY_REBUILD_RATE		0x02

#define DISABLE_DUAL_IOA_AF		0x00
#define ENABLE_DUAL_IOA_AF		0x02
#define ENABLE_DUAL_IOA_ACTIVE_ACTIVE	0x03
};

struct ipr_config_term_hdr {
	u8 term_id;
	u8 len;
};

struct ipr_subsys_config_term {
	struct ipr_config_term_hdr hdr;
#define IPR_SUBSYS_CONFIG_TERM_ID	0x02
	u8 config;
#define IPR_AFDASD_SUBSYS		0x00
#define IPR_GSCSI_ONLY_HA_SUBSYS	0x01
	u8 reserved;
};

struct ipr_mode_page25 {
	struct ipr_mode_page_hdr hdr;
	u8 reserved[2];
	struct ipr_config_term_hdr term;
	u8 data[256];
};

#define for_each_page25_term(hdr, page) \
for (hdr = &(page)->term;	\
	(char *)hdr < ((char *)(page) + (page)->hdr.page_length + sizeof((page)->hdr));	\
	hdr = (struct ipr_config_term_hdr *)((char *)hdr + (hdr)->len + sizeof(*hdr)))

struct ipr_mode_page_28_header {
	struct ipr_mode_page_hdr header;
	u8 num_dev_entries;
	u8 dev_entry_length;
};

struct ipr_mode_page_28 {
	struct ipr_mode_page_28_header page_hdr;
	struct ipr_mode_page_28_scsi_dev_bus_attr attr[0];
};

#define for_each_bus_attr(ptr, page28, i) \
      for (i = 0, ptr = page28->attr; i < page_28->page_hdr.num_dev_entries; \
           i++, ptr = (struct ipr_mode_page_28_scsi_dev_bus_attr *) \
               ((u8 *)ptr + page_28->page_hdr.dev_entry_length))

struct ipr_scsi_bus_attr {
	u32 max_xfer_rate;
	u8 qas_capability;
	u8 scsi_id;
	u8 bus_width;
	u8 extended_reset_delay;
	u8 min_time_delay;
};

struct ipr_scsi_buses {
	int num_buses;
	struct ipr_scsi_bus_attr bus[IPR_MAX_NUM_BUSES];
};

struct ipr_dasd_timeout_record {
	u8 op_code;
	u8 reserved;
	u16 timeout;
};

struct ipr_query_dasd_timeouts {
	u32 length;
	struct ipr_dasd_timeout_record record[100];
};

struct ipr_supported_arrays {
	struct ipr_common_record common;
	u16 num_entries;
	u16 entry_length;
	struct ipr_array_cap_entry entry[0];
};

struct ipr_read_cap {
	u32 max_user_lba;
	u32 block_length;
};

struct ipr_read_cap16 {
	u32 max_user_lba_hi;
	u32 max_user_lba_lo;
	u32 block_length;
};

/* Struct for disks that are unsupported or require a minimum microcode
 level prior to formatting to 522-byte sectors. */
struct unsupported_af_dasd {
	char vendor_id[IPR_VENDOR_ID_LEN + 1];
	char compare_vendor_id_byte[IPR_VENDOR_ID_LEN];
	char product_id[IPR_PROD_ID_LEN + 1];
	char compare_product_id_byte[IPR_PROD_ID_LEN];
	char lid[5];       /* Load ID - Bytes 8-11 of Inquiry Page 3 */
	char lid_mask[4];  /* Mask for certain bytes of the LID */
	uint supported_with_min_ucode_level;
	char min_ucode_level[5];
	char min_ucode_mask[4];    /* used to mask don't cares in the ucode level */
};

struct unsupported_dasd {
	char vendor_id[IPR_VENDOR_ID_LEN + 1];
	char compare_vendor_id_byte[IPR_VENDOR_ID_LEN];
	char product_id[IPR_PROD_ID_LEN + 1];
	char compare_product_id_byte[IPR_PROD_ID_LEN];
};

struct ipr_cmd_status_record {
	u16 reserved1;
	u16 length;
	u8 array_id;
	u8 command_code;
	u8 status;
#define IPR_CMD_STATUS_SUCCESSFUL            0
#define IPR_CMD_STATUS_IN_PROGRESS           2
#define IPR_CMD_STATUS_ATTRIB_CHANGE         3
#define IPR_CMD_STATUS_FAILED                4
#define IPR_CMD_STATUS_INSUFF_DATA_MOVED     5
#define IPR_CMD_STATUS_MIXED_BLK_DEV_CLASESS 6
#define IPR_CMD_STATUS_MIXED_LOG_BLK_SIZE    7
#define IPR_CMD_STATUS_UNSUPT_REQ_BLK_DEV_CLASS    8

	u8 percent_complete;
	struct ipr_res_addr failing_dev_res_addr;
	u32 failing_dev_res_handle;
	u32 failing_dev_ioasc;
	u32 ilid;
	u32 resource_handle;
	u8 vset_id;
	u8 flags;
	u16 reserved;
	u8 failing_dev_res_path[8];
};

struct ipr_cmd_status {
	u16 resp_len;
	u16 num_records;
	struct ipr_cmd_status_record record[250];
};

#define for_each_cmd_status(r, s) for (r = (s)->record; (unsigned long)(r) < ((unsigned long)((s)->record) + ntohs((s)->resp_len) - 4); r = (void *)(r) + ntohs((r)->length))

struct ipr_inquiry_page0 {
	u8 peri_qual_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
	u8 supported_page_codes[IPR_MAX_NUM_SUPP_INQ_PAGES];
};

struct ipr_inquiry_page3 {
	u8 peri_qual_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
	u8 ascii_len;
	u8 reserved2[3];
	u8 load_id[4];
	u8 major_release;
	u8 card_type;
	u8 minor_release[2];
	u8 ptf_number[4];
	u8 patch_number[4];
};

struct ipr_inquiry_ioa_cap {
	u8 peri_qual_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
	u8 ascii_len;
	u8 reserved2;
	u8 sis_version[2];
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 dual_ioa_raid:1;
	u8 dual_ioa_wcache:1;
	u8 dual_ioa_asymmetric_access:1;
	u8 reserved:2;
	u8 disable_array_rebuild_verify:1;
	u8 reserved7:2;

	u8 can_attach_to_aux_cache:1;
	u8 is_aux_cache:1;
	u8 is_dual_wide:1;
	u8 gscsi_only_ha:1;
	u8 reserved3:4;

	u8 reserved4:1;
	u8 af_4k_support:1;
	u8 reserved5:6;

	u8 reserved6:3;
	u8 ra_id_encoding:3;
	u8 sis_format:2;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved7:2;
	u8 disable_array_rebuild_verify:1;
	u8 reserved:2;
	u8 dual_ioa_asymmetric_access:1;
	u8 dual_ioa_wcache:1;
	u8 dual_ioa_raid:1;

	u8 reserved3:4;
	u8 gscsi_only_ha:1;
	u8 is_dual_wide:1;
	u8 is_aux_cache:1;
	u8 can_attach_to_aux_cache:1;

	u8 reserved4:6;
	u8 af_4k_support:1;
	u8 reserved5:1;

	u8 sis_format:2;
	u8 ra_id_encoding:3;
	u8 reserved6:3;
#endif
	u16 af_block_size;
	u16 af_ext_cap;
	u16 vset_ext_cap;
	u16 gscsi_ext_cap;
};

struct ipr_dasd_ucode_header {
	u8 length[3];
	u8 load_id[4];
	u8 modification_level[4];
	u8 ptf_number[4];
	u8 patch_number[4];
};

struct ipr_ioa_ucode_img_desc {
#define IPR_IOAF_STR   "IOAF"
#define IPR_FPGA_STR   "FPGA"
#define IPR_DRAM_STR   "AGIG"
	char fw_type[4];
#define IPR_IOAF       0
#define IPR_FPGA       1
#define IPR_DRAM       2
	u8 reserved[16];
};

struct ipr_ioa_ucode_ext_header {
       char eyecatcher[8];        /* EXTDLIMG */
       u32 image_length;
       u32 flags;
       char fw_level[8];
       u8 reserved[12];
       u32 img_desc_offset;
};

struct ipr_ioa_ucode_header {
	u32 header_length;
	u32 lid_table_offset;
	u32 rev_level;
#define LINUX_HEADER_RESERVED_BYTES 20
	u8 reserved[LINUX_HEADER_RESERVED_BYTES];
	char eyecatcher[16];        /* IBMAS400 CCIN */
	u32 num_lids;
};

struct ipr_fw_images {
	char file[100];
	u32 version;
	int has_header;
	char date[20];
};

struct ipr_ioa_vpd {
	struct ipr_std_inq_data std_inq_data;
	u8 ascii_part_num[IPR_VPD_PART_NUM_LEN];
	u8 reserved[40];
	u8 ascii_plant_code[IPR_VPD_PLANT_CODE_LEN];
};

struct ipr_cfc_vpd {
	u8 peri_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 add_page_len;
	u8 ascii_len;
	u8 cache_size[IPR_VPD_CACHE_SIZE_LEN];
	struct ipr_std_inq_vpids vpids;
	u8 revision_level[4];
	u8 serial_num[IPR_SERIAL_NUM_LEN];
	u8 ascii_part_num[12];
	u8 reserved3[40];
	u8 ascii_plant_code[IPR_VPD_PLANT_CODE_LEN];
};

struct ipr_dram_vpd {
	u8 peri_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 add_page_len;
	u8 ascii_len;
	u8 dram_size[IPR_VPD_DRAM_SIZE_LEN];
};

struct ipr_cache_cap_vpd {
#define IPR_CACHE_CAP_VSET_WRITE_CACHE	0x08000000
	u8 peri_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 add_page_len;
	u32 cache_cap;
	u32 data_store_size;
	u32 write_cache_size;
	u32 comp_write_cache_size;
	u32 read_cache_size;
	u32 comp_read_cache_size;
};

struct ipr_dev_identify_vpd {
	u8 peri_dev_type;
	u8 page_code;
	u16 add_page_len;
	u8 reserved[80];
	u8 dev_identify_contxt[40];
};

#define IPR_IOA_MAX_SUPP_LOG_PAGES		64
struct ipr_supp_log_pages {
	u8 page_code;
	u8 reserved;
	u16 length;
	u8 page[IPR_IOA_MAX_SUPP_LOG_PAGES];
};

struct ipr_sas_phy_log_desc {
	u8 reserved;
	u8 phy;
	u8 reserved2[2];

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reseved3:1;
	u8 attached_dev_type:3;
	u8 reserved4:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved4:4;
	u8 attached_dev_type:3;
	u8 reseved3:1;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved5:4;
	u8 link_rate:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 link_rate:4;
	u8 reserved5:4;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved6:4;
	u8 attached_ssp_initiator_port:1;
	u8 attached_stp_initiator_port:1;
	u8 attached_smp_initiator_port:1;
	u8 reserved7:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved7:1;
	u8 attached_smp_initiator_port:1;
	u8 attached_stp_initiator_port:1;
	u8 attached_ssp_initiator_port:1;
	u8 reserved6:4;
#endif

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved8:4;
	u8 attached_ssp_target_port:1;
	u8 attached_stp_target_port:1;
	u8 attached_smp_target_port:1;
	u8 reserved9:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved9:1;
	u8 attached_smp_target_port:1;
	u8 attached_stp_target_port:1;
	u8 attached_ssp_target_port:1;
	u8 reserved8:4;
#endif

	u8 sas_addr[8];
	u8 attached_sas_addr[8];
	u8 attached_phy_id;
	u8 reserved10[7];
	u32 invalid_dword_count;
	u32 running_disparity_error_count;
	u32 loss_of_dword_sync_count;
	u32 phy_reset_problem_count;
};

struct ipr_sas_port_log_desc {
	u16 port_num;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 du:1;
	u8 ds:1;
	u8 tsd:1;
	u8 etc:1;
	u8 tmc:2;
	u8 lbin:1;
	u8 lp:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 lp:1;
	u8 lbin:1;
	u8 tmc:2;
	u8 etc:1;
	u8 tsd:1;
	u8 ds:1;
	u8 du:1;
#endif
	u8 length;
	u8 proto_id;
#define IPR_SAS_PROTOCOL_ID	0x06
	u8 reserved[2];
	u8 num_phys;
#define IPR_IOA_MAX_PHYS	4
	struct ipr_sas_phy_log_desc phy[IPR_IOA_MAX_PHYS];
};

#define IPR_SAS_LINK_RATE_NOT_PROGRAMMABLE	0
#define IPR_SAS_LINK_RATE_1_5_Gbps			8
#define IPR_SAS_LINK_RATE_3_0_Gbps			9

#define IPR_SAS_ROUTING_DIRECT		0
#define IPR_SAS_ROUTING_SUB_OR_DIRECT	1
#define IPR_SAS_ROUTING_TABLE_OR_DIRECT	2

struct ipr_sas_phy_info {
	u32 len;
	u8 bus;
	u8 cascade;
	u8 phy_num;
	u8 reserved;
	struct ipr_sas_phy_log_desc phy_log;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 prog_min_link_rate:4;
	u8 hw_min_link_rate:4;

	u8 prog_max_link_rate:4;
	u8 hw_max_link_rate:4;

	u8 virtual_phy:1;
	u8 reserved2:7;

	u8 reserved3:4;
	u8 routing_attr:4;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 hw_min_link_rate:4;
	u8 prog_min_link_rate:4;

	u8 hw_max_link_rate:4;
	u8 prog_max_link_rate:4;

	u8 reserved2:7;
	u8 virtual_phy:1;

	u8 routing_attr:4;
	u8 reserved3:4;
#endif
};

struct ipr_sas_expander_info {
	u32 len;
	u8 bus;
	u8 cascade;
	u8 reserved;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved2:7;
	u8 sas_1_1_fmt:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 sas_1_1_fmt:1;
	u8 reserved2:7;
#endif
	struct ipr_std_inq_vpids vpids;
	u8 prod_rev_level[4];
	u8 component_vendor_id[8];
	u8 component_id[2];
	u8 component_rev_id;
	u8 reserved3;
	u8 vendor_spec[8];
	u8 enclosure_logical_id[8];
	u8 reserved4[3];
	u8 num_phys;
	struct ipr_sas_phy_info phy[1];
};

struct ipr_query_sas_expander_info {
	u32 len;
	u8 reserved[3];
	u8 num_expanders;
	struct ipr_sas_expander_info exp[1];
};

struct ipr_global_cache_params_term {
#define IPR_CACHE_PARAM_TERM_ID	0x10
	u8 term_id;
	u8 len;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 enable_caching_dual_ioa_failure:1;
	u8 disable_caching_requested:1;
	u8 reserved1:2;
	u8 vset_write_cache_enabled:1;
	u8 reserved2:3;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved2:3;
	u8 vset_write_cache_enabled:1;
	u8 reserved1:2;
	u8 disable_caching_requested:1;
	u8 enable_caching_dual_ioa_failure:1;
#endif
	u8 reserved3;
};

struct log_parameter_hdr {
	u8 parameter_code[2];

#if defined (__BIG_ENDIAN_BITFIELD)
	u8 du:1;
	u8 reserved1:1;
	u8 tsd:1;
	u8 etc:1;
	u8 tmc:2;
	u8 lbin:1;
	u8 lp:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 lp:1;
	u8 lbin:1;
	u8 tmc:2;
	u8 etc:1;
	u8 tsd:1;
	u8 reserved1:1;
	u8 du:1;
#endif
	u8 length;
};

/* Log Parameter: Log Page = 0x34. Attribute template */
struct ipr_sas_log_smart_attr {
	struct log_parameter_hdr hdr;
	u8 norm_threshold_val;
	int8_t norm_worst_val;
	u8 raw_data[10];
};

/* Log Parameter: Log Page = 0x2F. Attribute Code = 0x0 */
struct ipr_sas_log_inf_except_attr {
	struct log_parameter_hdr param_hdr;
	u8 inf_except_add_sense_code;
	u8 inf_except_add_sense_code_qual;
	u8 last_temp_read;
};

struct ipr_sas_log_write_err_cnt_attr {
	struct log_parameter_hdr param_hdr;
	u8 counter;
};

struct ipr_sas_log_page {
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 reserved1:2;
	u8 page_code:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 page_code:6;
	u8 reserved1:2;
#endif
	u8 reserved2;
	u8 page_length[2];

#define IPR_SAS_LOG_MAX_ENTRIES		256
	u8 raw_data[IPR_SAS_LOG_MAX_ENTRIES];
};

struct ipr_query_ioa_caching_info {
	u16 len;
	u8 reserved[2];
#define IPR_MAX_TERMS           512
	struct ipr_global_cache_params_term term[IPR_MAX_TERMS];
};

#define for_each_cache_term(term, info) \
        for (term = (info)->term; \
             ((unsigned long)term) < ((unsigned long)((unsigned long)(info) + ntohs((info)->len)) + 2) && \
             ((unsigned long)term + term->len + 2 - (unsigned long)(info)->term) < sizeof((info)->term); \
             term = (struct ipr_global_cache_params_term *)(((unsigned long)term) + term->len + 2))

struct ipr_log_page18 {
	u8 page_code;
	u8 reserved;
	u16 length;
#define IPR_IOA_MAX_PORTS	32
	struct ipr_sas_port_log_desc port[IPR_IOA_MAX_PORTS];
};

#define for_each_port(port, log) \
        for (port = (log)->port; \
             (unsigned long)port < ((unsigned long)((log)->port) + ntohs(port->length)); \
             port = (struct ipr_sas_port_log_desc *)((unsigned long)(&port->length) + port->length + 1))

#define for_each_phy(phy, port) \
        for (phy = (port)->phy; \
             (phy < ((port)->phy + (port)->num_phys)) && \
             (phy < ((port)->phy + IPR_IOA_MAX_PORTS)); phy++)

struct ipr_dasd_perf_counters_log_page30 {
	u8 page_code;
	u8 reserved1;
	u16 length;
	u8 reserved2[3];
	u8 param_length;
	u16 dev_no_seeks;
	u16 dev_seeks_2_3;
	u16 dev_seeks_1_3;
	u16 dev_seeks_1_6;
	u16 dev_seeks_1_12;
	u16 dev_seeks_0;
	u32 reserved3;
	u16 dev_read_buf_overruns;
	u16 dev_write_buf_underruns;
	u32 dev_cache_read_hits;
	u32 dev_cache_partial_read_hits;
	u32 dev_cache_write_hits;
	u32 dev_cache_fast_write_hits;
	u32 reserved4;
	u32 reserved5;
	u32 ioa_dev_read_ops;
	u32 ioa_dev_write_ops;
	u32 ioa_cache_read_hits;
	u32 ioa_cache_partial_read_hits;
	u32 ioa_cache_write_hits;
	u32 ioa_cache_fast_write_hits;
	u32 ioa_cache_emu_read_hits;
	u32 ioa_idle_loop_count[2];
	u32 ioa_idle_count_value;
	u8 ioa_idle_units;
	u8 reserved6[3];
};

struct ipr_fabric_config_element {
	u8 type_status;
#define IPR_PATH_CFG_TYPE_MASK	0xF0
#define IPR_PATH_CFG_NOT_EXIST	0x00
#define IPR_PATH_CFG_IOA_PORT		0x10
#define IPR_PATH_CFG_EXP_PORT		0x20
#define IPR_PATH_CFG_DEVICE_PORT	0x30
#define IPR_PATH_CFG_DEVICE_LUN	0x40

#define IPR_PATH_CFG_STATUS_MASK	0x0F
#define IPR_PATH_CFG_NO_PROB		0x00
#define IPR_PATH_CFG_DEGRADED		0x01
#define IPR_PATH_CFG_FAILED		0x02
#define IPR_PATH_CFG_SUSPECT		0x03
#define IPR_PATH_NOT_DETECTED		0x04
#define IPR_PATH_INCORRECT_CONN	0x05

	u8 cascaded_expander;
	u8 phy;
	u8 link_rate;
#define IPR_PHY_LINK_RATE_MASK	0x0F

	u32 wwid[2];
};

struct ipr_fabric_descriptor {
	u16 length;
	u8 ioa_port;
	u8 cascaded_expander;
	u8 phy;
	u8 path_state;
#define IPR_PATH_ACTIVE_MASK		0xC0
#define IPR_PATH_NO_INFO		0x00
#define IPR_PATH_ACTIVE			0x40
#define IPR_PATH_NOT_ACTIVE		0x80

#define IPR_PATH_STATE_MASK		0x0F
#define IPR_PATH_STATE_NO_INFO		0x00
#define IPR_PATH_HEALTHY		0x01
#define IPR_PATH_DEGRADED		0x02
#define IPR_PATH_FAILED			0x03

	u16 num_entries;
	struct ipr_fabric_config_element elem[1];
};

struct ipr_fabric_config_element64 {
	u16 length;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 cfg_elem_id:2;
	u8 reserved1:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved1:6;
	u8 cfg_elem_id:2;
#endif
	u8 reserved2;
	u8 type_status;
	u8 reserved3[2];
	u8 link_rate;
	u8 res_path[8];
	u32 wwid[4];
};

struct ipr_fabric_descriptor64 {
	u16 length;
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 fabric_id:2;
	u8 reserved1:6;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 reserved1:6;
	u8 fabric_id:2;
#endif
	u8 reserved2[2];
	u8 path_state;
	u8 reserved3;
	u8 res_path[8];
	u32 reserved4;
	u8 reserved5[2];
	u16 num_entries;
	struct ipr_fabric_config_element64 elem[1];
};

#define for_each_fabric_cfg(fabric, cfg) \
		for (cfg = (fabric)->elem; \
			cfg < ((fabric)->elem + ntohs((fabric)->num_entries)); \
			cfg++)

#define for_each_fabric_desc(fabric, info) \
	for (fabric = (info)->u.fabric; \
	     ((unsigned long)fabric) < (((unsigned long)(info)) + ntohl((info)->len) + sizeof((info)->len)); \
	     fabric = (struct ipr_fabric_descriptor *)(((unsigned long)fabric) + ntohs(fabric->length)))

#define for_each_fabric_desc64(fabric, info) \
	for (fabric = (info)->u.fabric64; \
	     ((unsigned long)fabric) < (((unsigned long)(info)) + ntohl((info)->len) + sizeof((info)->len)); \
	     fabric = (struct ipr_fabric_descriptor64 *)(((unsigned long)fabric) + ntohs(fabric->length)))

struct ipr_res_redundancy_info {
	u32 len;
	u8 possibly_redundant_paths;
	u8 healthy_paths;
	u8 degraded_paths;
	u8 failed_paths;
	u8 active_paths;
	u8 reserved[2];
	u8 fabric_descriptors;
	union {
		struct ipr_fabric_descriptor fabric[1];
		struct ipr_fabric_descriptor64 fabric64[1];
	} u;
	u8 data[16384];
};

struct ses_inquiry_page0 {
	u8 peri_qual_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
	u8 supported_vpd_page[SES_MAX_NUM_SUPP_INQ_PAGES];
};

struct ses_serial_num_vpd {
	u8 peri_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 add_page_len;
	u8 ascii_len;
	u8 serial_num_head[3];
	u8 feature_code[4];
	u8 ascii_dash;
	u8 count[3];
	u8 ascii_space;
	u8 ses_serial_num[7];
};


struct esm_serial_num_vpd {
	u8 peri_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_len;
	u8 ascii_len;
	u8 fru_part_number[3];
	u8 frb_number[8];
	u8 reserved2;
	u8 serial_num_head[3];
	u8 esm_serial_num[12];
	u8 reserved3;
	u8 model_num_head[3];
	u8 model_num[4];
	u8 reserved4;
	u8 frb_label_head[3];
	u8 frb_label[5];
	u8 reserved5;
};

struct drive_elem_desc {
	u8 reserved1[2];
	u8 desc_length[2];
	u8 reserved2;
#define DISK_PHY_LOC_LENGTH	9
	u8 disk_physical_loc[DISK_PHY_LOC_LENGTH];
	u8 reserved3[2];
	u8 form_facter;
	u8 slot_height;
	u8 slot_bus;
	u8 phy_speed;
};

struct drive_elem_desc_pg {
	u8 page_code;
	u8 reserved1;
	u16 page_length;
	u8 reserved2[6];
	u16 desc_length;
#define DEVICE_ELEM_NUMBER	50
	struct drive_elem_desc dev_elem[DEVICE_ELEM_NUMBER];
};
struct ipr_ses_type_desc {
	u8 elem_type;
#define IPR_SES_DEVICE_ELEM	0x01
#define IPR_SES_ESM_ELEM	0x07
#define IPR_SES_ENCLOSURE_ELEM	0x0E
	u8 num_elems;
	u8 subenclosure_id;
	u8 text_len;
};

struct ipr_drive_elem_status {
#if defined (__BIG_ENDIAN_BITFIELD)
	u8 select:1;
	u8 predictive_fault:1;
	u8 reserved:1;
	u8 swap:1;
	u8 status:4;

	u8 reserved2:1;
	u8 device_environment:2;
	u8 slot_id:5;

	u8 reserved3:4;
	u8 insert:1;
	u8 remove:1;
	u8 identify:1;
	u8 reserved4:1;

	u8 reserved5:1;
	u8 fault_requested:1;
	u8 fault_sensed:1;
	u8 reserved6:1;
	u8 enable_byp:2;
	u8 reserved7:1;
	u8 disable_resets:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
	u8 status:4;
	u8 swap:1;
	u8 reserved:1;
	u8 predictive_fault:1;
	u8 select:1;

	u8 slot_id:5;
	u8 device_environment:2;
	u8 reserved2:1;

	u8 reserved4:1;
	u8 identify:1;
	u8 remove:1;
	u8 insert:1;
	u8 reserved3:4;

	u8 disable_resets:1;
	u8 reserved7:1;
	u8 enable_byp:2;
	u8 reserved6:1;
	u8 fault_sensed:1;
	u8 fault_requested:1;
	u8 reserved5:1;
#endif
};

struct ipr_encl_status_ctl_pg {
	u8 page_code;
	u8 health_status;
	u16 byte_count;
	u8 reserved1[4];
	struct ipr_drive_elem_status elem_status[IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES];
	u8 reserved2[468];	/*rest of page 2*/
};

struct ipr_ses_config_pg {
	u8 buf[2048];
};

struct ipr_ses_inquiry_pageC3 {
	u8 perif_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
	u8 ascii_length;
	u8 mode_keyword[3];
	u8 mode[4];
	u8 reserved2;
};

/* Page 12h - Get Time */
struct ipr_ses_diag_page12 {
	u8 page_code;
	u8 reserved1;
	u8 page_length[2];
	u8 timestamp_origin;
	u8 reserved2;
	u8 timestamp[6];
};

/* Page 13h - Set Time */
struct ipr_ses_diag_ctrl_page13 {
	u8 page_code;
	u8 reserved1;
	u8 page_length[2];
	u8 timestamp[6];
	u8 reserved[2];
};

struct ipr_sas_inquiry_pageC4 {
	u8 peri_qual_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
#define IPR_SAS_ENDURANCE_HIGH_HDD 0x20
#define IPR_SAS_ENDURANCE_LOW_EZ   0x31
#define IPR_SAS_ENDURANCE_LOW3	   0x32
#define IPR_SAS_ENDURANCE_LOW1	   0x33
	u8 endurance;
	u8 reserved[6];
	u8 revision;
	u8 serial_num_11s[8];
	u8 serial_num_supplier[8];
	u8 master_drive_part[12];
};

struct ipr_sas_inquiry_pageC7 {
	u8 peri_qual_dev_type;
	u8 page_code;
	u8 reserved1;
	u8 page_length;
	u8 ascii_len;
	u8 reserved2[38];
	u8 format_timeout_hi; /* in minutes */
	u8 format_timeout_lo;
	u8 reserved3[63];
	u8 support_4k_modes;
#define ONLY_5XX_SUPPORTED		0
#define BOTH_5XXe_OR_4K_SUPPORTED	1
#define ONLY_4K_SUPPORTED		2
	u8 reserved4[5];
	u8 total_bytes_warranty[IPR_SAS_INQ_BYTES_WARRANTY_LEN];
	u8 reserved5[43];
};

static inline int ipr_elem_offset(struct ipr_ses_config_pg *ses_cfg, u8 type)
{
	int i, off;
	struct ipr_ses_type_desc *desc;
	u8 *diag = ses_cfg->buf;

	desc = (struct ipr_ses_type_desc *)&diag[12+diag[11]];

	for (i = 0, off = 1; i < diag[10]; off += (desc->num_elems + 1), i++, desc++)
		if (desc->elem_type == type)
			return off;

	return 1;
}

static inline int ipr_dev_elem_offset(struct ipr_ses_config_pg *ses_cfg)
{
	return ipr_elem_offset(ses_cfg, IPR_SES_DEVICE_ELEM);
}

static inline int ipr_ses_elem_offset(struct ipr_ses_config_pg *ses_cfg)
{
	return ipr_elem_offset(ses_cfg, IPR_SES_ENCLOSURE_ELEM);
}

static inline int ipr_esm_elem_offset(struct ipr_ses_config_pg *ses_cfg)
{
	return ipr_elem_offset(ses_cfg, IPR_SES_ESM_ELEM);
}

static inline struct ipr_drive_elem_status *
ipr_get_overall_elem(struct ipr_encl_status_ctl_pg *ses_data,
		     struct ipr_ses_config_pg *ses_cfg)
{
	return &(ses_data->elem_status[ipr_dev_elem_offset(ses_cfg) - 1]);
}

static inline struct ipr_ses_type_desc *ipr_get_elem(struct ipr_ses_config_pg *ses_cfg, u8 type)
{
	int i;
	struct ipr_ses_type_desc *desc;
	u8 *diag = ses_cfg->buf;

	desc = (struct ipr_ses_type_desc *)&diag[12+diag[11]];

	for (i = 0; i < diag[10]; i++, desc++)
		if (desc->elem_type == type)
			return desc;

	return NULL;
}

static inline struct ipr_ses_type_desc *ipr_get_dev_elem(struct ipr_ses_config_pg *ses_cfg)
{
	return ipr_get_elem(ses_cfg, IPR_SES_DEVICE_ELEM);
}

static inline struct ipr_drive_elem_status *
ipr_get_enclosure_elem(struct ipr_encl_status_ctl_pg *ses_data,
		       struct ipr_ses_config_pg *ses_cfg)
{
	return &(ses_data->elem_status[ipr_ses_elem_offset(ses_cfg) - 1]);
}

static inline struct ipr_drive_elem_status *
ipr_get_esm_elem(struct ipr_encl_status_ctl_pg *ses_data,
		 struct ipr_ses_config_pg *ses_cfg)
{
	return &(ses_data->elem_status[ipr_esm_elem_offset(ses_cfg) - 1]);
}

static inline int ipr_max_dev_elems(struct ipr_ses_config_pg *ses_cfg)
{
	struct ipr_ses_type_desc *desc = ipr_get_dev_elem(ses_cfg);

	if (desc && desc->num_elems < IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES)
		return desc->num_elems;

	return IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES;
}

#define for_each_elem_status(elem, sd, sc) \
        for (elem = &((sd)->elem_status[ipr_dev_elem_offset(sc)]); \
             elem < &((sd)->elem_status[(ntohs((sd)->byte_count)-4)/sizeof((sd)->elem_status[0])]) && \
             elem < &((sd)->elem_status[ipr_dev_elem_offset(sc) + ipr_max_dev_elems(sc)]) && \
             elem < &((sd)->elem_status[IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES]); elem++)

int sg_ioctl(int, u8 *, void *, u32, u32, struct sense_data_t *, u32);
int sg_ioctl_noretry(int, u8 *, void *, u32, u32, struct sense_data_t *, u32);
int ipr_change_multi_adapter_assignment(struct ipr_ioa *, int, int);
int set_ha_mode(struct ipr_ioa *, int);
int set_preferred_primary(struct ipr_ioa *, int);
void check_current_config(bool);
void __check_current_config(bool, bool);
int num_device_opens(int, int, int, int);
int open_and_lock(char *);
int tool_init(int);
void exit_on_error(char *, ...);
bool is_af_blocked(struct ipr_dev *, int);
int ipr_query_array_config(struct ipr_ioa *, bool, bool, bool, int, struct ipr_array_query_data *);
int __ipr_query_array_config(struct ipr_ioa *, int, bool, bool, bool, int, struct ipr_array_query_data *);
int ipr_query_command_status(struct ipr_dev *, void *);
int ipr_query_io_dev_port(struct ipr_dev *, struct ipr_query_io_port *);
int ipr_mode_sense(struct ipr_dev *, u8, void *);
int ipr_mode_select(struct ipr_dev *, void *, int);
int ipr_log_sense(struct ipr_dev *, u8, void *, u16);
int ipr_is_log_page_supported(struct ipr_dev *, u8);
void *ipr_sas_log_get_param(const struct ipr_sas_log_page *page, u32 param,
			    int *entries_cnt);
int ipr_reset_device(struct ipr_dev *);
int ipr_re_read_partition(struct ipr_dev *);
int ipr_read_capacity(struct ipr_dev *, void *);
int ipr_read_capacity_16(struct ipr_dev *, void *);
int ipr_query_resource_state(struct ipr_dev *, void *);
void ipr_allow_restart(struct ipr_dev *, int);
int ipr_get_logical_block_size(struct ipr_dev *);
bool ipr_is_af_blk_size(struct ipr_ioa *, int);
void ipr_set_manage_start_stop(struct ipr_dev *);
int ipr_start_stop_start(struct ipr_dev *);
int ipr_start_stop_stop(struct ipr_dev *);
int ipr_stop_array_protection(struct ipr_ioa *);
int ipr_remove_hot_spare(struct ipr_ioa *);
int ipr_start_array_protection(struct ipr_ioa *, int, int);
int ipr_migrate_array_protection(struct ipr_ioa *,
	       			 struct ipr_array_query_data *, int, int, int);
int ipr_set_array_asym_access(struct ipr_ioa *);
int ipr_add_hot_spare(struct ipr_ioa *);
int ipr_rebuild_device_data(struct ipr_ioa *);
int ipr_resync_array(struct ipr_ioa *);
int ipr_test_unit_ready(struct ipr_dev *, struct sense_data_t *);
int ipr_format_unit(struct ipr_dev *);
void ipr_format_res_path(u8 *, char *, int);
void ipr_format_res_path_wo_hyphen(u8 *, char *, int);
int ipr_add_array_device(struct ipr_ioa *, int, struct ipr_array_query_data *);
int ipr_reclaim_cache_store(struct ipr_ioa *, int, void *);
int ipr_evaluate_device(struct ipr_dev *, u32);
int ipr_query_res_redundancy_info(struct ipr_dev *,
				  struct ipr_res_redundancy_info *);
int ipr_query_sas_expander_info(struct ipr_ioa *,
				struct ipr_query_sas_expander_info *);
int ipr_query_cache_parameters(struct ipr_ioa *, void *, int);
int ipr_disrupt_device(struct ipr_dev *);
int ipr_inquiry(struct ipr_dev *, u8, void *, u8);
int ipr_query_res_addr_aliases(struct ipr_ioa *, struct ipr_res_addr *,
			       struct ipr_res_addr_aliases *);
int ipr_query_res_path_aliases(struct ipr_ioa *, struct ipr_res_path *,
			       struct ipr_res_path_aliases *);
void ipr_convert_res_path_to_bytes(struct ipr_dev *);
void ipr_format_res_path(u8 *, char *, int);
void ipr_reset_adapter(struct ipr_ioa *);
void ipr_scan(struct ipr_ioa *, int, int, int);
int ipr_read_host_attr(struct ipr_ioa *, char *, void *, size_t);
int ipr_write_host_attr(struct ipr_ioa *, char *, void *, size_t);
int ipr_read_dev_attr(struct ipr_dev *, char *, char *, size_t);
int ipr_write_dev_attr(struct ipr_dev *, char *, char *);
int ipr_suspend_device_bus(struct ipr_dev *, struct ipr_res_addr *, u8);
int ipr_resume_device_bus(struct ipr_dev *, struct ipr_res_addr *);
int ipr_can_remove_device(struct ipr_dev *);
int ipr_receive_diagnostics(struct ipr_dev *, u8, void *, int);
int ipr_send_diagnostics(struct ipr_dev *, void *, int);
int ipr_get_bus_attr(struct ipr_ioa *, struct ipr_scsi_buses *);
void ipr_modify_bus_attr(struct ipr_ioa *, struct ipr_scsi_buses *);
int ipr_set_bus_attr(struct ipr_ioa *, struct ipr_scsi_buses *, int);
int ipr_write_buffer(struct ipr_dev *, void *, int);
int enable_af(struct ipr_dev *);
int get_max_bus_speed(struct ipr_ioa *, int);
int ipr_get_ioa_attr(struct ipr_ioa *, struct ipr_ioa_attr *);
int ipr_get_dev_attr(struct ipr_dev *, struct ipr_disk_attr *);
int ipr_modify_dev_attr(struct ipr_dev *, struct ipr_disk_attr *);
int ipr_set_ioa_attr(struct ipr_ioa *, struct ipr_ioa_attr *, int);
int ipr_modify_ioa_attr(struct ipr_ioa *, struct ipr_ioa_attr *);
int ipr_set_dev_attr(struct ipr_dev *, struct ipr_disk_attr *, int);
int set_active_active_mode(struct ipr_ioa *, int);
int ipr_set_format_completed_bit(struct ipr_dev *);
int ipr_set_ses_mode(struct ipr_dev *, int);
int get_ioa_caching(struct ipr_ioa *);
int ipr_change_cache_parameters(struct ipr_ioa *, int);
int ipr_query_dasd_timeouts(struct ipr_dev *, struct ipr_query_dasd_timeouts *);
int get_ioa_firmware_image_list(struct ipr_ioa *, struct ipr_fw_images **);
int get_dasd_firmware_image_list(struct ipr_dev *, struct ipr_fw_images **);
int get_ses_firmware_image_list(struct ipr_dev *, struct ipr_fw_images **);
int get_latest_fw_image_version(struct ipr_dev *);
struct ipr_fw_images *get_latest_fw_image(struct ipr_dev *);
int ipr_update_ioa_fw(struct ipr_ioa *, struct ipr_fw_images *, int);
int ipr_update_disk_fw(struct ipr_dev *, struct ipr_fw_images *, int);
int ipr_init_dev(struct ipr_dev *);
int ipr_init_new_dev(struct ipr_dev *);
int ipr_init_ioa(struct ipr_ioa *);
int device_supported(struct ipr_dev *);
struct ipr_dev *get_dev_from_addr(struct ipr_res_addr *res_addr);
struct ipr_dev *get_dev_from_handle(struct ipr_ioa *ioa, u32 res_handle);
void ipr_daemonize();
struct unsupported_af_dasd *get_unsupp_af(struct ipr_std_inq_data *,
					  struct ipr_dasd_inquiry_page3 *);
bool disk_needs_msl(struct unsupported_af_dasd *,
		    struct ipr_std_inq_data *);
void ipr_add_zeroed_dev(struct ipr_dev *);
void ipr_update_qac_with_zeroed_devs(struct ipr_ioa *);
void ipr_cleanup_zeroed_devs();
void ipr_del_zeroed_dev(struct ipr_dev *);
int ipr_device_is_zeroed(struct ipr_dev *);
struct ipr_array_cap_entry *get_raid_cap_entry(struct ipr_supported_arrays *, u8 );
char *get_prot_level_str(struct ipr_supported_arrays *, int);
u32 get_fw_version(struct ipr_dev *);
int ipr_disable_qerr(struct ipr_dev *);
void ipr_log_ucode_error(struct ipr_ioa *);
u32 get_dasd_ucode_version(char *, int);
u32 get_ses_ucode_version(char *ucode_file);
const char *get_bus_desc(struct ipr_ioa *);
const char *get_ioa_desc(struct ipr_ioa *);
int ioa_is_spi(struct ipr_ioa *);
int __ioa_is_spi(struct ipr_ioa *);
int page0x0a_setup(struct ipr_dev *);
int handle_events(void (*) (void), int, void (*) (char *));
struct ipr_ioa *find_ioa(int);
int parse_option(char *);
struct ipr_dev *find_blk_dev(char *);
struct ipr_dev *find_gen_dev(char *);
struct ipr_dev *find_dev(char *);
int ipr_cmds_per_lun(struct ipr_ioa *);
void scsi_host_kevent(char *, int (*)(struct ipr_ioa *));
void scsi_dev_kevent(char *, struct ipr_dev *(*)(char *), int (*)(struct ipr_dev *));
int format_req(struct ipr_dev *);
struct ipr_dev *get_vset_from_array(struct ipr_ioa *, struct ipr_dev *);
struct ipr_dev *get_array_from_vset(struct ipr_ioa *, struct ipr_dev *);
struct sysfs_dev * ipr_find_sysfs_dev(struct ipr_dev *, struct sysfs_dev *);
void ipr_add_sysfs_dev(struct ipr_dev *, struct sysfs_dev **, struct sysfs_dev **);
void ipr_del_sysfs_dev(struct ipr_dev *, struct sysfs_dev **, struct sysfs_dev **);
struct ipr_dev *ipr_sysfs_dev_to_dev(struct sysfs_dev *);
struct ipr_array_cap_entry *get_cap_entry(struct ipr_supported_arrays *, char *);
int ipr_get_blk_size(struct ipr_dev *);
u32 get_ioa_ucode_version(char *);
int ipr_improper_device_type(struct ipr_dev *);
int ipr_get_fw_version(struct ipr_dev *, u8 release_level[4]);
int ipr_get_live_dump(struct ipr_ioa *);
int ipr_jbod_sysfs_bind(struct ipr_dev *, u8);
int ipr_max_queue_depth(struct ipr_ioa *ioa, int num_devs, int num_ssd_devs);
void ipr_count_devices_in_vset(struct ipr_dev *, int *num_devs, int *ssd_num_devs);
int ipr_known_zeroed_is_saved(struct ipr_dev *);
int get_sg_name(struct scsi_dev_data *);
int ipr_sg_inquiry(struct scsi_dev_data *, u8, void *, u8);
int get_scsi_dev_data(struct scsi_dev_data **scsi_dev_ref);

int ipr_device_lock(struct ipr_dev *dev);
void ipr_device_unlock(struct ipr_dev *dev);
int check_sg_module();

static inline u32 ipr_get_dev_res_handle(struct ipr_ioa *ioa, struct ipr_dev_record *dev_rcd)
{
	if (ioa->sis64)
		return dev_rcd->type3.resource_handle;
	else
		return dev_rcd->type2.resource_handle;
}

static inline u32 ipr_get_arr_res_handle(struct ipr_ioa *ioa, struct ipr_array_record *array_rcd)
{
	if (ioa->sis64)
		return array_rcd->type3.resource_handle;
	else
		return array_rcd->type2.resource_handle;
}

static inline int ipr_is_device_record(int record_id)
{
	if ((record_id == IPR_RECORD_ID_DEVICE_RECORD) ||
	    (record_id == IPR_RECORD_ID_DEVICE_RECORD_3))
		return 1;
	else
		return 0;
}

static inline int ipr_is_vset_record(int record_id)
{
	if ((record_id == IPR_RECORD_ID_ARRAY_RECORD) ||
	    (record_id == IPR_RECORD_ID_VSET_RECORD_3))
		return 1;
	else
		return 0;
}

static inline int ipr_is_array_record(int record_id)
{
	if ((record_id == IPR_RECORD_ID_ARRAY_RECORD) ||
	    (record_id == IPR_RECORD_ID_ARRAY_RECORD_3))
		return 1;
	else
		return 0;
}

static inline int ipr_is_ioa(struct ipr_dev *device)
{
	if (device->ioa && device->ioa->ioa.scsi_dev_data &&
	    device->scsi_dev_data == device->ioa->ioa.scsi_dev_data)
		return 1;
	else
		return 0;
}

static inline int ipr_is_af_dasd_device(struct ipr_dev *device)
{
	if ((device->qac_entry != NULL) &&
	    (ipr_is_device_record(device->qac_entry->record_id)))
		return 1;
	else
		return 0;
}

static inline int ipr_is_remote_af_dasd_device(struct ipr_dev *device)
{
	if ((device->qac_entry != NULL) &&
	    (ipr_is_device_record(device->qac_entry->record_id) &&
		device->dev_rcd->current_asym_access_state == IPR_ACTIVE_NON_OPTIMIZED))
		return 1;
	else
		return 0;
}

static inline int ipr_is_volume_set(struct ipr_dev *device)
{
	if ((device->qac_entry != NULL) &&
	    (ipr_is_vset_record(device->qac_entry->record_id)))
		return 1;
	else
		return 0;
}

static inline int ipr_is_array(struct ipr_dev *device)
{
	if ((device->qac_entry != NULL) &&
	    (ipr_is_array_record(device->qac_entry->record_id)))
		return 1;
	else
		return 0;
}

static inline int ipr_is_hidden(struct ipr_dev *device)
{
	if (ipr_is_af_dasd_device(device) ||
	    ((device->scsi_dev_data) &&
	     (device->scsi_dev_data->type == 3)))  //FIXME SES type.
			return 1;
	else
		return 0;}


static inline int ipr_is_hot_spare(struct ipr_dev *device)
{
	struct ipr_dev_record *dev_record =
		(struct ipr_dev_record *)device->qac_entry;

	if ((dev_record != NULL) &&
	    (ipr_is_device_record(dev_record->common.record_id)) &&
	    (dev_record->is_hot_spare))
		return 1;
	else
		return 0;
}

static inline int ipr_is_array_member(struct ipr_dev *device)
{
	struct ipr_dev_record *dev_record =
		(struct ipr_dev_record *)device->qac_entry;

	if ((dev_record != NULL) &&
	    (dev_record->array_member))
		return 1;
	else
		return 0;
}

static inline int ipr_is_af(struct ipr_dev *device)
{
	if (device->qac_entry != NULL)
		return 1;
	else
		return 0;
}

static inline int ipr_is_gscsi(struct ipr_dev *dev)
{
	if (!dev->qac_entry &&
	    dev->scsi_dev_data &&
	    dev->scsi_dev_data->type == TYPE_DISK)
		return 1;
	else
		return 0;
}

static inline int ipr_is_ses(struct ipr_dev *dev)
{
	if (dev->scsi_dev_data &&
	    dev->scsi_dev_data->type == TYPE_ENCLOSURE)
		return 1;
	else
		return 0;
}

static inline void ipr_strncpy_0(char *dest, char *source, int length)
{
	memcpy(dest, source, length);
	dest[length] = '\0';
}

static inline void ipr_strncpy_0n(char *dest, char *source, int length)
{
	char *ch;
	memcpy(dest, source, length);
	dest[length] = '\0';
	ch = strchr(dest, '\n');
	if (ch)
		*ch = '\0';
}

#define dprintf(...) \
do { \
if (ipr_debug) \
fprintf(stderr, __VA_ARGS__);\
} while(0)

#define ENTER dprintf("Entering %s\n", __FUNCTION__);
#define LEAVE dprintf("Leaving %s\n", __FUNCTION__);

#define syslog_dbg(...) \
do { \
if (ipr_debug) \
syslog(LOG_ERR, __VA_ARGS__);\
} while(0)

#define ra_dbg(ra, fmt, ...) \
      syslog_dbg("%d:%d:%d:%d: " fmt, (ra)->host, (ra)->bus, \
             (ra)->target, (ra)->lun, ##__VA_ARGS__); \

#define scsi_log(level, dev, fmt, ...) \
do { \
if (dev->scsi_dev_data && !dev->ioa->ioa_dead) { \
      syslog(level, "%d:%d:%d:%d: " fmt, dev->ioa->host_num, \
             dev->scsi_dev_data->channel, dev->scsi_dev_data->id, \
             dev->scsi_dev_data->lun, ##__VA_ARGS__); \
} \
} while (0)

#define scsi_dbg(dev, fmt, ...) \
do { \
if ((dev)->scsi_dev_data) { \
      syslog_dbg("%d:%d:%d:%d: " fmt, (dev)->ioa->host_num, \
             (dev)->scsi_dev_data->channel, (dev)->scsi_dev_data->id, \
             (dev)->scsi_dev_data->lun, ##__VA_ARGS__); \
} \
} while (0)

#define scsi_info(dev, fmt, ...) \
      scsi_log(LOG_NOTICE, dev, fmt, ##__VA_ARGS__)

#define scsi_err(dev, fmt, ...) \
      scsi_log(LOG_ERR, dev, fmt, ##__VA_ARGS__)

#define scsi_warn(dev, fmt, ...) \
      scsi_log(LOG_WARNING, dev, fmt, ##__VA_ARGS__)

#define scsi_cmd_err(dev, sense, cmd, rc) \
do { \
      if ((((sense)->error_code & 0x7F) != 0x70) || \
          (((sense)->sense_key & 0x0F) != 0x05) || ipr_debug) { \
             scsi_err(dev, "%s failed. rc=%d, SK: %X ASC: %X ASCQ: %X\n",\
                      cmd, rc, (sense)->sense_key & 0x0f, (sense)->add_sense_code, \
                      (sense)->add_sense_code_qual); \
      } \
} while (0)

#define scsi_cmd_dbg(dev, sense, cmd, rc) \
do { \
      if (rc && ipr_debug) { \
             scsi_err(dev, "%s failed. rc=%d, SK: %X ASC: %X ASCQ: %X\n",\
                      cmd, rc, (sense)->sense_key & 0x0f, (sense)->add_sense_code, \
                      (sense)->add_sense_code_qual); \
      } \
} while (0)

#define ioa_log(level, ioa, fmt, ...) \
      syslog(level, "%s: " fmt, ioa->pci_address, ##__VA_ARGS__)

#define ioa_info(ioa, fmt, ...) \
      ioa_log(LOG_NOTICE, ioa, fmt, ##__VA_ARGS__)

#define ioa_err(ioa, fmt, ...) \
      ioa_log(LOG_ERR, ioa, fmt, ##__VA_ARGS__)

#define ioa_dbg(ioa, fmt, ...) \
      syslog_dbg("%s: " fmt, ioa->pci_address, ##__VA_ARGS__)

#define ioa_cmd_err(ioa, sense, cmd, rc) \
do { \
if (!ioa->ioa_dead) { \
      if ((((sense)->error_code & 0x7F) != 0x70) || \
          (((sense)->sense_key & 0x0F) != 0x05) || ipr_debug) { \
             ioa_err(ioa, "%s failed. rc=%d, SK: %X ASC: %X ASCQ: %X\n",\
                     cmd, rc, (sense)->sense_key & 0x0f, (sense)->add_sense_code, \
                     (sense)->add_sense_code_qual); \
      } \
} \
} while (0)

#endif /* iprlib_h */