1756 lines
43 KiB
C
1756 lines
43 KiB
C
#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.69 2005/12/15 02:10:07 brking Exp $
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.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 <ctype.h>
|
|
#include <syslog.h>
|
|
#include <term.h>
|
|
#include <pci/pci.h>
|
|
#include <stdbool.h>
|
|
#include <netinet/in.h>
|
|
#include <sysfs/libsysfs.h>
|
|
#include <linux/byteorder/swab.h>
|
|
#include <asm/byteorder.h>
|
|
#include <sys/mman.h>
|
|
#include <paths.h>
|
|
#include <bits/sockaddr.h>
|
|
#include <linux/netlink.h>
|
|
|
|
#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 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 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 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_MAX_NUM_SUPP_INQ_PAGES 36
|
|
#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 (2 * 60) /* 2 minutes */
|
|
#define SET_DASD_TIMEOUTS_TIMEOUT (2 * 60)
|
|
#define IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES 15
|
|
#define IPR_DRIVE_ELEM_STATUS_EMPTY 5
|
|
#define IPR_DRIVE_ELEM_STATUS_POPULATED 1
|
|
#define IPR_TIMEOUT_MINUTE_RADIX 0x4000
|
|
|
|
#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 0xC8u
|
|
#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_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_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_TYPE_AF_DISK 0xC
|
|
#define IPR_TYPE_ADAPTER 0x1f
|
|
#define IPR_TYPE_EMPTY_SLOT 0xff
|
|
|
|
#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)
|
|
|
|
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 char *tool_name;
|
|
extern struct sysfs_dev *head_zdev;
|
|
extern struct sysfs_dev *tail_zdev;
|
|
|
|
struct sysfs_dev
|
|
{
|
|
char sysfs_device_name[16];
|
|
struct sysfs_dev *next, *prev;
|
|
};
|
|
|
|
struct ipr_res_addr {
|
|
u8 host;
|
|
u8 bus;
|
|
u8 target;
|
|
u8 lun;
|
|
#define IPR_GET_PHYSICAL_LOCATOR(res_addr) \
|
|
(((res_addr)->channel << 16) | ((res_addr)->id << 8) | (res_addr)->lun)
|
|
};
|
|
|
|
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_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;
|
|
#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;
|
|
#endif
|
|
u8 reserved5;
|
|
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_array_cap_entry {
|
|
u8 prot_level;
|
|
#define IPR_DEFAULT_RAID_LVL "5"
|
|
#if defined (__BIG_ENDIAN_BITFIELD)
|
|
u8 include_allowed:1;
|
|
u8 reserved:7;
|
|
#elif defined (__LITTLE_ENDIAN_BITFIELD)
|
|
u8 reserved:7;
|
|
u8 include_allowed:1;
|
|
#endif
|
|
u16 reserved2;
|
|
u8 reserved3;
|
|
u8 max_num_array_devices;
|
|
u8 min_num_array_devices;
|
|
u8 min_mult_array_devices;
|
|
u16 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
|
|
|
|
u8 reserved2;
|
|
|
|
#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 reserved4:5;
|
|
#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:5;
|
|
u8 resync_cand:1;
|
|
u8 stop_cand:1;
|
|
u8 start_cand:1;
|
|
#endif
|
|
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];
|
|
u32 reserved;
|
|
};
|
|
|
|
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
|
|
u8 reserved1;
|
|
|
|
#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 reserved3:6;
|
|
#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:6;
|
|
u8 rmv_hot_spare_cand:1;
|
|
u8 add_hot_spare_cand:1;
|
|
#endif
|
|
|
|
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_num[IPR_SERIAL_NUM_LEN];
|
|
u32 reserved5;
|
|
};
|
|
|
|
#define __for_each_qac_entry(rcd, qac, type) \
|
|
for (rcd = (type *)(qac)->data; \
|
|
((unsigned long)rcd) < ((unsigned long)((unsigned long)(qac) + ntohs((qac)->resp_len))) && \
|
|
((unsigned long)rcd) < ((unsigned long)((qac)->data + sizeof(*(qac)))); \
|
|
rcd = (type *)((unsigned long)rcd + ntohs(((struct ipr_common_record *)rcd)->record_len)))
|
|
|
|
#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 (rcd->common.record_id == IPR_RECORD_ID_DEVICE_RECORD)
|
|
|
|
#define for_each_array_rcd(rcd, qac) \
|
|
__for_each_qac_entry(rcd, qac, struct ipr_array_record) \
|
|
if (rcd->common.record_id == IPR_RECORD_ID_ARRAY_RECORD)
|
|
|
|
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 part_number[IPR_STD_INQ_PART_NUM_LEN];
|
|
u8 ec_level[IPR_STD_INQ_EC_LEVEL_LEN];
|
|
u8 fru_number[IPR_STD_INQ_FRU_NUM_LEN];
|
|
u8 z6_term[IPR_STD_INQ_Z6_TERM_LEN];
|
|
};
|
|
|
|
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_DA_PREFERRED_PRIMARY "PREFERRED_PRIMARY"
|
|
|
|
#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"
|
|
|
|
#define IPR_CATEGORY_DISK "Disk"
|
|
#define IPR_QUEUE_DEPTH "QUEUE_DEPTH"
|
|
#define IPR_TCQ_ENABLED "TCQ_ENABLED"
|
|
#define IPR_FORMAT_TIMEOUT "FORMAT_UNIT_TIMEOUT"
|
|
|
|
#define IPR_MAX_XFER_RATE 320
|
|
#define IPR_SAFE_XFER_RATE 160
|
|
|
|
/* 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;
|
|
int id;
|
|
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[16];
|
|
char dev_name[64];
|
|
char gen_name[64];
|
|
};
|
|
|
|
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_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_PRIMARY 2
|
|
#define IPR_IOA_STATE_SECONDARY 3
|
|
#define IPR_IOA_STATE_NO_PREFERENCE 4
|
|
u8 reserved;
|
|
u8 token;
|
|
u8 reserved2[4];
|
|
u8 remote_vendor_id[IPR_VENDOR_ID_LEN];
|
|
u8 remote_prod_id[IPR_PROD_ID_LEN];
|
|
u8 remote_sn[IPR_SERIAL_NUM_LEN];
|
|
u32 num_path_entries;
|
|
struct ipr_path_entry path[0]; /* variable length */
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
struct ipr_vset_attr {
|
|
int queue_depth;
|
|
};
|
|
|
|
struct ipr_ioa_attr {
|
|
int preferred_primary;
|
|
};
|
|
|
|
struct ipr_dev {
|
|
char dev_name[64];
|
|
char gen_name[64];
|
|
char prot_level_str[8];
|
|
u32 is_reclaim_cand:1;
|
|
u32 should_init:1;
|
|
u32 init_not_allowed:1;
|
|
struct scsi_dev_data *scsi_dev_data;
|
|
struct ipr_disk_attr attr;
|
|
union {
|
|
struct ipr_common_record *qac_entry;
|
|
struct ipr_dev_record *dev_rcd;
|
|
struct ipr_array_record *array_rcd;
|
|
};
|
|
struct ipr_ioa *ioa;
|
|
};
|
|
|
|
#define IPR_MAX_IOA_DEVICES (IPR_MAX_NUM_BUSES * 15 * 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 rw_protected:1; /* FIXME */
|
|
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;
|
|
u16 pci_vendor;
|
|
u16 pci_device;
|
|
u16 subsystem_vendor;
|
|
u16 subsystem_device;
|
|
char dual_state[16];
|
|
char preferred_dual_state[16];
|
|
int host_num;
|
|
char pci_address[16];
|
|
char host_name[16];
|
|
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_dev(i, d) for (d = (i)->dev; (d - (i)->dev) < (i)->num_devices; 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->dev_rcd->array_id == (v)->array_rcd->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_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_standalone_disk(i, d) \
|
|
for_each_disk(i, d) \
|
|
if (!ipr_is_hot_spare(d) && !ipr_is_array_member(dev))
|
|
|
|
#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_query_data {
|
|
u16 resp_len;
|
|
u8 reserved;
|
|
u8 num_records;
|
|
u8 data[IPR_QAC_BUFFER_SIZE];
|
|
};
|
|
|
|
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];
|
|
};
|
|
|
|
struct ipr_ioa_mode_page {
|
|
struct ipr_mode_page_hdr hdr;
|
|
u8 reserved;
|
|
u8 max_tcq_depth;
|
|
};
|
|
|
|
struct ipr_mode_page24 {
|
|
struct ipr_mode_page_hdr hdr;
|
|
#if defined (__BIG_ENDIAN_BITFIELD)
|
|
u8 enable_dual_ioa_af:1;
|
|
u8 reserved:7;
|
|
#elif defined (__LITTLE_ENDIAN_BITFIELD)
|
|
u8 reserved:7;
|
|
u8 enable_dual_ioa_af:1;
|
|
#endif
|
|
};
|
|
|
|
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_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
|
|
|
|
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;
|
|
};
|
|
|
|
struct ipr_cmd_status {
|
|
u16 resp_len;
|
|
u8 reserved;
|
|
u8 num_records;
|
|
struct ipr_cmd_status_record record[100];
|
|
};
|
|
|
|
#define for_each_cmd_status(r, s) for (r = (s)->record; (r - (s)->record) < (s)->num_records; r++)
|
|
|
|
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[3];
|
|
#if defined (__BIG_ENDIAN_BITFIELD)
|
|
u8 dual_ioa_raid:1;
|
|
u8 reserved:7;
|
|
u8 reserved3[3];
|
|
#elif defined (__LITTLE_ENDIAN_BITFIELD)
|
|
u8 reserved:7;
|
|
u8 dual_ioa_raid:1;
|
|
u8 reserved3[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_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;
|
|
};
|
|
|
|
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_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:4;
|
|
u8 scsi_id:4;
|
|
|
|
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:5;
|
|
#elif defined (__LITTLE_ENDIAN_BITFIELD)
|
|
u8 status:4;
|
|
u8 swap:1;
|
|
u8 reserved:1;
|
|
u8 predictive_fault:1;
|
|
u8 select:1;
|
|
|
|
u8 scsi_id:4;
|
|
u8 reserved2:4;
|
|
|
|
u8 reserved4:1;
|
|
u8 identify:1;
|
|
u8 remove:1;
|
|
u8 insert:1;
|
|
u8 reserved3:4;
|
|
|
|
u8 reserved6:5;
|
|
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];
|
|
|
|
#if defined (__BIG_ENDIAN_BITFIELD)
|
|
u8 overall_status_select:1;
|
|
u8 overall_status_predictive_fault:1;
|
|
u8 overall_status_reserved:1;
|
|
u8 overall_status_swap:1;
|
|
u8 overall_status_reserved2:4;
|
|
|
|
u8 overall_status_reserved3;
|
|
|
|
u8 overall_status_reserved4:4;
|
|
u8 overall_status_insert:1;
|
|
u8 overall_status_remove:1;
|
|
u8 overall_status_identify:1;
|
|
u8 overall_status_reserved5:1;
|
|
|
|
u8 overall_status_reserved6:2;
|
|
u8 overall_status_fault_requested:1;
|
|
u8 overall_status_reserved7:4;
|
|
u8 overall_status_disable_resets:1;
|
|
#elif defined (__LITTLE_ENDIAN_BITFIELD)
|
|
u8 overall_status_reserved2:4;
|
|
u8 overall_status_swap:1;
|
|
u8 overall_status_reserved:1;
|
|
u8 overall_status_predictive_fault:1;
|
|
u8 overall_status_select:1;
|
|
|
|
u8 overall_status_reserved3;
|
|
|
|
u8 overall_status_reserved5:1;
|
|
u8 overall_status_identify:1;
|
|
u8 overall_status_remove:1;
|
|
u8 overall_status_insert:1;
|
|
u8 overall_status_reserved4:4;
|
|
|
|
u8 overall_status_disable_resets:1;
|
|
u8 overall_status_reserved7:4;
|
|
u8 overall_status_fault_requested:1;
|
|
u8 overall_status_reserved6:2;
|
|
#endif
|
|
struct ipr_drive_elem_status elem_status[IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES];
|
|
};
|
|
|
|
#define for_each_elem_status(elem, sd) \
|
|
for (elem = (sd)->elem_status; \
|
|
elem < &((sd)->elem_status[(ntohs((sd)->byte_count)-8)/sizeof((sd)->elem_status[0])]) && \
|
|
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_set_preferred_primary(struct ipr_ioa *, int);
|
|
int set_preferred_primary(char *, int);
|
|
void check_current_config(bool);
|
|
int num_device_opens(int, int, int, int);
|
|
void 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, int, void *);
|
|
int __ipr_query_array_config(struct ipr_ioa *, int, bool, bool, int, void *);
|
|
int ipr_query_command_status(struct ipr_dev *, void *);
|
|
int ipr_mode_sense(struct ipr_dev *, u8, void *);
|
|
int ipr_mode_select(struct ipr_dev *, void *, int);
|
|
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 *);
|
|
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_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 *);
|
|
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_inquiry(struct ipr_dev *, u8, void *, u8);
|
|
void ipr_reset_adapter(struct ipr_ioa *);
|
|
void ipr_scan(struct ipr_ioa *, int, int, int);
|
|
int ipr_read_dev_attr(struct ipr_dev *, char *, char *);
|
|
int ipr_write_dev_attr(struct ipr_dev *, char *, char *);
|
|
int ipr_suspend_device_bus(struct ipr_ioa *, struct ipr_res_addr *, u8);
|
|
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_set_dev_attr(struct ipr_dev *, struct ipr_disk_attr *, int);
|
|
int ipr_set_dasd_timeouts(struct ipr_dev *);
|
|
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 **);
|
|
void ipr_update_ioa_fw(struct ipr_ioa *, struct ipr_fw_images *, int);
|
|
void ipr_update_disk_fw(struct ipr_dev *, struct ipr_fw_images *, int);
|
|
void ipr_init_dev(struct ipr_dev *);
|
|
void ipr_init_new_dev(struct ipr_dev *);
|
|
void 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(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_dev_fw_version(struct ipr_dev *);
|
|
u32 get_ioa_fw_version(struct ipr_ioa *);
|
|
int ipr_disable_qerr(struct ipr_dev *);
|
|
void ipr_log_ucode_error(struct ipr_ioa *);
|
|
u32 get_dasd_ucode_version(char *, int);
|
|
const char *get_ioa_desc(struct ipr_ioa *);
|
|
int 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 *, void (*)(struct ipr_ioa *));
|
|
void scsi_dev_kevent(char *, struct ipr_dev *(*)(char *), void (*)(struct ipr_dev *));
|
|
int format_req(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 *);
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Purpose: Identify Advanced Function DASD present
|
|
* Lock State: N/A
|
|
* Returns: 0 if not AF DASD
|
|
* 1 if AF DASD
|
|
*---------------------------------------------------------------------------*/
|
|
static inline int ipr_is_af_dasd_device(struct ipr_dev *device)
|
|
{
|
|
if ((device->qac_entry != NULL) &&
|
|
(device->qac_entry->record_id == IPR_RECORD_ID_DEVICE_RECORD))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static inline int ipr_is_volume_set(struct ipr_dev *device)
|
|
{
|
|
if ((device->qac_entry != NULL) &&
|
|
(device->qac_entry->record_id == IPR_RECORD_ID_ARRAY_RECORD))
|
|
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) &&
|
|
(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 syslog_dbg(...) \
|
|
do { \
|
|
if (ipr_debug) \
|
|
syslog(LOG_ERR, __VA_ARGS__);\
|
|
} while(0)
|
|
|
|
#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, (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, (sense)->add_sense_code, \
|
|
(sense)->add_sense_code_qual); \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
#endif
|