Add support for VIA Tech metadata as used on thier SATA parts.
This commit is contained in:
parent
45125e147a
commit
8ef82837f5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=144936
@ -77,6 +77,7 @@ static int ata_raid_lsiv3_read_meta(device_t dev, struct ar_softc **raidp);
|
||||
static int ata_raid_promise_read_meta(device_t dev, struct ar_softc **raidp, int native);
|
||||
static int ata_raid_promise_write_meta(struct ar_softc *rdp);
|
||||
static int ata_raid_sii_read_meta(device_t dev, struct ar_softc **raidp);
|
||||
static int ata_raid_via_read_meta(device_t dev, struct ar_softc **raidp);
|
||||
static struct ata_request *ata_raid_init_request(struct ar_softc *rdp, struct bio *bio);
|
||||
static int ata_raid_send_request(struct ata_request *request);
|
||||
static int ata_raid_rw(device_t dev, u_int64_t lba, void *data, u_int bcount, int flags);
|
||||
@ -95,6 +96,7 @@ static void ata_raid_lsiv2_print_meta(struct lsiv2_raid_conf *meta);
|
||||
static void ata_raid_lsiv3_print_meta(struct lsiv3_raid_conf *meta);
|
||||
static void ata_raid_promise_print_meta(struct promise_raid_conf *meta);
|
||||
static void ata_raid_sii_print_meta(struct sii_raid_conf *meta);
|
||||
static void ata_raid_via_print_meta(struct via_raid_conf *meta);
|
||||
|
||||
/* internal vars */
|
||||
static struct ar_softc *ata_raid_arrays[MAX_ARRAYS];
|
||||
@ -958,18 +960,6 @@ ata_raid_create(struct raid_setup *setup)
|
||||
rdp->interleave = min(max(32, rdp->interleave), 128); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_INTEL_RAID:
|
||||
rdp->interleave = min(max(8, rdp->interleave), 256); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_ITE_RAID:
|
||||
rdp->interleave = min(max(2, rdp->interleave), 128); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_SII_RAID:
|
||||
rdp->interleave = min(max(8, rdp->interleave), 256); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_HPTV2_RAID:
|
||||
rdp->interleave = min(max(8, rdp->interleave), 128); /*+*/
|
||||
rdp->offset_sectors = HPTV2_LBA(x) + 1;
|
||||
@ -979,6 +969,14 @@ ata_raid_create(struct raid_setup *setup)
|
||||
rdp->interleave = min(max(32, rdp->interleave), 4096); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_INTEL_RAID:
|
||||
rdp->interleave = min(max(8, rdp->interleave), 256); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_ITE_RAID:
|
||||
rdp->interleave = min(max(2, rdp->interleave), 128); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_LSIV2_RAID:
|
||||
rdp->interleave = min(max(2, rdp->interleave), 4096);
|
||||
break;
|
||||
@ -990,6 +988,14 @@ ata_raid_create(struct raid_setup *setup)
|
||||
case AR_F_PROMISE_RAID:
|
||||
rdp->interleave = min(max(2, rdp->interleave), 2048); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_SII_RAID:
|
||||
rdp->interleave = min(max(8, rdp->interleave), 256); /*+*/
|
||||
break;
|
||||
|
||||
case AR_F_VIA_RAID:
|
||||
rdp->interleave = min(max(8, rdp->interleave), 128); /*+*/
|
||||
break;
|
||||
}
|
||||
|
||||
rdp->total_disks = total_disks;
|
||||
@ -1177,6 +1183,11 @@ ata_raid_read_metadata(device_t subdisk)
|
||||
if (ata_raid_sii_read_meta(subdisk, ata_raid_arrays))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ATA_VIA_ID:
|
||||
if (ata_raid_via_read_meta(subdisk, ata_raid_arrays))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1219,10 +1230,10 @@ ata_raid_write_metadata(struct ar_softc *rdp)
|
||||
case AR_F_ADAPTEC_RAID:
|
||||
return ata_raid_adaptec_write_meta(rdp);
|
||||
|
||||
case ATA_INTEL_ID:
|
||||
case AR_F_INTEL_RAID:
|
||||
return ata_raid_intel_write_meta(rdp);
|
||||
|
||||
case ATA_ITE_ID:
|
||||
case AR_F_ITE_RAID:
|
||||
return ata_raid_ite_write_meta(rdp);
|
||||
|
||||
case AR_F_LSIV2_RAID:
|
||||
@ -1231,7 +1242,10 @@ ata_raid_write_metadata(struct ar_softc *rdp)
|
||||
case AR_F_LSIV3_RAID:
|
||||
return ata_raid_lsiv3_write_meta(rdp);
|
||||
|
||||
case ATA_SILICON_IMAGE_ID:
|
||||
case AR_F_SII_RAID:
|
||||
return ata_raid_sii_write_meta(rdp);
|
||||
|
||||
case AR_F_VIA_RAID:
|
||||
return ata_raid_sii_write_meta(rdp);
|
||||
#endif
|
||||
default:
|
||||
@ -2762,7 +2776,7 @@ ata_raid_sii_read_meta(device_t dev, struct ar_softc **raidp)
|
||||
|
||||
raid->disks[disk_number].dev = parent;
|
||||
raid->disks[disk_number].sectors =
|
||||
raid->total_sectors / raid->total_disks;
|
||||
raid->total_sectors / raid->width;
|
||||
raid->disks[disk_number].flags =
|
||||
(AR_DF_ONLINE | AR_DF_PRESENT | AR_DF_ASSIGNED);
|
||||
ars->raid = raid;
|
||||
@ -2778,6 +2792,123 @@ ata_raid_sii_read_meta(device_t dev, struct ar_softc **raidp)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* VIA Tech Metadata */
|
||||
static int
|
||||
ata_raid_via_read_meta(device_t dev, struct ar_softc **raidp)
|
||||
{
|
||||
struct ata_raid_subdisk *ars = device_get_softc(dev);
|
||||
device_t parent = device_get_parent(dev);
|
||||
struct via_raid_conf *meta;
|
||||
struct ar_softc *raid = NULL;
|
||||
u_int8_t checksum, *ptr;
|
||||
int array, count, disk, retval = 0;
|
||||
|
||||
if (!(meta = (struct via_raid_conf *)
|
||||
malloc(sizeof(struct via_raid_conf), M_AR, M_NOWAIT | M_ZERO)))
|
||||
return ENOMEM;
|
||||
|
||||
if (ata_raid_rw(parent, VIA_LBA(parent),
|
||||
meta, sizeof(struct via_raid_conf), ATA_R_READ)) {
|
||||
if (testing || bootverbose)
|
||||
device_printf(parent, "VIA read metadata failed\n");
|
||||
goto via_out;
|
||||
}
|
||||
|
||||
/* check if this is a VIA RAID struct */
|
||||
if (meta->magic != VIA_MAGIC) {
|
||||
if (testing || bootverbose)
|
||||
device_printf(parent, "VIA check1 failed\n");
|
||||
goto via_out;
|
||||
}
|
||||
|
||||
/* calc the checksum and compare for valid */
|
||||
for (checksum = 0, ptr = (u_int8_t *)meta, count = 0; count < 50; count++)
|
||||
checksum += *ptr++;
|
||||
if (checksum != meta->checksum) {
|
||||
if (testing || bootverbose)
|
||||
device_printf(parent, "VIA check2 failed\n");
|
||||
goto via_out;
|
||||
}
|
||||
|
||||
if (testing || bootverbose)
|
||||
ata_raid_via_print_meta(meta);
|
||||
|
||||
/* now convert VIA meta into our generic form */
|
||||
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]) {
|
||||
device_printf(parent, "failed to allocate metadata storage\n");
|
||||
goto via_out;
|
||||
}
|
||||
}
|
||||
raid = raidp[array];
|
||||
if (raid->format && (raid->format != AR_F_VIA_RAID))
|
||||
continue;
|
||||
|
||||
if (raid->format == AR_F_VIA_RAID && (raid->magic_0 != meta->disks[0]))
|
||||
continue;
|
||||
|
||||
switch (meta->type) {
|
||||
case VIA_T_RAID0:
|
||||
raid->type = AR_T_RAID0;
|
||||
raid->width = meta->stripe_layout & VIA_L_MASK;
|
||||
raid->total_sectors = meta->total_sectors;
|
||||
break;
|
||||
|
||||
case VIA_T_RAID1:
|
||||
raid->type = AR_T_RAID1;
|
||||
raid->width = 1;
|
||||
raid->total_sectors = meta->total_sectors;
|
||||
break;
|
||||
|
||||
case VIA_T_SPAN:
|
||||
raid->type = AR_T_SPAN;
|
||||
raid->width = 1;
|
||||
raid->total_sectors += meta->total_sectors;
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(parent,"VIA unknown RAID type 0x%02x\n", meta->type);
|
||||
free(raidp[array], M_AR);
|
||||
raidp[array] = NULL;
|
||||
goto via_out;
|
||||
}
|
||||
raid->magic_0 = meta->disks[0]; /* XXX SOS hackish */
|
||||
raid->format = AR_F_VIA_RAID;
|
||||
raid->generation = 0;
|
||||
raid->interleave = 0x08 << (meta->stripe_layout >> VIA_L_SHIFT);
|
||||
for (count = 0, disk = 0; disk < 8; disk++)
|
||||
if (meta->disks[disk])
|
||||
count++;
|
||||
raid->total_disks = count;
|
||||
raid->heads = 255;
|
||||
raid->sectors = 63;
|
||||
raid->cylinders = raid->total_sectors / (63 * 255);
|
||||
|
||||
for (disk = 0; disk < 8; disk++) {
|
||||
if ((meta->disks[disk] == meta->disk_id) &&
|
||||
((disk << 2) == meta->disk_index)) {
|
||||
raid->disks[disk].dev = parent;
|
||||
raid->disks[disk].sectors = meta->total_sectors / raid->width;
|
||||
raid->disks[disk].flags =
|
||||
(AR_DF_ONLINE | AR_DF_PRESENT | AR_DF_ASSIGNED);
|
||||
ars->raid = raid;
|
||||
ars->disk_number = disk;
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
via_out:
|
||||
free(meta, M_AR);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct ata_request *
|
||||
ata_raid_init_request(struct ar_softc *rdp, struct bio *bio)
|
||||
{
|
||||
@ -3019,6 +3150,7 @@ ata_raid_format(struct ar_softc *rdp)
|
||||
case AR_F_LSIV3_RAID: return "LSILogic v3 MegaRAID";
|
||||
case AR_F_PROMISE_RAID: return "Promise Fasttrak";
|
||||
case AR_F_SII_RAID: return "Silicon Image Medley";
|
||||
case AR_F_VIA_RAID: return "VIA Tech";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
@ -3603,3 +3735,40 @@ ata_raid_sii_print_meta(struct sii_raid_conf *meta)
|
||||
printf("checksum_1 0x%04x\n", meta->checksum_1);
|
||||
printf("=================================================\n");
|
||||
}
|
||||
|
||||
static char *
|
||||
ata_raid_via_type(int type)
|
||||
{
|
||||
static char buffer[16];
|
||||
|
||||
switch (type) {
|
||||
case VIA_T_RAID0: return "RAID0";
|
||||
case VIA_T_RAID1: return "RAID1";
|
||||
case VIA_T_SPAN: return "SPAN";
|
||||
default: sprintf(buffer, "UNKNOWN 0x%02x", type);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ata_raid_via_print_meta(struct via_raid_conf *meta)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("*************** ATA VIA Metadata ****************\n");
|
||||
printf("magic 0x%02x\n", meta->magic);
|
||||
printf("dummy_0 0x%02x\n", meta->dummy_0);
|
||||
printf("type %s\n", ata_raid_via_type(meta->type));
|
||||
printf("disk_index 0x%02x\n", meta->disk_index);
|
||||
printf("stripe_disks %d\n", meta->stripe_layout & VIA_L_MASK);
|
||||
printf("stripe_sectors %d\n", (meta->stripe_layout >> VIA_L_SHIFT));
|
||||
printf("total_sectors %llu\n", meta->total_sectors);
|
||||
printf("disk_id 0x%08x\n", meta->disk_id);
|
||||
printf("DISK# disk_id\n");
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (meta->disks[i])
|
||||
printf(" %d 0x%08x\n", i, meta->disks[i]);
|
||||
}
|
||||
printf("checksum 0x%02x\n", meta->checksum);
|
||||
printf("=================================================\n");
|
||||
}
|
||||
|
@ -72,7 +72,8 @@ struct ar_softc {
|
||||
#define AR_F_LSIV3_RAID 0x0080
|
||||
#define AR_F_PROMISE_RAID 0x0100
|
||||
#define AR_F_SII_RAID 0x0200
|
||||
#define AR_F_FORMAT_MASK 0x03ff
|
||||
#define AR_F_VIA_RAID 0x0400
|
||||
#define AR_F_FORMAT_MASK 0x07ff
|
||||
|
||||
u_int generation; /* generation of this array */
|
||||
u_int64_t total_sectors;
|
||||
@ -108,7 +109,7 @@ struct ar_softc {
|
||||
|
||||
/* note all entries are big endian */
|
||||
struct adaptec_raid_conf {
|
||||
u_int32_t magic_0; /* 0x0000 */
|
||||
u_int32_t magic_0;
|
||||
#define ADP_MAGIC_0 0xc4650790
|
||||
|
||||
u_int32_t generation;
|
||||
@ -116,13 +117,13 @@ struct adaptec_raid_conf {
|
||||
u_int16_t total_configs;
|
||||
u_int16_t dummy_1;
|
||||
u_int16_t checksum;
|
||||
u_int32_t dummy_2; /* 0x0010 */
|
||||
u_int32_t dummy_2;
|
||||
u_int32_t dummy_3;
|
||||
u_int32_t flags;
|
||||
u_int32_t timestamp;
|
||||
u_int32_t dummy_4[4]; /* 0x0020 */
|
||||
u_int32_t dummy_5[4]; /* 0x0030 */
|
||||
struct { /* 0x0040 */
|
||||
u_int32_t dummy_4[4];
|
||||
u_int32_t dummy_5[4];
|
||||
struct {
|
||||
u_int16_t total_disks;
|
||||
u_int16_t generation;
|
||||
u_int32_t magic_0;
|
||||
@ -146,9 +147,8 @@ struct adaptec_raid_conf {
|
||||
|
||||
u_int32_t dummy_8[4];
|
||||
u_int8_t name[16];
|
||||
} configs[127]; /* x 0x40 bytes */
|
||||
|
||||
u_int32_t dummy_6[13]; /* 0x2000 */
|
||||
} configs[127];
|
||||
u_int32_t dummy_6[13];
|
||||
u_int32_t magic_1;
|
||||
#define ADP_MAGIC_1 0x9ff85009
|
||||
u_int32_t dummy_7[3];
|
||||
@ -283,7 +283,7 @@ struct hptv3_raid_conf {
|
||||
|
||||
struct intel_raid_conf {
|
||||
u_int8_t intel_id[24];
|
||||
#define INTEL_MAGIC "Intel Raid ISM Cfg Sig. "
|
||||
#define INTEL_MAGIC "Intel Raid ISM Cfg Sig. "
|
||||
|
||||
u_int8_t version[6];
|
||||
u_int8_t dummy_0[2];
|
||||
@ -344,12 +344,12 @@ struct intel_raid_mapping {
|
||||
|
||||
struct ite_raid_conf {
|
||||
u_int32_t filler_1[5];
|
||||
u_int8_t timestamp_0[8]; /* BCD coded y:Y:M:D:m:h:f:s */
|
||||
u_int8_t timestamp_0[8];
|
||||
u_int32_t dummy_1;
|
||||
u_int32_t filler_2[5];
|
||||
u_int16_t filler_3;
|
||||
u_int8_t ite_id[40]; /* byte swapped */
|
||||
#define ITE_MAGIC "Integrated Technology Express Inc "
|
||||
u_int8_t ite_id[40];
|
||||
#define ITE_MAGIC "Integrated Technology Express Inc "
|
||||
|
||||
u_int16_t filler_4;
|
||||
u_int32_t filler_5[6];
|
||||
@ -361,7 +361,7 @@ struct ite_raid_conf {
|
||||
u_int64_t total_sectors __packed;
|
||||
u_int32_t filler_8[12];
|
||||
|
||||
u_int16_t filler_9; /* 0x100 */
|
||||
u_int16_t filler_9;
|
||||
u_int8_t type;
|
||||
#define ITE_T_RAID0 0x00
|
||||
#define ITE_T_RAID1 0x01
|
||||
@ -374,8 +374,8 @@ struct ite_raid_conf {
|
||||
u_int8_t filler_11[3];
|
||||
u_int32_t filler_12[54];
|
||||
|
||||
u_int32_t dummy_6[4]; /* 0x200 */
|
||||
u_int8_t timestamp_1[8]; /* same as timestamp_0 */
|
||||
u_int32_t dummy_6[4];
|
||||
u_int8_t timestamp_1[8];
|
||||
u_int32_t filler_13[9];
|
||||
u_int8_t stripe_sectors;
|
||||
u_int8_t filler_14[3];
|
||||
@ -397,7 +397,7 @@ struct ite_raid_conf {
|
||||
|
||||
struct lsiv2_raid_conf {
|
||||
u_int8_t lsi_id[6];
|
||||
#define LSIV2_MAGIC "$XIDE$"
|
||||
#define LSIV2_MAGIC "$XIDE$"
|
||||
|
||||
u_int8_t dummy_0;
|
||||
u_int8_t flags;
|
||||
@ -470,7 +470,7 @@ struct lsiv3_raid_conf {
|
||||
u_int8_t checksum_0;
|
||||
u_int8_t filler_5[512*2];
|
||||
u_int8_t lsi_id[6];
|
||||
#define LSIV3_MAGIC "$_IDE$"
|
||||
#define LSIV3_MAGIC "$_IDE$"
|
||||
|
||||
u_int16_t dummy_2; /* 0x33de for OK disk */
|
||||
u_int16_t version; /* 0x0131 for this version */
|
||||
@ -523,18 +523,15 @@ struct lsiv3_raid_conf {
|
||||
/* Promise FastTrak Metadata */
|
||||
#define PR_LBA(dev) \
|
||||
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 63)
|
||||
#if 0
|
||||
(((((struct ad_softc *)device_get_ivars(dev))->total_secs / (((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors)) * ((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors) - ((struct ad_softc *)device_get_ivars(dev))->sectors)
|
||||
#endif
|
||||
|
||||
struct promise_raid_conf {
|
||||
char promise_id[24];
|
||||
#define PR_MAGIC "Promise Technology, Inc."
|
||||
#define PR_MAGIC "Promise Technology, Inc."
|
||||
|
||||
u_int32_t dummy_0;
|
||||
u_int64_t magic_0;
|
||||
#define PR_MAGIC0(x) (((u_int64_t)(x.channel) << 48) | \
|
||||
((u_int64_t)(x.device != 0) << 56))
|
||||
#define PR_MAGIC0(x) (((u_int64_t)(x.channel) << 48) | \
|
||||
((u_int64_t)(x.device != 0) << 56))
|
||||
u_int16_t magic_1;
|
||||
u_int32_t magic_2;
|
||||
u_int8_t filler1[470];
|
||||
@ -612,7 +609,7 @@ struct sii_raid_conf {
|
||||
u_int32_t controller_pci_id;
|
||||
u_int16_t version_minor;
|
||||
u_int16_t version_major;
|
||||
u_int8_t timestamp[6]; /* BCD coded s:m:h:D:M:Y */
|
||||
u_int8_t timestamp[6];
|
||||
u_int16_t stripe_sectors;
|
||||
u_int16_t dummy_2;
|
||||
u_int8_t disk_number;
|
||||
@ -638,5 +635,32 @@ struct sii_raid_conf {
|
||||
u_int8_t name[16];
|
||||
u_int16_t checksum_0;
|
||||
int8_t filler1[190];
|
||||
u_int16_t checksum_1; /* sum of all 128 shorts == 0 */
|
||||
u_int16_t checksum_1;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* VIA Tech Metadata */
|
||||
#define VIA_LBA(dev) \
|
||||
( ((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
|
||||
|
||||
struct via_raid_conf {
|
||||
u_int16_t magic;
|
||||
#define VIA_MAGIC 0xaa55
|
||||
|
||||
u_int8_t dummy_0;
|
||||
u_int8_t type;
|
||||
#define VIA_T_RAID0 0x04
|
||||
#define VIA_T_RAID1 0x0c
|
||||
#define VIA_T_SPAN 0x44
|
||||
|
||||
u_int8_t disk_index;
|
||||
u_int8_t stripe_layout;
|
||||
#define VIA_L_MASK 0x07
|
||||
#define VIA_L_SHIFT 4
|
||||
|
||||
u_int64_t total_sectors;
|
||||
u_int32_t disk_id;
|
||||
u_int32_t disks[8];
|
||||
u_int8_t checksum;
|
||||
u_int8_t filler_1[461];
|
||||
} __packed;
|
||||
|
Loading…
Reference in New Issue
Block a user