Re: Sil 3114 SATA RAID

From: Saulius Menkevicius <bob_at_nulis.lt>
Date: Tue, 21 Sep 2004 11:30:37 +0300
David O'Brien wrote:

>On Mon, Sep 20, 2004 at 03:48:55PM +0200, Jiri Mikulas wrote:
>  
>
>>Hello
>>    
>>
>
>Hello, please don't cross-post.  It is appropiate to only pick one to
>email this to.
>
>  
>
>>I have Epox *EP-8HDA3+* motherboard
>>    
>>
>... 
>  
>
>>atapci0: <SiI 3114 SATA150 controller> port 
>>    
>>
>..
>  
>
>>Is it known bug, or anything else (my fault)?
>>    
>>
>
>The FreeBSD ATA-RAID driver does not reconize a raid created in the
>SiI3114 BIOS either, so it is known there is a new RAID meta data format.
>I've sent a copy of my RAID1 meta data to SOS to take a look at.
>
>  
>
BTW I have a patch for ata-raid.[c|h] to support the intel ICH5 raid 
metadata format too. It was written by Doug Abrisko and I adopted to 
-current. Any chance to take it in?

diff -Nru /usr/src/sys/dev/ata/ata-raid.c src/sys/dev/ata/ata-raid.c
--- /usr/src/sys/dev/ata/ata-raid.c	Mon Aug  9 17:22:58 2004
+++ src/sys/dev/ata/ata-raid.c	Fri Aug 27 21:58:46 2004
_at__at_ -71,6 +71,8 _at__at_
 static int ar_lsi_write_conf(struct ar_softc *);
 static int ar_promise_read_conf(struct ad_softc *, struct ar_softc **, int);
 static int ar_promise_write_conf(struct ar_softc *);
+static int ar_intel_read_conf(struct ad_softc *, struct ar_softc **);
+static int ar_intel_write_conf(struct ar_softc *);
 static int ar_rw(struct ad_softc *, u_int32_t, int, caddr_t, int);
 static struct ata_device *ar_locate_disk(int);
 static void ar_print_conf(struct ar_softc *);
_at__at_ -126,6 +128,9 _at__at_
     case ATA_SILICON_IMAGE_ID:
 	return (ar_lsi_read_conf(adp, ar_table));
 
+    case ATA_INTEL_ID:
+	return (ar_intel_read_conf(adp, ar_table));
+
     default:
 	return (ar_promise_read_conf(adp, ar_table, 1));
     }
_at__at_ -336,6 +341,12 _at__at_
 		    AD_SOFTC(rdp->disks[disk])->total_secs - 4208; /* SOS */
 		break;
 
+	    case ATA_INTEL_ID:
+		ctlr |= AR_F_INTEL_RAID;
+		rdp->disks[disk].disk_sectors =
+			I_LBA(AD_SOFTC(rdp->disks[disk])) - 430; /* SOS */
+		break;
+
 	    default:
 		ctlr |= AR_F_FREEBSD_RAID;
 		/* FALLTHROUGH */
_at__at_ -348,11 +359,14 _at__at_
 	    }
 
 	    if ((rdp->flags & 
-		 (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID)) &&
+		 (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID
+		  	| AR_F_INTEL_RAID)) &&
 		(rdp->flags & 
-		 (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID)) !=
+		 (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID
+		  	| AR_F_INTEL_RAID)) !=
 		(ctlr &
-		 (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID))) {
+		 (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID
+		  	| AR_F_INTEL_RAID))) {
 		free(rdp, M_AR);
 		return EXDEV;
 	    }
_at__at_ -417,6 +431,8 _at__at_
 	    rdp->interleave = min(max(2, 1 << bit), 4096);
 	if (rdp->flags & AR_F_PROMISE_RAID)
 	    rdp->interleave = min(max(2, 1 << bit), 2048);
+	if (rdp->flags & AR_F_INTEL_RAID)
+	    rdp->interleave = min(max(2, 1 << bit), 256);
     }
     rdp->total_disks = total_disks;
     rdp->width = total_disks / ((rdp->flags & AR_F_RAID1) ? 2 : 1);	
_at__at_ -432,6 +448,11 _at__at_
 	rdp->offset = HPT_LBA + 1;
 	rdp->reserved = HPT_LBA + 1;
     }
+    if (rdp->flags & AR_F_INTEL_RAID) {
+	rdp->offset = 0;
+	rdp->reserved = 63;
+	rdp->total_sectors = (rdp->total_sectors / 512) * 512;
+    }
     rdp->lock_start = rdp->lock_end = 0xffffffff;
     rdp->flags |= AR_F_READY;
 
_at__at_ -479,6 +500,8 _at__at_
 	ar_lsi_write_conf(rdp);
     if (rdp->flags & AR_F_PROMISE_RAID)
 	ar_promise_write_conf(rdp);
+    if (rdp->flags & AR_F_INTEL_RAID)
+	ar_intel_write_conf(rdp);
 
     disk_destroy(rdp->disk);
     free(rdp, M_AR);
_at__at_ -1005,6 +1028,8 _at__at_
 	    ar_lsi_write_conf(rdp);
 	if (rdp->flags & AR_F_PROMISE_RAID)
 	    ar_promise_write_conf(rdp);
+	if (rdp->flags & AR_F_INTEL_RAID)
+	    ar_intel_write_conf(rdp);
     }
 }
 
_at__at_ -1156,7 +1181,7 _at__at_
 	    }
 	}
 	raid = raidp[array];
-	if (raid->flags & (AR_F_PROMISE_RAID | AR_F_LSI_RAID))
+	if (raid->flags & (AR_F_PROMISE_RAID | AR_F_LSI_RAID | AR_F_INTEL_RAID))
 	    continue;
 
 	switch (info->type) {
_at__at_ -1386,7 +1411,8 _at__at_
 	}
 	raid = raidp[array + info->raid_number];
 
-	if (raid->flags & (AR_F_PROMISE_RAID | AR_F_HIGHPOINT_RAID))
+	if (raid->flags & (AR_F_PROMISE_RAID | AR_F_HIGHPOINT_RAID
+							| AR_F_INTEL_RAID))
 	    continue;
 
 	if (raid->magic_0 && 
_at__at_ -1622,7 +1648,7 _at__at_
 	    }
 	}
 	raid = raidp[array];
-	if (raid->flags & (AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID))
+	if (raid->flags & (AR_F_LSI_RAID | AR_F_HIGHPOINT_RAID | AR_F_INTEL_RAID))
 	    continue;
 
 	magic = (pci_get_device(device_get_parent(
_at__at_ -1860,6 +1886,405 _at__at_
     return 0;
 }
 
+static int
+ar_intel_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
+{
+    struct intel_raid_conf *info;
+    struct intel_raid_config *config;
+    struct ar_softc *raid = NULL;
+    int array, disk = 0, retval = 0, size = 1024, i, matched = -1;
+    u_int32_t count, cksum, cksum_orig, *ckptr;
+
+    if (!(info = (struct intel_raid_conf *)
+	  malloc(size, M_AR, M_NOWAIT | M_ZERO)))
+	return retval;
+
+    if (ar_rw(adp, I_LBA(adp), size,
+	      (caddr_t)info, AR_READ | AR_WAIT)) {
+	if (bootverbose)
+	    printf("ar: Intel read conf failed\n");
+	goto intel_out;
+    }
+
+    /* check if this is a Intel RAID struct */
+    if (bcmp(info->intel_id, I_MAGIC, sizeof(I_MAGIC) - 1)) {
+	if (bootverbose)
+	    printf("ar: Intel check1 failed\n");
+	goto intel_out;
+    }
+
+#if 0
+    printf("%s\n", info->intel_id);
+    printf("checksum %d\n",info->checksum);
+#endif
+
+    ckptr = (void *)info;
+    cksum_orig = info->checksum;
+    info->checksum = 0;
+    for (cksum = 0, count = 0; count < info->disk_struct_size / 4; count++)
+	cksum += *ckptr++;
+
+#if 0
+    printf("calculated checksum %d\n",cksum);
+#endif
+
+    if (cksum != cksum_orig) {
+	if (bootverbose)
+	    printf("ar: Intel checksum failed\n");
+	goto intel_out;
+    }
+
+#if 0
+    printf("disk_struct_size %d\n",info->disk_struct_size);
+    printf("id %d\n",info->id);
+    printf("generation %d\n",info->generation);
+    printf("reserved[0] %d\n",info->reserved[0]);
+    printf("reserved[1] %d\n",info->reserved[1]);
+    printf("total_disks %d\n",info->total_disks);
+    printf("bootable %d\n",info->bootable);
+#endif
+
+    for (i=0; i < info->total_disks; i++) {
+#if 0
+	printf("serial %s\n",info->disk[i].serial);
+	printf("total_sectors %d\n",info->disk[i].total_sectors);
+	printf("unit_id %d\n",info->disk[i].unit_id);
+	printf("status %d\n",info->disk[i].status);
+#endif
+	if (strncmp(info->disk[i].serial, adp->device->param->serial,
+	     sizeof(adp->device->param->serial)) == 0) {
+	   matched = i;
+	}
+    }
+
+    config = (struct intel_raid_config*)&info->disk[info->total_disks];
+#if 0
+    printf("volume serial %s\n", config->serial);
+    printf("volume total_sectors_low %d\n", config->total_sectors_low);
+    printf("volume total_sectors_high %d\n", config->total_sectors_high);
+    printf("volume status %d\n", config->status);
+    printf("volume migrating %d\n", config->volume.migrating);
+    printf("volume state %d\n", config->volume.state);
+    printf("volume dirty %d\n", config->volume.dirty);
+
+    printf("map start %d\n", config->map.start);
+    printf("map total_sectors %d\n", config->map.total_sectors);
+    printf("map stripes %d\n", config->map.stripes);
+    printf("map interleave %d\n", config->map.interleave);
+    printf("map state %d\n", config->map.state);
+    printf("map type %d\n", config->map.type);
+    printf("map total_disks %d\n", config->map.total_disks);
+    for(i=0; i < config->map.total_disks; i++){
+	printf("Disk %d %d\n", i, config->map.disk_order[i]);
+    }
+#endif
+
+    if (matched == -1) {
+	if (bootverbose)
+	    printf("ar: Intel couldn't match drive to config\n");
+	goto intel_out;
+    }
+
+    for (array = 0; array < MAX_ARRAYS; array++) {
+	if (!raidp[array]) {
+	    raidp[array] =
+		(struct ar_softc*)malloc(sizeof(struct ar_softc), M_AR,
+				     M_NOWAIT | M_ZERO);
+	    if (!raidp[array]) {
+		printf("ar%d: failed to allocate raid config storage\n", array);
+		goto intel_out;
+		raid->flags |= AR_F_DEGRADED;
+	    }
+	}
+	raid = raidp[array];
+	if (raid->flags & (AR_F_HIGHPOINT_RAID | AR_F_PROMISE_RAID
+							| AR_F_LSI_RAID))
+	    continue;
+	if ((raid->flags & AR_F_INTEL_RAID) && raid->magic_0 != info->id)
+	    continue;
+
+	raid->magic_0 = info->id;
+
+/*printf("HELLO gen %d %d\n",info->generation, raid->generation); */
+
+	if (!info->generation || info->generation > raid->generation) {
+	    raid->generation = info->generation;
+	    raid->flags = AR_F_INTEL_RAID;
+	    raid->lun = array;
+#if 0
+	    switch (config->volume.state) {
+#if 0
+	    case I_VOLUME_DISABLED:
+		raid->flags |= AR_F_DEGRADED;
+		break;
+	    case I_VOLUME_DEGRADED:
+		raid->flags |= AR_F_DEGRADED;
+		break;
+	    case I_VOLUME_FAILED:
+		raid->flags |= AR_F_DEGRADED;
+		break;
+#endif
+	    default:
+		/* printf("Unknown Intel Volume state %x\n", config->volume.state); */
+	    }
+#endif
+
+	    switch (config->map.state) {
+	    case I_MAP_OKAY:
+		raid->flags |= AR_F_READY;
+		break;
+	    case I_MAP_DEGRADED:
+		raid->flags |= AR_F_DEGRADED;
+	    case I_MAP_FAILED:
+		raid->flags |= AR_F_DEGRADED;
+		i = config->map.filler1[1];
+		if (i == 0xff) {
+		    printf("INTEL BOGUS drive failed\n");
+		} else {
+		    if (raid->disks[i].flags & AR_DF_ONLINE) {
+		        raid->disks[i].flags &= ~AR_DF_ONLINE;
+		    }
+		    raid->disks[i].flags |= AR_DF_SPARE;
+		}
+		break;
+	    default:
+		printf("Unkown Intel Map state %x\n", config->map.state);
+	    }
+
+	    switch (config->map.type) {
+	    case I_MAP_RAID0:
+		raid->flags |= AR_F_RAID0;
+	    	break;
+
+	    case I_MAP_RAID1:
+		raid->flags |= AR_F_RAID1;
+	    	break;
+
+	    default:
+		printf("ar%d: Intel unknown RAID type 0x%02x\n", array,
+		    config->map.type);
+		goto intel_out;
+	    }
+	    raid->width = config->map.total_disks 
+		/ ((raid->flags & AR_F_RAID1) ? 2 : 1);
+	    raid->interleave = config->map.interleave;
+	    raid->total_disks = config->map.total_disks;
+
+            raid->heads = 255;
+            raid->sectors = 63;
+            raid->cylinders = config->total_sectors_low / (63 * 255);
+            raid->total_sectors = config->total_sectors_low;
+            raid->offset = 0;
+            raid->reserved = 63;
+            raid->lock_start = raid->lock_end = 0;
+
+	    for (disk = 0; disk < config->map.total_disks; disk++) {
+		if (info->disk[disk].status & I_DISK_SPARE) {
+		    raid->disks[disk].flags |= AR_DF_SPARE;
+		}
+		if (info->disk[disk].status & I_DISK_CONFIGURED) { 
+		    raid->disks[disk].flags |= AR_DF_ASSIGNED; /*normally set*/
+		}
+		if (info->disk[disk].status & I_DISK_FAILED) {
+		    raid->disks[disk].flags |= AR_DF_SPARE;
+		}
+		if (info->disk[disk].status & I_DISK_USABLE) {
+		    if (!(raid->disks[disk].flags & AR_DF_SPARE)) {
+			raid->disks[disk].flags |= AR_DF_ONLINE; /* normally set */
+		    }
+		}
+	    }
+	}
+
+	if (info->generation == raid->generation
+	    && !raid->disks[matched].device) {
+	    disk = matched;
+	    raid->disks[disk].flags |= (AR_DF_PRESENT | AR_DF_SPARE);
+	    raid->disks[disk].device = adp->device;
+	    raid->disks[disk].disk_sectors =
+		info->disk[disk].total_sectors;
+	    AD_SOFTC(raid->disks[disk])->flags |= AD_F_RAID_SUBDISK;
+	}
+	if (info->generation < raid->generation) {
+/*printf("HELLO Generation was old\n"); */
+	    disk = matched;
+	    raid->disks[disk].flags = AR_DF_PRESENT | AR_DF_SPARE;
+	    raid->disks[disk].device = adp->device;
+	    raid->disks[disk].disk_sectors =
+		info->disk[disk].total_sectors;
+	    AD_SOFTC(raid->disks[disk])->flags |= AD_F_RAID_SUBDISK;
+	}
+
+	for (count = 0, disk = 0; disk < config->map.total_disks; disk++) {
+	    if (raid->disks[disk].device)
+		count++; 
+	}
+
+#define GEN_MARGIN 15
+#define GEN_MAX 0x80000000
+#define GEN_OVERFLOW(x) ((x + GEN_MARGIN < 0))
+
+	if (count == raid->total_disks 
+	    && GEN_OVERFLOW(raid->generation))
+	    ar_intel_write_conf(raid);
+	if (count == raid->total_disks && (raid->flags & AR_F_DEGRADED))
+		ata_raid_rebuild(array);
+
+	break;
+    }
+
+intel_out:
+    free(info, M_AR);
+
+    return retval;
+}
+
+static int
+ar_intel_write_conf(struct ar_softc *raid)
+{
+    struct intel_raid_conf *info;
+    struct intel_raid_config *config;
+    struct timeval timestamp;
+    u_int32_t cksum, *ckptr;
+    int count, disk, i;
+
+    raid->generation++;
+    if (GEN_OVERFLOW(raid->generation))	/* give us some margin */
+	raid->generation = 1;		/* roll generation */
+    microtime(&timestamp);
+
+    for (disk = 0; disk < raid->total_disks; disk++) {
+	if (!(info = (struct intel_raid_conf *)
+	    malloc(1024, M_AR, M_NOWAIT))) {
+	    printf("ar%d: Intel allocating conf failed\n",
+	    raid->lun);
+	    return -1;
+	}
+	bzero(info, 1024);
+
+	/* need to build critical parts of structure */
+	info->total_disks = raid->total_disks;
+	config = (struct intel_raid_config*)&info->disk[info->total_disks];
+	if (raid->flags & AR_F_RAID0)
+	    config->map.type = I_MAP_RAID0;
+	if (raid->flags & AR_F_RAID1)
+	    config->map.type = I_MAP_RAID1;
+
+	/* start to fill in */
+	snprintf(info->intel_id, sizeof(info->intel_id), "%s 1.%d.00",
+	    I_MAGIC, config->map.type);
+	info->checksum = 0; /* last */
+	info->disk_struct_size = 480;	/* Seems to be constant */
+	if (!raid->magic_0) {
+	    raid->magic_0 = 0x8253823c;
+	}
+	info->id = raid->magic_0;
+	info->generation = raid->generation;
+	info->reserved[1] = 0xc0000000; 	/* Unknown */
+	/* info->total_disks Already done above */
+	info->bootable = 1;
+
+	for (i = 0; i < info->total_disks; i++) {
+	    if (raid->disks[i].device) {
+		bcopy(raid->disks[i].device->param->serial,
+		    info->disk[i].serial, sizeof(info->disk[i].serial));
+		info->disk[i].total_sectors
+		    = AD_SOFTC(raid->disks[i])->total_secs;
+		info->disk[i].unit_id = i * 0x10000;
+		info->disk[i].status = 0x130;
+		if (raid->disks[i].flags & AR_DF_SPARE) {
+		    info->disk[i].status |= I_DISK_SPARE;
+		}
+		if (raid->disks[i].flags & AR_DF_ASSIGNED) { 
+		    info->disk[i].status |= I_DISK_CONFIGURED;  /* normally set */
+		}
+		if ((raid->disks[i].flags & AR_DF_ONLINE)
+		    && (raid->disks[i].flags & AR_DF_PRESENT)) {
+		    info->disk[i].status |= I_DISK_USABLE;	    /* normally set */
+		}
+		/* Other options
+		info->disk[i].status |= I_DISK_FAILED;
+		*/
+	   }
+	}
+
+	snprintf(config->serial, sizeof(config->serial),
+	    "RAID_Volume%d", raid->lun + 1);
+	config->total_sectors_low = raid->total_sectors;
+	config->total_sectors_high = 0;
+	config->status = 0;
+	config->volume.migrating = 0;
+#if 0	/* Not used */
+	if (raid->flags & AR_F_DEGRADED) {
+	    config->volume.state = I_VOLUME_DEGRADED;
+	}
+	/* Other options:
+	config->volume.state = I_VOLUME_DISABLED
+	config->volume.state = I_VOLUME_FAILED
+	*/
+#endif
+
+	config->volume.dirty = 0; /* not used yet */
+
+	config->map.start = 0;
+	config->map.state = 0;
+	if (raid->flags & AR_F_RAID0) {
+	    config->map.total_sectors = raid->total_sectors / 2;
+	    config->map.interleave = raid->interleave;
+	}
+	if (raid->flags & AR_F_RAID1) {
+	    config->map.total_sectors = raid->total_sectors;
+	    config->map.interleave = 256; /* DJA ??? */
+	}
+	config->map.stripes = raid->total_sectors / 512;
+	if (raid->flags & AR_F_READY) {
+	    config->map.state |= I_MAP_OKAY;
+	}
+	if (raid->flags & AR_F_DEGRADED) {
+	    config->map.state |= I_MAP_DEGRADED;
+	}
+	if (raid->flags & AR_F_REBUILDING) {
+	    config->map.state |= I_MAP_DEGRADED;
+	}
+	/* Other options are
+	config->map.state |= I_MAP_FAILED;
+	*/
+/*	config->map.type Already defined */
+	config->map.total_disks = info->total_disks;
+
+	config->map.filler1[0] = config->map.type + 1;	/* ??? */
+		
+	config->map.filler1[1] = 0xff;			/* None failed */
+	for (i = 0; i < raid->total_disks; i++) {
+	    if (!(raid->disks[i].flags & AR_DF_ONLINE)) {
+		config->map.filler1[1] = i;
+	    }
+	}
+	config->map.filler1[2] = 0x1;			/* ??? */
+    
+	for (i = 0; i < raid->total_disks; i++)
+	    config->map.disk_order[i]=i;
+
+	ckptr = (void *)info;
+	for (cksum = 0, count = 0; count < info->disk_struct_size / 4; count++)
+	    cksum += *ckptr++;
+	info->checksum = cksum; /* last */
+
+	if (raid->disks[disk].device &&
+		!(raid->disks[disk].device->flags & ATA_D_DETACHING)) {
+	    if (ar_rw(AD_SOFTC(raid->disks[disk]),
+		      I_LBA(AD_SOFTC(raid->disks[disk])),
+		      1024,
+		      (caddr_t)info, AR_WRITE)) {
+		printf("ar%d: Intel write conf failed\n",
+		       raid->lun);
+ 		return -1;
+ 	    }
+ 	}
+    }
+    return 0;
+}
+
 static void
 ar_rw_done(struct bio *bp)
 {
_at__at_ -1930,7 +2355,7 _at__at_
     printf("magic_0		0x%08x\n", config->magic_0);
     printf("magic_1		0x%08x\n", config->magic_1);
     printf("flags		0x%02x %b\n", config->flags, config->flags,
-	"\20\16HIGHPOINT\15PROMISE\13REBUILDING\12DEGRADED\11READY\3SPAN\2RAID1\1RAID0\n");
+	"\31\27QTEC\26INTEL\25LSI\24ADAPTEC\23HIGHPOINT\22PROMISE\21FREEBSD\14TOGGLE\13REBUILDING\12DEGRADED\11READY\5RAID5\4RAID3\3RAID1\2RAID0\1SPAN\n");
     printf("total_disks %d\n", config->total_disks);
     printf("generation	%d\n", config->generation);
     printf("width		%d\n", config->width);
diff -Nru /usr/src/sys/dev/ata/ata-raid.h src/sys/dev/ata/ata-raid.h
--- /usr/src/sys/dev/ata/ata-raid.h	Sat Jun 26 00:21:59 2004
+++ src/sys/dev/ata/ata-raid.h	Fri Aug 27 21:58:46 2004
_at__at_ -291,6 +291,72 _at__at_
     u_int32_t		checksum;
 } __packed;
 
+#define I_LBA(adp) (((adp->total_secs / 2) - 1) * 2)
+#define I_MAGIC	"Intel Raid ISM Cfg Sig."
+
+struct intel_raid_conf {
+    int8_t		intel_id[32];
+    u_int32_t		checksum;
+
+    u_int32_t		disk_struct_size;
+    u_int32_t		id;
+    u_int32_t		generation;
+    u_int32_t		reserved[2];
+    u_int8_t		total_disks;
+    u_int8_t		bootable;
+    u_int8_t		filler1[2];
+    u_int32_t		filler2[39];
+    struct {
+	int8_t		serial[16];
+	u_int32_t		total_sectors;
+	u_int32_t		unit_id;
+	u_int32_t		status;
+#define I_DISK_SPARE		0x1
+#define I_DISK_CONFIGURED	0x2
+#define I_DISK_FAILED		0x4
+#define I_DISK_USABLE		0x8
+	u_int32_t		filler2[5];
+    } disk[10];
+} __attribute__((packed));
+
+/* RAID DEVICE CONFIGURATION INFO */
+struct intel_raid_config {
+    int8_t		serial[16];
+    u_int32_t		total_sectors_low;
+    u_int32_t		total_sectors_high;
+    u_int32_t		status;
+    u_int32_t		reserved;
+    u_int32_t		filler[12];
+    struct {
+	u_int32_t	filler[2];
+        u_int8_t	migrating;
+        u_int8_t	state;
+/* ???
+#define I_VOLUME_OKAY		0x0
+*/
+        u_int8_t	dirty;
+        u_int8_t	filler1[1];
+        u_int32_t	filler2[5];
+    } volume;
+    struct {
+	u_int32_t	start;
+	u_int32_t	total_sectors;
+	u_int32_t	stripes;
+	u_int16_t	interleave;
+	u_int8_t	state;
+#define I_MAP_OKAY	0x0
+#define I_MAP_DEGRADED	0x2
+#define I_MAP_FAILED	0x3
+	u_int8_t	type;
+#define I_MAP_RAID0 0
+#define I_MAP_RAID1 1
+	u_int8_t	total_disks;
+	u_int8_t	filler1[3];
+	u_int32_t	filler2[7];
+	u_int32_t	disk_order[10];
+    } map;
+} __attribute__((packed));
+
 int ata_raiddisk_attach(struct ad_softc *);
 int ata_raiddisk_detach(struct ad_softc *);
 void ata_raid_attach(void);
Received on Tue Sep 21 2004 - 06:30:41 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:13 UTC