[PATCH] v2 of Adaptec HostRAID support for dmraid

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



All,

This is a revised patch to add HostRAID support to dmraid.  It contains
a reworked asr_group function that knows how to set up multilevel RAID
10, as well as the usual RAID0 / RAID1 cases.  It has seen somewhat
rigorous testing in RAID0/1/10 setups on a SCSI HostRAID x226 and very
light testing on SATA HostRAID on the same machine.  Last Friday I was
able to convert a a320raid based SLES9 SP2 system to a dmraid setup, and
verified that I could (with some difficulty) bring up the system.

Note that spare drives, metadata writes and I/O error handling are still
not implemented.

Mr. Mauelshagen: Was it ok to add subordinate raid_sets to the master
raid_set manually with list_add?

As usual, I'm looking for any comments or suggestions about how to
improve this code.  This patch should not be used in a production system
at all.

--D
diff -Naur orig/lib/format/ataraid/asr.c v3-test/lib/format/ataraid/asr.c
--- orig/lib/format/ataraid/asr.c	1969-12-31 16:00:00.000000000 -0800
+++ v3-test/lib/format/ataraid/asr.c	2006-01-10 16:13:40.000000000 -0800
@@ -0,0 +1,821 @@
+/*
+ * Adaptec HostRAID ASR format interpreter for dmraid.
+ * Copyright (C) 2005 IBM, All rights reserved.
+ *
+ * See file LICENSE at the top of this source tree for license information.
+ */
+
+#include <errno.h>
+#include <netinet/in.h>
+
+#define	HANDLER	"asr"
+
+#include "internal.h"
+#define	FORMAT_HANDLER
+#include "asr.h"
+#include <datastruct/byteorder.h>
+
+static const char *handler = HANDLER;
+
+/* Map ASR disk status to dmraid status */
+static enum status asr_disk_status(struct asr_raid_configline *disk) {
+	if (disk == NULL)
+		return s_undef;
+
+	switch (disk->raidstate) {
+		case LSU_COMPONENT_STATE_OPTIMAL:
+			return s_ok;
+		case LSU_COMPONENT_STATE_DEGRADED:
+		case LSU_COMPONENT_STATE_FAILED:
+			return s_broken;
+		case LSU_COMPONENT_STATE_UNINITIALIZED:
+		case LSU_COMPONENT_STATE_UNCONFIGURED:
+			return s_inconsistent;
+		case LSU_COMPONENT_SUBSTATE_BUILDING:
+		case LSU_COMPONENT_SUBSTATE_REBUILDING:
+		case LSU_COMPONENT_STATE_REPLACED:
+			return s_nosync;
+		default:
+			return s_undef;
+	}
+}
+		
+/* Extract config line from metadata */
+static struct asr_raid_configline *asr_get_config(struct asr *asr, uint32_t magic)
+{
+	unsigned int i;
+	
+	for (i = 0; i < asr->rt.elmcnt; i++) {
+		if (asr->rt.ent[i].raidmagic == magic)
+			return &asr->rt.ent[i];
+	}
+
+	return NULL;
+}
+
+/* Get this disk's configuration */
+static struct asr_raid_configline *asr_this_disk(struct asr *asr) {
+	return asr_get_config(asr, asr->rb.drivemagic);
+}
+
+/* Make up RAID device name. */
+static size_t _name(struct lib_context *lc, struct asr *asr, char *str,
+	size_t len)
+{
+	struct asr_raid_configline *cl = asr_this_disk(asr);
+	if (cl == NULL)
+		LOG_ERR(lc, 0, "%s: Could not find device in config table!\n",
+			handler);
+	return snprintf(str, len, "asr_%s", cl->name);
+}
+
+/* Figure out a name for the RAID device. */
+static char *asr_name(struct lib_context *lc, struct asr *asr)
+{
+	size_t len;
+	char *ret;
+
+	if ((ret = dbg_malloc((len = _name(lc, asr, NULL, 0) + 1)))) {
+		_name(lc, asr, ret, len);
+		/* Why do we call mk_alpha?  This makes labels like
+		 * "OS-u320-15k" become "OS-udca-bek", which is confusing.
+		 * mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN); */
+	} else
+		log_alloc_err(lc, handler);
+
+	return ret;
+}
+
+/* Mapping of template types to generic types */
+/* FIXME: This needs more examination.  Does HostRAID do linear
+ * combination?  The BIOS implies that it only does RAID 0, 1 and 10.
+ * The emd driver implied support for RAID3/4/5, but dm doesn't
+ * do any of those right now.
+ */
+static struct types types[] = {
+	{ ASR_RAID0,   t_raid0 },
+	{ ASR_RAID1,   t_raid1 },
+	{ ASR_RAIDSPR, t_spare },
+        { 0, t_undef}
+};
+
+/* Map the ASR raid type codes into dmraid type codes. */
+static enum type asr_type(struct asr_raid_configline *cl)
+{
+	return cl ? rd_type(types, (unsigned int)cl->raidtype) : t_undef;
+}
+
+/*
+ * Read an ASR RAID device.  Fields are big endian, so
+ * need to convert them if we're on a LE machine (i386, etc).
+ */
+#define ASR_BLOCK	1
+#define ASR_TABLE	2
+#define ASR_EXTTABLE 	4
+
+#if	BYTE_ORDER == LITTLE_ENDIAN
+
+static void cvt_configline(struct asr_raid_configline *cline)
+{
+	cline->raidcnt		= ntohs(cline->raidcnt);
+	cline->raidseq		= ntohs(cline->raidseq);
+	cline->raidmagic	= ntohl(cline->raidmagic);
+	cline->raidid		= ntohl(cline->raidid);
+	cline->loffset		= ntohl(cline->loffset);
+	cline->lcapcty		= ntohl(cline->lcapcty);
+	cline->strpsize		= ntohs(cline->strpsize);
+	cline->biosInfo		= ntohs(cline->biosInfo);
+	cline->lsu		= ntohl(cline->lsu);
+	cline->blockStorageTid	= ntohs(cline->blockStorageTid);
+	cline->curAppBlock	= ntohl(cline->curAppBlock);
+	cline->appBurstCount	= ntohl(cline->appBurstCount);
+}
+
+static void to_cpu(void *meta, unsigned int cvt) {
+	struct asr *asr = meta;
+	int i;
+
+	if (cvt & ASR_BLOCK) {
+		asr->rb.b0idcode	= ntohl(asr->rb.b0idcode);
+		asr->rb.biosInfo	= ntohs(asr->rb.biosInfo);
+		asr->rb.fstrsvrb	= ntohl(asr->rb.fstrsvrb);
+		asr->rb.svBlockStorageTid
+					= ntohs(asr->rb.svBlockStorageTid);
+		asr->rb.svtid		= ntohs(asr->rb.svtid);
+		asr->rb.drivemagic	= ntohl(asr->rb.drivemagic);
+		asr->rb.fwTestMagic	= ntohl(asr->rb.fwTestMagic);
+		asr->rb.fwTestSeqNum	= ntohl(asr->rb.fwTestSeqNum);
+		asr->rb.smagic		= ntohl(asr->rb.smagic);
+		asr->rb.raidtbl		= ntohl(asr->rb.raidtbl);
+	}
+
+	if (cvt & ASR_TABLE) {
+		asr->rt.ridcode		= ntohl(asr->rt.ridcode);
+		asr->rt.rversion	= ntohl(asr->rt.rversion);
+		asr->rt.maxelm		= ntohs(asr->rt.maxelm);
+		asr->rt.elmcnt		= ntohs(asr->rt.elmcnt);
+		asr->rt.elmsize		= ntohs(asr->rt.elmsize);
+		asr->rt.raidFlags	= ntohl(asr->rt.raidFlags);
+		asr->rt.timestamp	= ntohl(asr->rt.timestamp);
+		asr->rt.rchksum		= ntohs(asr->rt.rchksum);
+		asr->rt.sparedrivemagic	= ntohl(asr->rt.sparedrivemagic);
+		asr->rt.raidmagic	= ntohl(asr->rt.raidmagic);
+		asr->rt.verifyDate	= ntohl(asr->rt.verifyDate);
+		asr->rt.recreateDate	= ntohl(asr->rt.recreateDate);
+
+		/* Convert the first seven config lines */
+		for (i = 0; i < (asr->rt.elmcnt < 7 ? asr->rt.elmcnt : 7); i++) {
+			cvt_configline(&asr->rt.ent[i]);
+		}
+		
+	}
+
+	if (cvt & ASR_EXTTABLE) {
+		for (i = 7; i < asr->rt.elmcnt; i++) {
+			cvt_configline(&asr->rt.ent[i]);
+		}
+	}
+}
+#else
+# define to_cpu(x, y)
+#endif
+
+static int asr_read_extended(struct lib_context *lc, struct dev_info *di,
+	struct asr *asr)
+{
+	unsigned int remaining, i, checksum;
+	int j;
+	uint8_t *ptr;
+
+	log_info(lc, "%s: reading extended data", di->path);
+	
+	/* Read the RAID table. */
+	if (!read_file(lc, handler, di->path, &asr->rt, ASR_DISK_BLOCK_SIZE,
+		(uint64_t)asr->rb.raidtbl * ASR_DISK_BLOCK_SIZE))
+	{
+		LOG_ERR(lc, 0, "%s: Could not read metadata.", handler);
+	}
+
+	/* Convert it */
+	to_cpu(asr, ASR_TABLE);
+	
+	/* Is this ok? */
+	if (asr->rt.ridcode != RVALID2)
+		LOG_ERR(lc, 0, "%s: Invalid magic number in RAID table.",
+			handler);
+
+	/* Have we a valid element count? */
+	if (asr->rt.elmcnt >= asr->rt.maxelm)
+		LOG_ERR(lc, 0, "%s: Invalid RAID config table count.\n",
+			handler);
+
+	/* Is each element the right size? */
+	if (asr->rt.elmsize != sizeof(struct asr_raid_configline))
+		LOG_ERR(lc, 0, "%s: RAID config line is the wrong size.\n",
+			handler);
+
+	/* Figure out how much else we need to read. */
+	if (asr->rt.elmcnt > 7) {
+		remaining = asr->rt.elmsize * (asr->rt.elmcnt - 7);
+		if (!read_file(lc, handler, di->path, &asr->rt.ent[7],
+			remaining,
+			(uint64_t)(asr->rb.raidtbl + 1) * ASR_DISK_BLOCK_SIZE))
+		{
+			return 0;
+		}
+		to_cpu(asr, ASR_EXTTABLE);
+	}
+
+	/* Compute checksum. */
+	ptr = (uint8_t *)asr->rt.ent;
+	checksum = 0;
+	for (i = 0; i < sizeof(asr->rt.ent[0]) * asr->rt.elmcnt; i++) {
+		checksum += ptr[i];
+	}
+	checksum &= 0xFFFF;
+	if (checksum != asr->rt.rchksum)
+		LOG_ERR(lc, 0, "%s: Invalid RAID config table checksum (0x%X vs. 0x%X).\n",
+			handler, checksum, asr->rt.rchksum);
+	
+	/* Process the name of each line of the config line. */
+	for (i = 0; i < asr->rt.elmcnt; i++) {
+		/* 
+		 * Weird quirks of the name field of the config line:
+		 *
+		 * - SATA HostRAID w/ ICH5 on IBM x226: The name field is null
+		 *   in the drive config lines.  The zeroeth item does have a
+		 *   name, however.
+		 * - Spares on SCSI HostRAID on IBM x226: The name field for
+		 *   all config lines is null.
+		 * 
+		 * So, we'll assume that we can copy the name from the zeroeth
+		 * element in the array.  The twisted logic doesn't seem to
+		 * have a problem with either of the above cases, though
+		 * attaching spares is going to be a tad tricky (primarily
+		 * because there doesn't seem to be a way to attach a spare to
+		 * a particular array; presumably the binary driver knows how
+		 * or just grabs a disk out of the spare pool.
+		 *
+		 * This is nuts.
+		 */
+		if (asr->rt.ent[i].name == 0)
+			memcpy(asr->rt.ent[i].name, asr->rt.ent[0].name, 16);
+
+		/* Now truncate trailing whitespace in the name. */
+		for (j = 15; j >= 0; j--) {
+			if (asr->rt.ent[i].name[j] == ' ')
+				asr->rt.ent[i].name[j] = 0;
+		}
+	}
+
+	return 1;
+}
+
+static int is_asr(struct lib_context *lc, struct dev_info *di, void *meta)
+{
+	struct asr *asr = meta;
+
+	/* Check our magic numbers and that the version == v8.
+	 * We don't support anything other than that right now. */
+	if (asr->rb.b0idcode == B0RESRVD && asr->rb.smagic == SVALID) {
+		if (asr->rb.resver == RBLOCK_VER) {
+			return 1;
+		}
+		
+		LOG_ERR(lc, 0, "%s: ASR v%d detected, but we only support v8.\n",
+			handler, asr->rb.resver);
+	}
+
+	return 0;
+}
+
+/*
+ * Attempt to interpret ASR metadata from a block device.  This function
+ * returns either NULL (not an ASR) or a pointer to a descriptor struct.
+ * Note that the struct should be fully converted to the correct endianness
+ * by the time this function returns.
+ *
+ * WARNING: If you take disks out of an ASR HostRAID array and plug them in
+ * to a normal SCSI controller, the array will still show up!  Even if you
+ * scribble over the disks!  I assume that the a320raid binary driver only
+ * does its HostRAID magic if your controller is in RAID mode... but dmraid
+ * lacks this sort of visibility as to where its block devices come from.
+ * This is EXTREMELY DANGEROUS if you aren't careful!
+ */
+static void *asr_read_metadata(struct lib_context *lc, struct dev_info *di,
+			       size_t *sz, uint64_t *offset,
+			       union read_info *info)
+{
+	size_t size = ASR_DISK_BLOCK_SIZE;
+	uint64_t asr_sboffset = ASR_CONFIGOFFSET;
+	struct asr *asr;
+
+	/*
+	 * Read the ASR reserved block on each disk.  This is the very
+	 * last sector of the disk, and we're really only interested in
+	 * the two magic numbers, the version, and the pointer to the
+	 * RAID table.  Everything else appears to be unused in v8.
+	 */
+	asr = alloc_private(lc, handler, sizeof(struct asr));
+	if (!asr) {
+		goto out;
+	}
+
+	if (!read_file(lc, handler, di->path, &asr->rb, size, asr_sboffset))
+		goto bad;
+
+	/*
+	 * Convert metadata and read in 
+	 */
+	to_cpu(asr, ASR_BLOCK);
+
+	/* Check Signature and read optional extended metadata. */
+	if (!is_asr(lc, di, asr) ||
+	    !asr_read_extended(lc, di, asr))
+		goto bad;
+
+	/*
+	 * Now that we made sure that we have all the metadata, we exit.
+	 * XXX: Maybe we should check the disk status?  Does it matter if
+	 * we ignore a s_broken drive?
+	 */
+	goto out;
+   bad:
+	dbg_free(asr);
+	asr = NULL;
+
+   out:
+	return (void*) asr;
+}
+
+/*
+ * "File the metadata areas" -- I think this function is supposed to declare
+ * which parts of the drive are metadata and thus off-limits to dmraid.
+ */
+static void asr_file_metadata(struct lib_context *lc, struct dev_info *di,
+	void *meta)
+{
+	struct asr *asr = meta;
+	
+	/*
+	 * NOTE: We could probably just register the last 17 sectors
+	 * of the drive in one big operation...
+	 */
+
+	/* Register the reserved block. */
+	file_metadata(lc, handler, di->path, &asr->rb, ASR_DISK_BLOCK_SIZE,
+		ASR_CONFIGOFFSET);
+
+	/* Register the raid table. */
+	file_metadata(lc, handler, di->path, &asr->rt, ASR_DISK_BLOCK_SIZE,
+		(uint64_t)asr->rb.raidtbl * ASR_DISK_BLOCK_SIZE);
+
+	/*
+	 * Register the rest of the config table.  We need to register
+	 * all the space (i.e. maxelm), not just what we're using now.
+	 */
+	if (asr->rt.maxelm > 7)
+		file_metadata(lc, handler, di->path, &asr->rt.ent[7],
+			(asr->rt.maxelm-7) * sizeof(struct asr_raid_configline),
+			(uint64_t)(asr->rb.raidtbl+1) * ASR_DISK_BLOCK_SIZE);
+
+
+	/* I have no idea what this does */
+	file_dev_size(lc, handler, di);
+}
+
+static int asr_setup_rd(struct lib_context *lc, struct raid_dev *rd,
+		    struct dev_info *di, void *meta, union read_info *info);
+
+static struct raid_dev *asr_read(struct lib_context *lc,
+					struct dev_info *di)
+{
+	/*
+	 * NOTE: Everything called after asr_read_metadata assumes that
+	 * the reserved block, raid table and config table have been
+	 * converted to the appropriate endianness.
+	 */
+	return read_raid_dev(lc, di, asr_read_metadata, 0, 0, NULL, NULL,
+		asr_file_metadata, asr_setup_rd, handler);
+}
+
+static int no_sort(struct list_head *dont, struct list_head *care)
+{
+	return 0;
+}
+
+/* Sort ASR devices by for a RAID set. */
+static int asr_dev_sort(struct list_head *pos, struct list_head *new)
+{
+	struct asr_raid_configline *p, *n;
+	uint64_t one, two;
+
+	p = asr_this_disk( META(RD(pos), asr) );
+	n = asr_this_disk( META(RD(new), asr) );
+
+	/* Is using a 64-bit id composed of hba:ch:lun:id ok? */
+	one =     ((uint64_t)n->raidhba << 48)
+		| ((uint64_t)n->raidchnl << 40)
+		| ((uint64_t)n->raidlun << 32)
+		| ((uint64_t)n->raidid);
+
+	two =     ((uint64_t)p->raidhba << 48)
+		| ((uint64_t)p->raidchnl << 40)
+		| ((uint64_t)p->raidlun << 32)
+		| ((uint64_t)p->raidid);
+
+	return (one < two);
+}
+
+/*
+ * Find the top-level RAID set for an ASR context.
+ */
+static int asr_find_toplevel(struct lib_context *lc,
+		struct asr *asr)
+{
+	int i, toplevel = -1;
+
+	for (i = 0; i < asr->rt.elmcnt; i++) {
+		if (asr->rt.ent[i].raidlevel == FWL_2)
+		{
+			toplevel = i;
+			break;
+		}
+		else if (asr->rt.ent[i].raidlevel == FWL)
+		{
+			toplevel = i;
+		}
+	}
+	
+	return toplevel;
+}
+
+/*
+ * Find the logical drive configuration that goes with this
+ * physical disk configuration.
+ */
+static struct asr_raid_configline *asr_find_logical(struct asr *asr)
+{
+	int i, j;
+
+	/* This MUST be done backwards! */
+	for (i = asr->rt.elmcnt - 1; i >= 0; i--) {
+		if (asr->rt.ent[i].raidmagic == asr->rb.drivemagic) {
+			for (j = i - 1; j >= 0; j--) {
+				if (asr->rt.ent[j].raidlevel == FWL) {
+					return &asr->rt.ent[j];
+				}
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/* 
+ * Add an ASR device to a RAID set.  Basically, this means that
+ * we have to find the set to which this disk belongs (or create
+ * one if we haven't) and then add this disk to the list if it's
+ * not a spare.
+ *
+ * FIXME: Actually, HostRAID _does_ do multilevel RAID (10).
+ */
+static struct raid_set *asr_group(struct lib_context *lc,
+		struct raid_dev *rd)
+{
+	int top_idx, i;
+	struct raid_set *top_set, *set = NULL, *tmp;
+	struct asr *asr = META(rd, asr);
+	struct asr_raid_configline *cl = asr_this_disk(asr);
+	struct asr_raid_configline *fwl;
+	char inbuf[65], *outbuf;
+
+	/* Can we find a top level raid set? */
+	top_idx = asr_find_toplevel(lc, asr);
+	if (top_idx < 0) {
+		LOG_ERR(lc, NULL, "Can't find a FWL or FWL2 for FWP %x\n",
+			asr->rb.drivemagic);
+	}
+	top_set = find_set(lc, NULL, asr_name(lc, asr), FIND_TOP);
+	if (top_set != NULL) {
+		if (asr->rt.ent[top_idx].raidlevel == FWL_2) {
+			/* double-layered; find the appropriate set */
+			list_for_each_entry(tmp, &top_set->sets, list) {
+				/* find the FWL that goes with the drive. */
+				fwl = asr_find_logical(asr);
+				if (fwl == NULL) {
+					LOG_ERR(lc, NULL,
+					"Can't find a FWL to go with FWP %x\n",
+					asr->rb.drivemagic);
+				}
+				snprintf(inbuf, 64, "asr_%s_%x", fwl->name,
+					fwl->raidmagic);
+				if (strcmp(tmp->name, inbuf) == 0) {
+					set = tmp;
+					break;
+				}
+			}
+		} else {
+			set = top_set;
+		}
+
+		/* now attach it */
+		if (!set) {
+			LOG_ERR(lc, NULL, "No FWL to go with FWP %x\n",
+				asr->rb.drivemagic);
+		}
+		list_add_sorted(lc, &set->devs, &rd->devs, asr_dev_sort);
+
+		return top_set;
+	}
+
+	/* Otherwise, we need to create a new set structure. */
+
+	/* If we're dealing with a single-level array... */
+	if (asr->rt.ent[top_idx].raidlevel == FWL) {
+		top_set = find_or_alloc_raid_set(lc, asr_name(lc, asr),
+			FIND_TOP, rd, LC_RS(lc), NO_CREATE, NO_CREATE_ARG);
+
+		top_set->stride = (cl ? cl->strpsize: 0);
+		top_set->status = s_ok;
+		top_set->type = asr_type(asr_find_logical(asr));
+
+		/* Add the disk to the set. */
+		list_add_sorted(lc, &top_set->devs, &rd->devs, asr_dev_sort);
+		
+		return top_set;
+	}
+
+	/* Nope.  Two-level array. */
+	top_set = find_or_alloc_raid_set(lc, asr_name(lc, asr),
+		FIND_TOP, rd, LC_RS(lc), NO_CREATE, NO_CREATE_ARG);
+	top_set->stride = (cl ? cl->strpsize : 0);
+	top_set->status = s_ok;
+	top_set->type = asr_type(&asr->rt.ent[top_idx]);
+
+	/* Find all FWLs that go with this FWL2 and add them. */
+	for (i = 0; i < asr->rt.elmcnt; i++) {
+		if (asr->rt.ent[i].raidlevel != FWL)
+			continue;
+		if (asr->rt.ent[i].raidcnt == 0)
+			continue;
+
+		outbuf = malloc(32);
+		if (outbuf == NULL) {
+			LOG_ERR(lc, NULL, "Can't allocate array name.\n");
+		}
+		snprintf(outbuf, 64, "asr_%s_%x", asr->rt.ent[i].name,
+			asr->rt.ent[i].raidmagic);
+		set = alloc_raid_set(lc, __func__);
+		if (!set) {
+			LOG_ERR(lc, NULL, "Can't allocate RAID set.\n");
+		}
+
+		set->name = outbuf;
+		set->status = s_ok;
+		set->type = asr_type(asr_find_logical(asr));
+		list_add_sorted(lc, &top_set->sets, &set->list, no_sort);
+
+		/* Add the drive to the set too */
+		fwl = asr_find_logical(asr);
+		if (fwl == NULL) {
+			LOG_ERR(lc, NULL,
+				"Can't find a FWL to go with FWP %x\n",
+				asr->rb.drivemagic);
+		}
+		if (fwl->raidmagic == asr->rt.ent[i].raidmagic) {
+			list_add_sorted(lc, &set->devs, &rd->devs, asr_dev_sort);
+		}
+
+	}
+
+	printf("finished!\n");
+
+	return set;
+}
+
+/* Write metadata. */
+static int asr_write(struct lib_context *lc,
+			  struct raid_dev *rd, int erase)
+{
+	fprintf(stderr, "ERROR: asr_write not implemented!\n");
+	return EPERM;
+}
+
+#if 0
+/* CODEME: Write private RAID metadata to device */
+static int template_write(struct lib_context *lc,
+			  struct raid_dev *rd, int erase)
+{
+	int ret;
+#if	BYTE_ORDER != LITTLE_ENDIAN
+	struct template *template = META(rd, template);
+#endif
+
+	/* CODEME: in case there's more complex metadata areas */
+	to_disk(template);
+	ret = write_metadata(lc, handler, rd, -1, erase);
+	to_cpu(template);
+	return ret;
+}
+#endif
+
+/*
+ * Check integrity of a RAID set.
+ */
+
+/* Retrieve the number of devices that should be in this set. */
+static unsigned int asr_device_count(struct raid_dev *rd, void *context)
+{
+	/* Get the logical drive */
+	struct asr_raid_configline *cl = asr_find_logical(META(rd, asr));
+	return (cl ? cl->raidcnt : 0);
+}
+
+/* Check a RAID device */
+static int asr_check_rd(struct lib_context *lc, struct raid_set *rs,
+		    struct raid_dev *rd, void *context)
+{
+	/* XXX: Assume non-broken means ok. */
+	return (rd->type != s_broken);
+}
+
+/* Start the recursive RAID set check. */
+static int asr_check(struct lib_context *lc, struct raid_set *rs)
+{
+	int f = check_raid_set(lc, rs, asr_device_count, NULL, asr_check_rd,
+		NULL, handler);
+	return f;
+}
+
+/*
+ * IO error event handler.
+ */
+static int event_io(struct lib_context *lc, struct event_io *e_io)
+{
+	LOG_ERR(lc, 0, "An I/O error event occurred.  Now what?\n");
+}
+
+static struct event_handlers asr_event_handlers = {
+	.io = event_io,	/* CODEME: */
+	.rd = NULL,	/* FIXME: no device add/remove event handler yet. */
+};
+
+/* Dump a reserved block */
+static void asr_dump_rb(struct lib_context *lc, struct asr_reservedblock *rb)
+{
+	log_print(lc, "block magic:\t\t0x%X", rb->b0idcode);
+	log_print(lc, "sb0flags:\t\t0x%X", rb->sb0flags);
+	log_print(lc, "jbodEnable:\t\t%d", rb->jbodEnable);
+	log_print(lc, "biosInfo:\t\t0x%X", rb->biosInfo);
+	log_print(lc, "drivemagic:\t\t0x%X", rb->drivemagic);
+	log_print(lc, "svBlockStorageTid:\t0x%X", rb->svBlockStorageTid);
+	log_print(lc, "svtid:\t\t\t0x%X", rb->svtid);
+	log_print(lc, "resver:\t\t\t%d", rb->resver);
+	log_print(lc, "smagic:\t\t\t0x%X", rb->smagic);
+	log_print(lc, "raidtbl @ sector:\t%d", rb->raidtbl);
+}
+
+/* Dump a raid config line */
+static void asr_dump_cl(struct lib_context *lc, struct asr_raid_configline *cl)
+{
+	log_print(lc, "config ID:\t\t0x%X", cl->raidmagic);
+	log_print(lc, "  name:\t\t\t\"%s\"", cl->name);
+	log_print(lc, "  raidcount:\t\t%d", cl->raidcnt);
+	log_print(lc, "  sequence #:\t\t%d", cl->raidseq);
+	log_print(lc, "  level:\t\t%d", cl->raidlevel);
+	log_print(lc, "  type:\t\t\t%d", cl->raidtype);
+	log_print(lc, "  state:\t\t%d", cl->raidstate);
+	log_print(lc, "  flags:\t\t0x%X", cl->flags);
+	log_print(lc, "  refcount:\t\t%d", cl->refcnt);
+	log_print(lc, "  hba:\t\t\t%d", cl->raidhba);
+	log_print(lc, "  channel:\t\t%d", cl->raidchnl);
+	log_print(lc, "  lun:\t\t\t%d", cl->raidlun);
+	log_print(lc, "  id:\t\t\t%d", cl->raidid);
+	log_print(lc, "  offset:\t\t%d", cl->loffset);
+	log_print(lc, "  capacity:\t\t%d", cl->lcapcty);
+	log_print(lc, "  stripe size:\t\t%d KB",
+		cl->strpsize * ASR_DISK_BLOCK_SIZE / 1024);
+	log_print(lc, "  BIOS info:\t\t%d", cl->biosInfo);
+	log_print(lc, "  phys/log lun:\t\t%d", cl->lsu);
+	log_print(lc, "  addedDrives:\t\t%d", cl->addedDrives);
+	log_print(lc, "  appSleepRate:\t\t%d", cl->appSleepRate);
+	log_print(lc, "  blockStorageTid:\t%d", cl->blockStorageTid);
+	log_print(lc, "  curAppBlock:\t\t%d", cl->curAppBlock);
+	log_print(lc, "  appBurstCount:\t%d", cl->appBurstCount);
+}
+
+/* Dump a raid config table */
+static void asr_dump_rt(struct lib_context *lc, struct asr_raidtable *rt)
+{
+	unsigned int i;
+	log_print(lc, "ridcode:\t\t0x%X", rt->ridcode);
+	log_print(lc, "table ver:\t\t%d", rt->rversion);
+	log_print(lc, "max configs:\t\t%d", rt->maxelm);
+	log_print(lc, "configs:\t\t%d", rt->elmcnt);
+	log_print(lc, "config sz:\t\t%d", rt->elmsize);
+	log_print(lc, "checksum:\t\t0x%X", rt->rchksum);
+	log_print(lc, "raid flags:\t\t0x%X", rt->raidFlags);
+	log_print(lc, "timestamp:\t\t0x%X", rt->timestamp);
+	log_print(lc, "irocFlags:\t\t0x%X%s", rt->irocFlags,
+		(rt->irocFlags & ASR_IF_BOOTABLE ? " (bootable)" : ""));
+	log_print(lc, "dirty:\t\t\t%d", rt->dirty);
+	log_print(lc, "action prio:\t\t%d", rt->actionPriority);
+	log_print(lc, "spareid:\t\t%d", rt->spareid);
+	log_print(lc, "sparedrivemagic:\t0x%X", rt->sparedrivemagic);
+	log_print(lc, "raidmagic:\t\t0x%X", rt->raidmagic);
+	log_print(lc, "verifydate:\t\t0x%X", rt->verifyDate);
+	log_print(lc, "recreatedate:\t\t0x%X", rt->recreateDate);
+	log_print(lc, "RAID config table:");
+	for (i = 0; i < rt->elmcnt; i++) {
+		asr_dump_cl(lc, &rt->ent[i]);
+	}
+}
+
+#ifdef DMRAID_NATIVE_LOG
+/*
+ * Log native information about the RAID device.
+ */
+static void asr_log(struct lib_context *lc, struct raid_dev *rd)
+{
+	struct asr *asr = META(rd, asr);
+
+	log_print(lc, "%s (%s):", rd->di->path, handler);
+	asr_dump_rb(lc, &asr->rb);
+	asr_dump_rt(lc, &asr->rt);
+}
+#endif
+
+static struct dmraid_format asr_format = {
+	.name	= HANDLER,
+	.descr	= "Adaptec HostRAID ASR",
+	.caps	= "0,1",
+	.format = FMT_RAID,
+	.read	= asr_read,
+	.write	= asr_write, // FIXME
+	.group	= asr_group,
+	.check	= asr_check,
+	.events	= &asr_event_handlers, // FIXME
+#ifdef DMRAID_NATIVE_LOG
+	.log	= asr_log,
+#endif
+};
+
+/* Register this format handler with the format core */
+int register_asr(struct lib_context *lc)
+{
+	return register_format_handler(lc, &asr_format);
+}
+
+/*
+ * Set up a RAID device from what we've assembled out of the metadata.
+ */
+static int asr_setup_rd(struct lib_context *lc, struct raid_dev *rd,
+		    struct dev_info *di, void *meta, union read_info *info)
+{
+	struct asr *asr = meta;
+	struct meta_areas *ma;
+	struct asr_raid_configline *cl = asr_this_disk(asr);
+
+	if (!cl)
+		LOG_ERR(lc, 0, "%s: Could not find current disk!\n",
+			handler);		
+
+	/* We need three metadata areas */
+	if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 3)))
+		return 0;
+
+	/* First area: reserved block. */
+	ma = rd->meta_areas;
+	ma->offset = ASR_CONFIGOFFSET >> 9;
+	ma->size = ASR_DISK_BLOCK_SIZE;
+	ma->area = (void *)asr;
+
+	/* Second area: raid table. */
+	ma++;
+	ma->offset = asr->rb.raidtbl;
+	ma->size = ASR_DISK_BLOCK_SIZE;
+	ma->area = (void *)asr;
+
+	/* Third area: raid config table. */
+	ma++;
+	ma->offset = asr->rb.raidtbl + 1;
+	ma->size = 15 * ASR_DISK_BLOCK_SIZE;
+	ma->area = (void *)asr;
+
+	/* Now set up the rest of the metadata info */
+        rd->di = di;
+	rd->fmt = &asr_format;
+
+	rd->status = asr_disk_status(cl);
+	rd->type   = asr_type(cl);
+
+	rd->offset = ASR_DATAOFFSET;
+	rd->sectors = cl->lcapcty;
+
+        if ((rd->name = asr_name(lc, asr))) {
+		return 1;
+	}
+
+	return 0;
+}
diff -Naur orig/lib/format/ataraid/asr.h v3-test/lib/format/ataraid/asr.h
--- orig/lib/format/ataraid/asr.h	1969-12-31 16:00:00.000000000 -0800
+++ v3-test/lib/format/ataraid/asr.h	2006-01-10 16:11:23.000000000 -0800
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2005 IBM
+ * 
+ * Copyright (c) 2001, 2002, 2004 Adaptec Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _ASR_H
+#define _ASR_H
+
+/* Stuff that djwong added */
+#ifdef	FORMAT_HANDLER
+#undef	FORMAT_HANDLER
+
+/* ASR metadata offset in bytes */
+#define	ASR_CONFIGOFFSET	((di->sectors - 1) << 9)
+
+/* Data offset in sectors */
+#define	ASR_DATAOFFSET		0
+
+/* Assume block size is 512.  So much for CD dmraid... */
+#define ASR_DISK_BLOCK_SIZE	512
+
+/* Copied verbatim from Adaptec's emd driver. */
+
+/*
+ * This is a metadata versioning mechanism, but rather a versioning
+ * mechansim for Adaptec-sponsored changes to md.  (i.e. more of a driver
+ * version)
+ */
+#define	MD_ADAPTEC_MAJOR_VERSION	0
+#define	MD_ADAPTEC_MINOR_VERSION	0
+#define	MD_ADAPTEC_PATCHLEVEL_VERSION	13
+
+#define FW_RESERVED_BLOCKS  0x800
+
+#define MAX_SLEEPRATE_ENTRIES 10
+
+/* define lsu levels */
+#define LSU_LEVEL_PHYSICAL	1	/* Firmware Physical */
+#define LSU_LEVEL_LOGICAL	2	/* Firmware Logical */
+
+/* define RAID drive substates */
+#define FWP		0	/* Firmware Physical */
+#define FWL		1	/* Firmware Logical */
+#define OSI		2	/* Operating System Intermediate */
+#define FWL_2		3	/* Dual Level */
+
+#define ASR_RAID0		0
+#define ASR_RAID1		1
+#define ASR_RAID4		4
+#define ASR_RAID5		5
+#define ASR_RAIDRED		0xFF
+#define ASR_RAIDSPR		0xFE
+
+/*** RAID CONFIGURATION TABLE STRUCTURE ***/
+
+#define RVALID2			0x900765C4   /* Version 2+ RAID table ID code
+						signature */
+#define RCTBL_MAX_ENTRIES	127
+#define HBA_RCTBL_MAX_ENTRIES	255
+#define RTBLBLOCKS		16	     /* Size of drive's raid table
+						in blocks */
+
+/* flag bits */
+#define RCTBLCHNG					0x80	/* Set on comp OR log (NOT AND) if tbl updates needed */
+#define	COPYDIR						0x40
+#define	MIRCOPY						0x20
+#define INITIAL_BUILD_COMPLETED				0x10
+#define SMART_DISABLED					0x08
+#define WRITEBACK					0x04
+#define PREDICTIVE_ENABLE				0x02
+#define RAID_ENTRY_FLAGS_ALARM_OFF_M			0x01
+
+struct asr_raid_configline
+{
+	uint16_t	raidcnt;    /* Component count of an OSL/FWL array */
+	uint16_t	raidseq;    /* Sequence # of component to look for */
+	uint32_t	raidmagic;  /* Magic # of component to look for */
+	uint8_t		raidlevel;  /* Array level = OSL/FWL/OSI/FWP */
+	uint8_t		raidtype;   /* Array type = RAID0/1/3/5, RAIDRED,
+				       RAIDSPR */
+	uint8_t		raidstate;  /* State of logical or physical drive */
+
+	uint8_t		flags;      /* misc flags set bit positions above */
+
+	uint8_t		refcnt;     /* Number of references to this log entry */
+	uint8_t		raidhba;    /* -- not used -- Host bus adapter number
+				       or RAIDID */
+	uint8_t		raidchnl;   /* Channel number */
+	uint8_t		raidlun;    /* SCSI LUN of log/phys drv */
+	uint32_t	raidid;     /* SCSI ID of log/phys drv */
+	uint32_t	loffset;    /* Offset of data for this comp in the
+				       array */
+	uint32_t	lcapcty;    /* Capacity of log drv or space used on
+				       phys */
+	uint16_t	strpsize;   /* Stripe size in blocks of this drive */
+	uint16_t	biosInfo;   /* bios info - set by
+				       I2O_EXEC_BIOS_INFO_SET */
+	uint32_t	lsu;        /* Pointer to phys/log lun of this entry */
+	uint8_t		addedDrives;
+	uint8_t		appSleepRate;
+	uint16_t	blockStorageTid;
+	uint32_t	curAppBlock;
+	uint32_t	appBurstCount;
+	uint8_t		name[16];   /* Full name of the array. */
+} __attribute__ ((packed));
+
+struct asr_raidtable
+{
+/* raid Flag defines 32 bits 0 - FFFFFFFF */
+#define RAID_FLAGS_ALARM_OFF_M 0x00000001
+	uint32_t	ridcode;	/* RAID table signature - 0x900765C4 */
+	uint32_t	rversion;	/* Version of the RAID config table */
+	uint16_t	maxelm;		/* Maximum number of elements */
+	uint16_t	elmcnt;		/* Element Count (number used) */
+	uint16_t	elmsize;	/* Size of an individual raidCLine */
+	uint16_t	rchksum;	/* RAID table check sum
+					   (no rconfTblV2)*/
+	uint32_t	res1;		/* Reserved */
+	uint16_t	res2;		/* was bldRate - Time in 1/10s
+					   between idle build bursts */
+	uint16_t	res3;		/* was bldAmount - Block to build
+					   during a build burst */
+	uint32_t	raidFlags;
+	uint32_t	timestamp;	/* used for iROC. A stamp to find
+					   which is latest */
+	uint8_t		irocFlags;
+#define	ASR_IF_VERIFY_WITH_AUTOFIX	0x01
+#define ASR_IF_BOOTABLE			0x80
+	uint8_t		dirty;		/* Records "open state" for array */
+#define ARRAY_STATE_OK		0x00
+#define ARRAY_STATE_DIRTY	0x03
+	uint8_t		actionPriority;
+	uint8_t		spareid;	/* Stored in member disk meta data
+					   to declare the ID of dedicated
+					   spare to show up. */
+	uint32_t	sparedrivemagic;/* drivemagic (in RB) of the spare
+					   at above ID. */
+	uint32_t	raidmagic;	/* used to identify spare drive with
+					   its mirror set. */
+	uint32_t 	verifyDate;	/* used by iomgr */
+	uint32_t	recreateDate;	/* used by iomgr */
+	uint8_t		res4[12];	/* Reserved */
+	struct asr_raid_configline ent[RCTBL_MAX_ENTRIES];
+} __attribute__ ((packed));
+
+
+#define RBLOCK_VER  8           /* Version of the reserved block */
+#define B0RESRVD    0x37FC4D1E  /* Signature of the reserved block */
+#define SVALID      0x4450544D  /* ASCII code for "DPTM" DPT Mirror */
+
+struct asr_reservedblock
+{
+	uint32_t	b0idcode;	/* 0x00 - ID code signifying block 0
+					   reserved */
+	uint8_t		lunsave[8];	/* 0x04 - NOT USED - LUN mappings for
+					   all drives */
+	uint16_t	sdtype;		/* 0x0C - NOT USED - drive type in
+					   boot prom */
+	uint16_t	ssavecyl;	/* 0x0E - NOT USED - Set Parameters
+					   cylinders */
+	uint8_t		ssavehed;	/* 0x10 - NOT USED - Set Parameters
+					   heads */
+	uint8_t		ssavesec;	/* 0x11 - NOT USED - Set Parameters
+					   sectors */
+	uint8_t		sb0flags;	/* 0x12 - flags saved in reserved
+					   block */
+	uint8_t		jbodEnable;	/* 0x13 - jbod enable -- DEC drive
+					   hiding */
+	uint8_t		lundsave;	/* 0x14 - NOT USED - LUNMAP disable
+					   flags */
+	uint8_t		svpdirty;	/* 0x15 - NOT USED - saved percentage
+					   dirty */
+	uint16_t	biosInfo;	/* 0x16 - bios info - set by
+					   I2O_EXEC_BIOS_INFO_SET */
+	uint16_t	svwbskip;	/* 0x18 - NOT USED - saved write-back
+					   skip value */
+	uint16_t	svwbcln;	/* 0x1A - NOT USED - saved maximum
+					   clean blocks in write-back */
+	uint16_t	svwbmax;	/* 0x1C - NOT USED - saved maximum
+					   write-back length */
+	uint16_t	res3;		/* 0x1E - unused (was write-back burst
+					   block count) */
+	uint16_t	svwbmin;	/* 0x20 - NOT USED - saved minimum
+					   block count to write */
+	uint16_t	res4;		/* 0x22 - unused (was minimum
+					   look-ahead length) */
+	uint16_t	svrcacth;	/* 0x24 - NOT USED - saved read cache
+					   threshold */
+	uint16_t	svwcacth;	/* 0x26 - NOT USED - saved write
+					    cache threshold */
+	uint16_t	svwbdly;	/* 0x28 - NOT USED - saved write-back
+					   delay */
+	uint8_t		svsdtime;	/* 0x2A - NOT USED - saved spin down
+					   time */
+	uint8_t		res5;		/* 0x2B - unused */
+	uint16_t	firmval;	/* 0x2C - NOT USED - firmware on
+					   drive  (dw) */
+	uint16_t	firmbln;	/* 0x2E - NOT USED - length in blocks
+					   for firmware */
+	uint32_t	firmblk;	/* 0x30 - NOT USED - starting block
+					   for firmware */
+	uint32_t	fstrsvrb;	/* 0x34 - 1st block reserved by
+					   Storage Manager */
+	uint16_t	svBlockStorageTid;	/* 0x38 - */
+	uint16_t	svtid;		/* 0x3A - */
+	uint8_t		svseccfl;	/* 0x3C - NOT USED - reserved block
+					   scsi bus ecc flags */
+	uint8_t		res6;		/* 0x3D - unused */
+	uint8_t		svhbanum;	/* 0x3E - NOT USED - HBA's unique
+					   RAID number */
+	uint8_t		resver;		/* 0x3F - reserved block version
+					   number */
+	uint32_t	drivemagic;	/* 0x40 - Magic number of this drive -
+					   used w/ RCTBLs */
+	uint8_t		reserved[20];	/* 0x44 - unused */
+	uint8_t		testnum;	/* 0x58 - NOT USED - diagnostic test
+					   number */
+	uint8_t		testflags;	/* 0x59 - NOT USED - diagnostic test
+					   flags */
+	uint16_t	maxErrorCount;	/* 0x5A - NOT USED - diagnostic test
+					   maximum error count */
+	uint32_t	count;		/* 0x5C - NOT USED - diagnostic test
+					   cycles - # of iterations */
+	uint32_t	startTime;	/* 0x60 - NOT USED - diagnostic test
+					   absolute test start time in
+					   seconds */
+	uint32_t	interval;	/* 0x64 - NOT USED - diagnostic test
+					   interval in seconds */
+	uint8_t		tstxt0;		/* 0x68 - not used - originally
+					   diagnostic test exclusion period
+					   start hour */
+	uint8_t		tstxt1;		/* 0x69 - not used - originally
+					   diagnostic test exclusion period
+					   end hour */
+	uint8_t		serNum[32];	/* 0x6A - reserved */
+	uint8_t		res8[102];	/* 0x8A - reserved */
+	uint32_t	fwTestMagic;	/* 0xF0 - test magic number - used by
+					   FW Test for automated tests */
+	uint32_t	fwTestSeqNum;	/* 0xF4 - test sequence number - used
+					   by FW Test for automated tests */
+	uint8_t		fwTestRes[8];	/* 0xF6 - reserved by FW Test for
+					   automated tests */
+	uint32_t	smagic;		/* 0x100 - magic value saying software
+					   half is valid */
+	uint32_t	raidtbl;	/* 0x104 - pointer to first block of
+					   raid table */
+	uint16_t	raidline;	/* 0x108 - line number of this raid
+					   table entry - only if version <7 */
+	uint8_t		res9[0xF6];	/* 0x10A - reserved for software stuff*/
+} __attribute__ ((packed));
+
+
+
+#define ARRAY_NEW       0x00
+#define ARRAY_EQUAL     0x01
+#define ARRAY_SEQ_LESS  0x02
+#define ARRAY_SEQ_GREAT 0x03
+
+#define LOCK_PRIORITY      10	/* Uses 10, 11, 12 - For all three channels */
+
+
+/* B0FLAGS flag bits: */
+
+#define SMARTENA		7	/* SMART emulation enabled */
+#define CLRERROR		4	/* Clear stage of Interpret Format
+					   not completed */
+#define FMTERROR		3	/* Format stage of Interpret Format
+					   not completed */
+#define WRTTHRU			2	/* write throughs */
+#define CACHEDIS		0	/* cache disable bit */
+#define PREDICTIVE_ENABLE	0x02
+
+#define ID_MAP_PHYSICAL_M	1	/* Logical Map Physical */
+#define ID_MAP_LOGICAL_M	2	/* Either Dual Level or Single Level
+					   Logical*/
+
+#define MAX_LSU_COUNT			256
+
+#define MAX_LSU_COMPONENTS		64
+#define MAX_LSU_INQUIRY_DATA		64
+#define MAX_LSU_SERIAL_NUMBER		8
+#define STD_INQUIRY_SIZE		48
+
+#define MAX_LSU_BAD_BLOCKS		8
+
+/* lsuType definitions */
+#define LT_UNCONFIGURED_M		0x00
+#define LT_RAID0_M			0x01
+#define LT_RAID1_M			0x02
+#define LT_RAID3_M			0x08
+#define LT_RAID4_M			0x10
+#define LT_RAID5_M			0x20
+#define LT_REDIR_M			0x40
+#define LT_SPARE_M			0x80
+
+#define	LSU_RAID_LEVEL_0		LT_RAID0_M
+#define	LSU_RAID_LEVEL_1		LT_RAID1_M
+#define	LSU_RAID_LEVEL_3		LT_RAID3_M
+#define	LSU_RAID_LEVEL_4		LT_RAID4_M
+#define	LSU_RAID_LEVEL_5		LT_RAID5_M
+#define LSU_RAID_REDIRECT		LT_REDIR_M
+#define	LSU_RAID_SPARE			LT_SPARE_M
+
+/* raidState definitions */
+#define LS_OPTIMAL_M			0x00
+#define LS_DEGRADED_M			0x01
+#define LS_REBUILDING_M			0x02
+#define LS_MORPHING_M			0x03
+#define LS_DEAD_M			0x04
+#define LS_WARNING_M			0x05
+
+#define LS_VERIFYING_M			0x0A
+#define LSU_ARRAY_SUBSTATE_WITH_FIX	0x10
+
+#define LS_BUILDING_M			0x0B
+#define LS_CREATED_M			0x54
+#define LS_DIAGNOSING_M			0xFD
+
+
+/* arrayState definitions */
+#define LSU_ARRAY_STATE_OPTIMAL			0x00
+#define LSU_ARRAY_STATE_DEGRADED		0x01
+/* etc. */
+
+/* component raidState definitions */
+#define MAIN_STATE				0x0F
+#define LSU_COMPONENT_STATE_OPTIMAL		0x00
+#define LSU_COMPONENT_STATE_DEGRADED		0x01
+#define LSU_COMPONENT_STATE_UNCONFIGURED	0x02
+#define LSU_COMPONENT_STATE_FAILED		0x03
+#define LSU_COMPONENT_STATE_REPLACED		0x04
+#define LSU_COMPONENT_STATE_UNINITIALIZED	0x0A
+
+#define LSU_COMPONENT_SUBSTATE_BUILDING		0x10  /* drive is being built
+							 for first time */
+#define LSU_COMPONENT_SUBSTATE_REBUILDING	0x20  /* drive is being
+							 rebuilt */
+#define LSU_ARRAY_SUBSTATE_AWAIT_FORMAT		0x50
+/* etc. */
+
+/* Everything after here also added by djwong */
+
+struct asr {
+	struct asr_reservedblock rb;
+	struct asr_raidtable rt;
+};
+
+#endif /* FORMAT_HANDLER */
+
+int register_asr(struct lib_context *lc);
+
+#endif /* _ASR_H */
diff -Naur orig/lib/format/ondisk.h v3-test/lib/format/ondisk.h
--- orig/lib/format/ondisk.h	2005-12-06 16:30:04.000000000 -0800
+++ v3-test/lib/format/ondisk.h	2006-01-10 16:11:23.000000000 -0800
@@ -16,6 +16,7 @@
 #include "ataraid/pdc.h"
 #include "ataraid/via.h"
 #include "ataraid/sil.h"
+#include "ataraid/asr.h"
 
 #include "partition/dos.h"
 
diff -Naur orig/lib/format/register.h v3-test/lib/format/register.h
--- orig/lib/format/register.h	2005-12-06 16:30:04.000000000 -0800
+++ v3-test/lib/format/register.h	2006-01-10 16:11:23.000000000 -0800
@@ -23,6 +23,7 @@
 	xx(pdc)
 	xx(sil)
 	xx(via)
+	xx(asr)
 
 	/* DOS partition type handler. */
 	xx(dos)
diff -Naur orig/lib/Makefile.in v3-test/lib/Makefile.in
--- orig/lib/Makefile.in	2005-12-06 16:30:05.000000000 -0800
+++ v3-test/lib/Makefile.in	2006-01-10 16:11:23.000000000 -0800
@@ -33,6 +33,7 @@
 	format/ataraid/pdc.c \
 	format/ataraid/sil.c \
 	format/ataraid/via.c \
+	format/ataraid/asr.c \
 	format/partition/dos.c
 
 OBJECTS=$(SOURCES:%.c=%.o)

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________

Ataraid-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/ataraid-list

[Index of Archives]     [Linux RAID]     [Linux Device Mapper]     [Linux IDE]     [Linux SCSI]     [Kernel]     [Linux Books]     [Linux Admin]     [GFS]     [RPM]     [Yosemite Campgrounds]     [AMD 64]

  Powered by Linux