#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 */