2
* LSI Logic MegaRAID (and MegaIDE ?) ATARAID metadata format handler.
4
* Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH.
7
* See file LICENSE at the top of this source tree for license information.
11
* FIXME: needs more metadata reengineering and grouping logic coding.
17
#define FORMAT_HANDLER
20
#if BYTE_ORDER != LITTLE_ENDIAN
21
# define DM_BYTEORDER_SWAB
22
# include <datastruct/byteorder.h>
25
static const char *handler = HANDLER;
27
/* Make up RAID device name. */
28
/* FIXME: senseful name ;) */
30
get_disk_slot(struct lsi *lsi)
32
return lsi->set_number * 2 + lsi->disk_number;
35
static struct lsi_disk *
36
get_disk(struct lsi *lsi)
38
return lsi->disks + get_disk_slot(lsi);
42
_name(struct lsi *lsi, char *str, size_t len, unsigned int subset)
44
return snprintf(str, len,
45
subset ? "lsi_%u%u-%u" : "lsi_%u%u",
46
lsi->set_id, lsi->set_number,
47
get_disk(lsi)->raid10_mirror);
51
name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset)
55
struct lsi *lsi = META(rd, lsi);
57
subset = subset && (lsi->type == LSI_T_RAID10);
58
if ((ret = dbg_malloc((len = _name(lsi, NULL, 0, subset) + 1)))) {
59
_name(lsi, ret, len, subset);
60
mk_alpha(lc, ret + HANDLER_LEN, strlen(ret) - HANDLER_LEN -
63
log_alloc_err(lc, handler);
68
/* Neutralize disk type */
72
/* Mapping of LSI Logic types to generic types */
73
static struct types types[] = {
74
{ LSI_T_RAID0, t_raid0 },
75
{ LSI_T_RAID1, t_raid1 },
76
{ LSI_T_RAID10, t_raid0 },
80
return rd_type(types, (unsigned int) lsi->type);
83
/* LSI device status. */
84
/* FIXME: add flesh. */
86
status(struct lsi *lsi)
91
/* Decide about ordering sequence of RAID device. */
93
dev_sort(struct list_head *pos, struct list_head *new)
95
struct lsi *p = META(RD(pos), lsi), *n = META(RD(new), lsi);
99
return (get_disk(n))->raid10_stripe <
100
(get_disk(p))->raid10_stripe;
102
default: /* RAID0 + RAID01 */
103
return get_disk_slot(n) < get_disk_slot(p);
107
/* Decide about ordering sequence of RAID subset. */
109
set_sort(struct list_head *pos, struct list_head *new)
111
struct lsi *p = META(RD_RS(pos), lsi), *n = META(RD_RS(new), lsi);
113
return n->disks[get_disk_slot(n)].raid10_mirror <
114
p->disks[get_disk_slot(p)].raid10_mirror;
118
* Read an LSI Logic RAID device
120
/* Endianess conversion. */
121
#if BYTE_ORDER == LITTLE_ENDIAN
127
struct lsi *lsi = meta;
128
struct lsi_disk *disk;
132
for (disk = lsi->disks; disk < &lsi->disks[LSI_MAX_DISKS]; disk++) {
133
CVT16(disk->magic_0);
134
CVT16(disk->magic_1);
142
is_lsi(struct lib_context *lc, struct dev_info *di, void *meta)
144
return !strncmp((const char *) ((struct lsi *) meta)->magic_name,
145
LSI_MAGIC_NAME, LSI_MAGIC_NAME_LEN);
148
static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
149
struct dev_info *di, void *meta, union read_info *info);
150
static struct raid_dev *
151
lsi_read(struct lib_context *lc, struct dev_info *di)
153
return read_raid_dev(lc, di, NULL,
154
sizeof(struct lsi), LSI_CONFIGOFFSET,
155
to_cpu, is_lsi, NULL, setup_rd, handler);
159
* Write a LSI Logic RAID device.
162
lsi_write(struct lib_context *lc, struct raid_dev *rd, int erase)
165
#if BYTE_ORDER != LITTLE_ENDIAN
166
struct lsi *lsi = META(rd, lsi);
170
ret = write_metadata(lc, handler, rd, -1, erase);
171
#if BYTE_ORDER != LITTLE_ENDIAN
178
* Group the RAID disk into a set.
180
* FIXME: this needs more work together with the metadata reengineering.
183
super_created(struct raid_set *ss, void *private)
186
ss->stride = META(private, lsi)->stride;
190
group_rd(struct lib_context *lc, struct raid_set *rs,
191
struct raid_set **ss, struct raid_dev *rd)
193
struct lsi *lsi = META(rd, lsi);
195
/* Refuse to add drives that are not online */
196
if (get_disk(lsi)->offline)
199
if (!init_raid_set(lc, rs, rd, lsi->stride, type(lsi), handler))
202
list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
207
if (!find_set(lc, NULL, rs->name, FIND_TOP))
208
list_add_tail(&rs->list, LC_RS(lc));
212
if (!(*ss = join_superset(lc, name, super_created,
220
static struct raid_set *
221
lsi_group(struct lib_context *lc, struct raid_dev *rd)
223
struct raid_set *rs, *ss = NULL;
228
if ((rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, rd,
229
NO_LIST, NO_CREATE, NO_CREATE_ARG)))
230
return group_rd(lc, rs, &ss, rd) ? (ss ? ss : rs) : NULL;
235
/* Figure total number of disks depending on RAID type. */
237
devices(struct raid_dev *rd, void *context)
239
switch (META(rd, lsi)->type) {
252
* Check an LSI RAID set.
254
* FIXME: more sanity checks!!!
257
lsi_check(struct lib_context *lc, struct raid_set *rs)
259
return check_raid_set(lc, rs, devices, NULL,
260
NO_CHECK_RD, NULL, handler);
264
* IO error event handler.
267
event_io(struct lib_context *lc, struct event_io *e_io)
269
struct raid_dev *rd = e_io->rd;
270
struct lsi *lsi = META(rd, lsi);
272
/* Avoid write trashing. */
273
if (status(lsi) & s_broken)
276
// FIXME: lsi->? = BAD;
280
static struct event_handlers lsi_event_handlers = {
282
.rd = NULL, /* FIXME: no device add/remove event handler yet. */
285
#ifdef DMRAID_NATIVE_LOG
286
/* Log native information about an LSI Logic RAID device. */
288
lsi_log(struct lib_context *lc, struct raid_dev *rd)
291
struct lsi *lsi = META(rd, lsi);
292
struct lsi_disk *disk;
294
log_print(lc, "%s (%s):", rd->di->path, handler);
295
DP("magic_name: %s", lsi, lsi->magic_name);
296
P("dummy: %u, 0x%x", lsi, lsi->dummy, lsi->dummy, lsi->dummy);
297
DP("seqno: %u", lsi, lsi->seqno);
298
P("dummy2: %u, 0x%x", lsi, lsi->dummy2, lsi->dummy2, lsi->dummy2);
299
P("dummy3: %u, 0x%x", lsi, lsi->dummy3, lsi->dummy3, lsi->dummy3);
300
DP("type: %u", lsi, lsi->type);
301
P("dummy4: %u, 0x%x", lsi, lsi->dummy4, lsi->dummy4, lsi->dummy4);
302
DP("stride: %u", lsi, lsi->stride);
304
for (disk = lsi->disks, i = 0; i < LSI_MAX_DISKS; disk++, i++) {
305
P("disks[%u].raid10_stripe: %u", lsi, disk, i,
306
disk->raid10_stripe);
307
P("disks[%u].raid10_mirror: %u", lsi, disk, i,
308
disk->raid10_mirror);
309
P("disks[%u].unknown: %u, 0x%x", lsi, disk, i,
310
disk->unknown, disk->unknown);
311
P("disks[%u].magic_0: 0x%x, %x, %x", lsi,
312
disk->magic_0, i, disk->magic_0,
313
(unsigned char) (((char *) &disk->magic_0)[0]),
314
(unsigned char) (((char *) &disk->magic_0)[1]));
315
P("disks[%u].magic_1: 0x%x, %x, %x", lsi,
316
disk->magic_1, i, disk->magic_1,
317
(unsigned char) (((char *) &disk->magic_1)[0]),
318
(unsigned char) (((char *) &disk->magic_1)[1]));
319
P("disks[%u].disk_number: %u", lsi, disk->disk_number,
320
i, disk->disk_number);
321
P("disks[%u].set_number: %u", lsi, disk->set_number,
322
i, disk->set_number);
323
P("disks[%u].unknown1: %lu, 0x%lX", lsi, disk->unknown1,
324
i, (uint64_t) disk->unknown1, (uint64_t) disk->unknown1);
327
DP("disk_number: %u", lsi, lsi->disk_number);
328
DP("set_number: %u", lsi, lsi->set_number);
329
DP("set_id: %u", lsi, lsi->set_id);
333
static struct dmraid_format lsi_format = {
335
.descr = "LSI Logic MegaRAID",
342
.events = &lsi_event_handlers,
343
#ifdef DMRAID_NATIVE_LOG
348
/* Register this format handler with the format core. */
350
register_lsi(struct lib_context *lc)
352
return register_format_handler(lc, &lsi_format);
355
/* Set the RAID device contents up derived from the LSI ones */
357
setup_rd(struct lib_context *lc, struct raid_dev *rd,
358
struct dev_info *di, void *meta, union read_info *info)
360
struct lsi *lsi = meta;
362
if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1)))
365
rd->meta_areas->offset = LSI_CONFIGOFFSET >> 9;
366
rd->meta_areas->size = sizeof(*lsi);
367
rd->meta_areas->area = (void *) lsi;
370
rd->fmt = &lsi_format;
372
rd->status = status(lsi);
373
rd->type = type(lsi);
375
rd->offset = LSI_DATAOFFSET;
376
/* FIXME: propper size ? */
377
if (!(rd->sectors = rd->meta_areas->offset))
378
return log_zero_sectors(lc, di->path, handler);
380
return (rd->name = name(lc, rd, 1)) ? 1 : 0;