megactl/src/mega.h

586 lines
17 KiB
C

#ifndef _MEGA_H
#define _MEGA_H
/*
* Definitions of data structures used by the adapter and by our
* high-level interface.
*
* Copyright (c) 2007 by Jefferson Ogata
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; see the file COPYING. If not, write to the Free Software
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "logpage.h"
#include <sys/types.h>
#include <sys/uio.h>
#include <scg/scsireg.h>
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
#define BITS_PER_LONG 32
#include <stdint.h>
#ifdef NEED_UINT8_T
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
#endif
/* DMA addresses come in generic and 64-bit flavours. */
#ifdef CONFIG_HIGHMEM
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
#endif
typedef u64 dma64_addr_t;
/* Hacks to get kernel module headers to compile. We're not using any data structures where these matter. */
typedef struct
{
volatile unsigned int lock;
} spinlock_t;
struct semaphore
{
int foo;
};
typedef struct { volatile int counter; } atomic_t;
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long);
unsigned long data;
};
#define __iomem
#define __user
#define wait_queue_head_t void *
/* typedef void wait_queue_head_t; */
struct list_head {
struct list_head *next, *prev;
};
/* Okay, should be able to include module headers now, hopefully. */
#include "megaraid/mbox_defs.h"
#include "megaraid/megaraid_ioctl.h"
#include "megaraid/megaraid_sas.h"
#define MAX_CONTROLLERS 32
#define M_RD_IOCTL_CMD 0x80
#define M_RD_IOCTL_CMD_NEW 0x81
#define M_RD_DRIVER_IOCTL_INTERFACE 0x82
#define SCSI_SELFTEST_DEFAULT 0x00
#define SCSI_SELFTEST_BACKGROUND_SHORT 0x01
#define SCSI_SELFTEST_BACKGROUND_LONG 0x02
#define SCSI_SELFTEST_BACKGROUND_ABORT 0x04
#define SCSI_SELFTEST_FOREGROUND_SHORT 0x05
#define SCSI_SELFTEST_FOREGROUND_LONG 0x06
/* megaraid2 header file gets this wrong. */
typedef struct {
uint8_t max_commands;
uint8_t rebuild_rate;
uint8_t max_targ_per_chan;
uint8_t nchannels;
uint8_t fw_version[4];
uint16_t age_of_flash;
uint8_t chip_set_value;
uint8_t dram_size;
uint8_t cache_flush_interval;
uint8_t bios_version[4];
uint8_t board_type;
uint8_t sense_alert;
uint8_t write_config_count;
uint8_t drive_inserted_count;
uint8_t inserted_drive;
uint8_t battery_status;
uint8_t dec_fault_bus_info;
} __attribute__ ((packed)) mraid_adapinfo1_t;
typedef struct {
mraid_adapinfo1_t adapter_info;
mraid_ldrv_info_t logdrv_info;
mraid_pdrv_info_t pdrv_info;
} __attribute__ ((packed)) mraid_inquiry1_t;
typedef struct {
mraid_inquiry1_t raid_inq;
uint16_t phys_drv_format[MAX_MBOX_CHANNELS];
uint8_t stack_attn;
uint8_t modem_status;
uint8_t rsvd[2];
} __attribute__ ((packed)) mraid_extinq1_t;
/* Structures we've figured out over many hours of staring at hex data. */
struct mega_physical_drive_error_info
{
uint8_t media;
uint8_t other;
} __attribute__ ((packed));
struct mega_predictive_map
{
uint8_t map[FC_MAX_PHYSICAL_DEVICES / 8];
} __attribute__ ((packed));
struct mega_device_entry_sas {
uint16_t device_id;
uint16_t enclosure;
uint8_t value_1; /* ? 1, 2 enclosure number + 1? backend port number? */
uint8_t slot;
uint8_t type; /* INQ_DASD, INQ_ENCL */
uint8_t port; /* 1 << connected port number */
uint64_t sas_address[2];
} __attribute__ ((packed));
/* opcode 0x02010000 */
struct mega_device_list_sas {
uint32_t length;
uint16_t num_devices;
uint16_t rsvd0;
struct mega_device_entry_sas device[32]; /* actually any number */
} __attribute__ ((packed));
struct mega_array_header_sas {
uint32_t length;
uint16_t num_span_defs;
uint16_t span_def_size; /* 0x0120 */
uint16_t num_disk_defs;
uint16_t disk_def_size; /* 0x0100 */
uint16_t num_hot_spares;
uint16_t value_0028; /* ? 0x0028 */
uint32_t pad0[4];
} __attribute__ ((packed));
struct mega_array_span_disk_sas
{
uint16_t device_id; /* 0xffff if device missing */
uint16_t sequence; /* ? 0x0002, 0x0004, 0x0006... as disks are created */
uint8_t flag_0:1;
uint8_t hotspare:1;
uint8_t rebuild:1;
uint8_t online:1;
uint8_t present:1;
uint8_t flag_1;
uint8_t enclosure;
uint8_t slot;
} __attribute__ ((packed));
struct mega_array_span_def_sas
{
uint64_t sectors_per_disk;
uint16_t span_size; /* number of disks in span */
uint16_t span_index; /* 0, 1, 2... */
uint32_t value_1; /* ? 0 */
uint32_t pad0[4];
struct mega_array_span_disk_sas disk[32]; /* real number is (config.span_def_size - offset .disks) / sizeof span_entry */
} __attribute__ ((packed));
struct mega_array_disk_entry_sas
{
uint64_t offset; /* offset in sectors of this vd */
uint64_t sectors_per_disk; /* sectors used for this vd on each disk */
uint16_t span_index; /* number of this span */
uint16_t pad2; /* ? 0 */
uint32_t pad3; /* ? 0 */
} __attribute__ ((packed));
#define MEGA_SAS_LD_OFFLINE 0
#define MEGA_SAS_LD_PARTIALLY_DEGRADED 1
#define MEGA_SAS_LD_DEGRADED 2
#define MEGA_SAS_LD_OPTIMAL 3
struct mega_array_disk_def_sas {
uint16_t disk_index; /* 0, 1, 2... */
uint16_t sequence; /* ? 0x0004, 0x0003 */
char name[16]; /* null-terminated, max 15 chars */
uint32_t flags; /* ? 0x01000001, 0x00000000 */
uint32_t pad0[2]; /* ? 0 */
uint8_t raid_level; /* 0, 1, 5 */
uint8_t raid_level_secondary; /* ? 3 for raid 5 with 4 spans, 0 for raid1 with 1 span */
uint8_t raid_level_qualifier; /* ? 3 for raid 5 with 4 spans, 0 for raid1 with 1 span */
uint8_t stripe_size; /* (2 << this) sectors per stripe; 4 == 8K, 5 == 16K, etc. */
uint8_t disks_per_span;
uint8_t num_spans;
uint16_t state; /* ? 0 == offline, 1 == partially degraded, 2 == degraded, 3 == optimal */
uint32_t value_4; /* ? 0x00000001, 0x00000000 */
uint32_t pad1[5]; /* ? 0 */
struct mega_array_disk_entry_sas span[8]; /* real number is (config.disk_def_size - offset .spans) / sizeof disk_entry */
} __attribute__ ((packed));
struct mega_array_hotspare_def_sas
{
uint16_t device_id;
uint16_t sequence; /* ? 0x001c, 0x001e, 0x0020 */
uint32_t flags; /* ? 0x00000000 for global, 0x01000001 for dedicated */
uint32_t array; /* dedicated array index */
uint32_t pad0[7]; /* ? 0 */
} __attribute__ ((packed));
/* opcode 0x04010000: array config is { header span_def* disk_def* hotspare_def* } */
struct mega_array_config_sas
{
struct mega_array_header_sas *header;
struct mega_array_span_def_sas *span;
struct mega_array_disk_def_sas *disk;
struct mega_array_hotspare_def_sas *hotspare;
};
/* opcode 0x05010000 */
#define MEGA_BATTERY_TYPE_NONE 0
#define MEGA_BATTERY_TYPE_ITBBU 1
#define MEGA_BATTERY_TYPE_TBBU 2
struct mega_battery_state_sas
{
uint8_t type; /* see above */
uint8_t foo; /* ? */
uint16_t voltage; /* millivolts */
uint16_t current; /* milliamps */
uint16_t temperature; /* celsius */
uint32_t firmware_status;
uint32_t pad0[5]; /* ? 0 */
uint8_t pad1:4;
uint8_t fully_discharged:1;
uint8_t fully_charged:1;
uint8_t discharging:1;
uint8_t initialized:1;
uint8_t remaining_time_alarm:1;
uint8_t remaining_capacity_alarm:1;
uint8_t pad2:1;
uint8_t discharge_terminated:1;
uint8_t over_temperature:1;
uint8_t pad3:1;
uint8_t charging_terminated:1;
uint8_t over_charged:1;
uint16_t charge; /* percentage */
uint16_t charger_status; /* charger status 0 == off, 1 == complete, 2 == in progress */
uint16_t capacity_remaining; /* milliamp-hours */
uint16_t capacity_full; /* milliamp-hours */
uint16_t health; /* state of health 0 == no, * == good */
uint32_t pad9[5]; /* ? 0 */
} __attribute__ ((packed));
/* opcode 0x05020000 */
struct mega_battery_capacity_sas
{
uint16_t charge_relative; /* percentage */
uint16_t charge_absolute; /* percentage */
uint16_t capacity_remaining; /* milliamp-hours */
uint16_t capacity_full; /* milliamp-hours */
uint16_t time_empty_run; /* minutes */
uint16_t time_empty_average; /* minutes */
uint16_t time_full_average; /* minutes */
uint16_t cycles;
uint16_t error_max; /* percentage */
uint16_t alarm_capacity; /* milliamp-hours */
uint16_t alarm_time; /* minutes */
uint16_t pad0; /* ? 0 */
uint32_t pad1[6]; /* ? 0 */
} __attribute__ ((packed));
/* opcode 0x05030000 */
struct mega_battery_design_sas
{
uint32_t manufacture_date; /* weird encoding: 0xfae87 == 2007/04/07, 0xfaebf == 2007/05/31 */
uint16_t design_capacity; /* milliamp-hours */
uint16_t design_voltage; /* millivolts */
uint16_t specification_info;
uint16_t serial_number;
uint16_t pack_stat_configuration;
char manufacturer[12];
char device_name[8];
char device_chemistry[5];
char device_vendor[5];
uint32_t pad0[5]; /* ? 0 */
} __attribute__ ((packed));
/* opcode 0x05050100 */
struct mega_battery_properties_sas
{
uint32_t device_learn_period; /* seconds */
uint32_t next_learn_time; /* seconds */
uint32_t learn_delay_interval; /* ? hours */
uint32_t auto_learn_mode; /* ? */
uint32_t pad0[4]; /* ? 0 */
} __attribute__ ((packed));
struct mega_battery_info_sas
{
struct mega_battery_state_sas state;
struct mega_battery_capacity_sas capacity;
struct mega_battery_design_sas design;
struct mega_battery_properties_sas properties;
};
/* opcode 0x02020000 */
struct mega_physical_disk_info_sas
{
uint16_t device_id;
uint16_t sequence;
union
{
struct scsi_inquiry inq;
uint8_t buf[96];
} inquiry;
uint16_t value_x; /* ? 0x8300 */ /* 0x064 */
uint16_t value_y; /* ? 0x4800, 0x2000 */
struct
{
uint8_t value[60];
} mystery_struct; /* 0x0a4 */
uint16_t value_0; /* ? 0x0000 */
uint8_t port; /* 1 << connected port number */
uint8_t value_1; /* ? 0 */
uint32_t media_errors;
uint32_t other_errors;
uint32_t predictive_failures;
uint32_t predictive_failure_event_sequence;
uint8_t failure:1;
uint8_t hotspare:1;
uint8_t rebuild:1;
uint8_t online:1;
uint8_t configured:1;
uint8_t flags_0:3;
uint8_t flags_1;
uint16_t value_4; /* ? 0x0000 */
uint32_t value_5; /* ? 0x00002002, 0x00003003, 0x00003009 */
uint32_t sas_address_count; /* number of sas addresses */
uint32_t pad_sas_addr; /* ? 0x00000000 */
uint64_t sas_address[4];
uint64_t raw_size; /* sectors; MegaCli only sees 32 bits */ /* 0x0e8 */
uint64_t noncoerced_size; /* sectors; MegaCli only sees 32 bits */ /* 0x0f0 */
uint64_t coerced_size; /* sectors; MegaCli only sees 32 bits */ /* 0x0f8 */
uint16_t enclosure; /* 0x100 */
uint8_t value_9; /* 1 or 2, not sure what it means, goes with enclosure */
uint8_t slot;
uint8_t value_10[0xfc];
} __attribute__ ((packed));
/* Unified config structures for generic high-level interface. */
enum mega_adapter_enum {
MEGA_ADAPTER_V2, /* PERC2 */
MEGA_ADAPTER_V34, /* PERC3 or PERC4 */
MEGA_ADAPTER_V5, /* PERC5 (SAS) */
};
/* Structure for io to adapters. */
struct mega_adapter_path
{
int fd; /* block device descriptor for adapter access */
uint8_t adapno; /* adapter number */
enum mega_adapter_enum type; /* adapter variant */
};
struct log_page_list
{
struct logData log;
uint8_t buf[4095]; /* rhl 7.3 croaks on >= 4096 */
struct log_page_list *next;
};
enum physical_drive_state
{
PdStateUnknown,
PdStateUnconfiguredGood,
PdStateUnconfiguredBad,
PdStateHotspare,
PdStateFailed,
PdStateRebuild,
PdStateOnline,
};
struct physical_drive_info
{
uint8_t present; /* whether drive responds to inquiry */
struct adapter_config *adapter; /* adapter this drive belongs to */
struct span_info *span; /* span this disk is a member of */
char name[16]; /* drive name (AxCyTz) */
uint16_t target; /* scsi channel+id or device_id */
uint16_t channel; /* channel or enclosure */
uint8_t id; /* scsi id or enclosure slot */
enum physical_drive_state state; /* drive state */
char *error_string; /* status error string (NULL if okay) */
uint64_t blocks; /* number of blocks */
char vendor[9]; /* vendor name */
char model[17]; /* vendor model */
char revision[5]; /* firmware version */
char serial[32]; /* serial number */
uint32_t predictive_failures; /* predictive failure count */
uint32_t media_errors;
uint32_t other_errors;
struct scsi_inquiry inquiry; /* scsi inquiry result */
struct log_page_list *log;
union
{
struct
{
struct mega_physical_disk_info_sas info;
} v5;
} q;
};
struct span_info
{
struct adapter_config *adapter; /* adapter this span belongs to */
uint32_t blocks_per_disk; /* blocks used per disk for this span */
uint32_t num_disks; /* number of disks in this span */
struct physical_drive_info **disk; /* pointers to component disks */
uint32_t num_logical_drives; /* how many logical drives this span belongs to */
struct logical_drive_info **logical_drive; /* pointers to logical drives */
};
struct span_reference
{
uint64_t offset; /* offset into each disk */
uint64_t blocks_per_disk; /* number of blocks used per disk */
struct span_info *span; /* the span */
};
enum logical_drive_state
{
LdStateUnknown,
LdStateOffline,
LdStatePartiallyDegraded,
LdStateDegraded,
LdStateOptimal,
LdStateDeleted,
};
struct logical_drive_info
{
struct adapter_config *adapter; /* adapter this drive belongs to */
char name[16]; /* logical drive name (AxLDy) */
uint16_t target; /* logical drive number */
enum logical_drive_state state; /* logical drive state */
uint8_t raid_level; /* raid level */
uint8_t num_spans; /* how many spans in this logical drive */
struct span_reference *span; /* pointers to component spans */
uint8_t span_size; /* number of disks per span */
};
enum battery_charger_state
{
ChargerStateUnknown,
ChargerStateFailed,
ChargerStateInProgress,
ChargerStateComplete,
};
struct adapter_config
{
struct mega_adapter_path target; /* adapter access path */
uint8_t is_sas; /* adapter is a sas adapter */
char name[16]; /* adapter name (Ax) */
char product[81]; /* adapter product name */
char bios[17]; /* adapter bios version */
char firmware[17]; /* adapter firmware version */
struct
{
uint8_t healthy:1;
uint8_t module_missing:1;
uint8_t pack_missing:1;
uint8_t low_voltage:1;
uint8_t high_temperature:1;
uint8_t cycles_exceeded:1;
uint8_t over_charged:1;
enum battery_charger_state charger_state;
int16_t voltage;
int16_t temperature;
} battery;
uint16_t dram_size; /* size of DRAM in MB */
uint16_t rebuild_rate; /* rebuild rate as percentage */
uint16_t num_channels; /* number of channels or enclosures */
uint8_t *channel; /* channel/enclosure map */
uint16_t num_physicals;
struct physical_drive_info *physical;
struct physical_drive_info **physical_list; /* ordered list of physical devices */
uint16_t num_spans; /* number of spans */
struct span_info *span;
uint16_t num_logicals; /* number of logical drives */
struct logical_drive_info *logical; /* logical drives */
struct adapter_config *next;
/* adapter-specific data structures */
union
{
struct
{
mraid_inquiry1_t inquiry;
struct mega_predictive_map map;
disk_array_8ld_span8_t config;
} v2;
struct
{
mraid_pinfo_t adapinfo;
mraid_inquiry3_t enquiry3;
struct mega_predictive_map map;
disk_array_40ld_t config;
} v3;
struct
{
struct megasas_ctrl_info adapinfo;
struct mega_device_list_sas *device;
struct mega_array_config_sas config;
struct mega_battery_info_sas battery;
} v5;
} q;
};
#endif