forked from hmage/megactl
-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
mega.h
587 lines (509 loc) · 17.2 KB
/
mega.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
#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
/* Drives without enclosure report this as the enclosure ID */
#define DISK_NOENC 0xffff
/* 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 */
uint16_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