diff options
| author | Søren Schmidt <sos@FreeBSD.org> | 2005-06-06 13:35:24 +0000 |
|---|---|---|
| committer | Søren Schmidt <sos@FreeBSD.org> | 2005-06-06 13:35:24 +0000 |
| commit | b397739aabf38d84c57cea7cf63d5dfde84289c8 (patch) | |
| tree | 2d81e61305202d3ff7de98837162c56ce5c78d19 /sys/dev/ata | |
| parent | d8a1df199c4392e7abc7e0d61c753dc43bad0e44 (diff) | |
Notes
Diffstat (limited to 'sys/dev/ata')
| -rw-r--r-- | sys/dev/ata/ata-raid.c | 201 | ||||
| -rw-r--r-- | sys/dev/ata/ata-raid.h | 63 |
2 files changed, 257 insertions, 7 deletions
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index 4b2824f1ba534..74299fac7c179 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -74,6 +74,7 @@ static int ata_raid_intel_read_meta(device_t dev, struct ar_softc **raidp); static int ata_raid_ite_read_meta(device_t dev, struct ar_softc **raidp); static int ata_raid_lsiv2_read_meta(device_t dev, struct ar_softc **raidp); static int ata_raid_lsiv3_read_meta(device_t dev, struct ar_softc **raidp); +static int ata_raid_nvidia_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); @@ -94,6 +95,7 @@ static void ata_raid_intel_print_meta(struct intel_raid_conf *meta); static void ata_raid_ite_print_meta(struct ite_raid_conf *meta); 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_nvidia_print_meta(struct nvidia_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); @@ -111,6 +113,7 @@ static disk_strategy_t ata_raid_strategy; static void ata_raid_attach(struct ar_softc *rdp, int writeback) { + char buffer[32] = {""};; int disk; mtx_init(&rdp->lock, "ATA PseudoRAID metadata lock", NULL, MTX_DEF); @@ -118,9 +121,12 @@ ata_raid_attach(struct ar_softc *rdp, int writeback) /* sanitize arrays total_size % (width * interleave) == 0 */ if (rdp->type == AR_T_RAID0 || rdp->type == AR_T_RAID01 || - rdp->type == AR_T_RAID5) + rdp->type == AR_T_RAID5) { rdp->total_sectors = (rdp->total_sectors/(rdp->interleave*rdp->width))* (rdp->interleave * rdp->width); + sprintf(buffer, " (stripe %d KB)", + (rdp->interleave * DEV_BSIZE) / 1024); + } rdp->disk = disk_alloc(); rdp->disk->d_strategy = ata_raid_strategy; //rdp->disk->d_dump = ata_raid_dump; @@ -134,9 +140,10 @@ ata_raid_attach(struct ar_softc *rdp, int writeback) rdp->disk->d_unit = rdp->lun; disk_create(rdp->disk, DISK_VERSION); - printf("ar%d: %lluMB <%s %s array> status: %s\n", rdp->lun, + printf("ar%d: %lluMB <%s %s%s> status: %s\n", rdp->lun, (unsigned long long)(rdp->total_sectors / ((1024L*1024L)/DEV_BSIZE)), - ata_raid_format(rdp), ata_raid_type(rdp), ata_raid_flags(rdp)); + ata_raid_format(rdp), ata_raid_type(rdp), + buffer, ata_raid_flags(rdp)); if (testing || bootverbose) printf("ar%d: %llu sectors [%dC/%dH/%dS] <%s> subdisks defined as:\n", @@ -1206,6 +1213,11 @@ ata_raid_read_metadata(device_t subdisk) return 0; break; + case ATA_NVIDIA_ID: + if (ata_raid_nvidia_read_meta(subdisk, ata_raid_arrays)) + return 0; + break; + case 0: /* XXX SOS cover up for bug in our PCI code */ case ATA_PROMISE_ID: if (ata_raid_promise_read_meta(subdisk, ata_raid_arrays, 0)) @@ -1275,6 +1287,9 @@ ata_raid_write_metadata(struct ar_softc *rdp) case AR_F_LSIV3_RAID: return ata_raid_lsiv3_write_meta(rdp); + case AR_F_NVIDIA_RAID: + return ata_raid_nvidia_write_meta(rdp); + case AR_F_SII_RAID: return ata_raid_sii_write_meta(rdp); @@ -2345,6 +2360,131 @@ lsiv3_out: return retval; } +/* nVidia MediaShield Metadata */ +static int +ata_raid_nvidia_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 nvidia_raid_conf *meta; + struct ar_softc *raid = NULL; + u_int32_t checksum, *ptr; + int array, count, retval = 0; + + if (!(meta = (struct nvidia_raid_conf *) + malloc(sizeof(struct nvidia_raid_conf), M_AR, M_NOWAIT | M_ZERO))) + return ENOMEM; + + if (ata_raid_rw(parent, NVIDIA_LBA(parent), + meta, sizeof(struct nvidia_raid_conf), ATA_R_READ)) { + if (testing || bootverbose) + device_printf(parent, "nVidia read metadata failed\n"); + goto nvidia_out; + } + + /* check if this is a nVidia RAID struct */ + if (strncmp(meta->nvidia_id, NV_MAGIC, strlen(NV_MAGIC))) { + if (testing || bootverbose) + device_printf(parent, "nVidia check1 failed\n"); + goto nvidia_out; + } + + /* check if the checksum is OK */ + for (checksum = 0, ptr = (u_int32_t*)meta, count = 0; + count < meta->config_size; count++) + checksum += *ptr++; + if (checksum) { + if (testing || bootverbose) + device_printf(parent, "nVidia check2 failed\n"); + goto nvidia_out; + } + + if (testing || bootverbose) + ata_raid_nvidia_print_meta(meta); + + /* now convert nVidia 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 nvidia_out; + } + } + raid = raidp[array]; + if (raid->format && (raid->format != AR_F_NVIDIA_RAID)) + continue; + + if (raid->format == AR_F_NVIDIA_RAID && + ((raid->magic_0 != meta->magic_1) || + (raid->magic_1 != meta->magic_2))) { + continue; + } + + switch (meta->type) { + case NV_T_SPAN: + raid->type = AR_T_SPAN; + break; + + case NV_T_RAID0: + raid->type = AR_T_RAID0; + break; + + case NV_T_RAID1: + raid->type = AR_T_RAID1; + break; + + case NV_T_RAID5: + raid->type = AR_T_RAID5; + break; + + case NV_T_RAID01: + raid->type = AR_T_RAID01; + break; + + default: + device_printf(parent, "nVidia unknown RAID type 0x%02x\n", + meta->type); + free(raidp[array], M_AR); + raidp[array] = NULL; + goto nvidia_out; + } + raid->magic_0 = meta->magic_1; + raid->magic_1 = meta->magic_2; + raid->format = AR_F_NVIDIA_RAID; + raid->generation = 0; + raid->interleave = meta->stripe_sectors; + raid->width = meta->array_width; + raid->total_disks = meta->total_disks; + raid->total_sectors = meta->total_sectors; + raid->heads = 255; + raid->sectors = 63; + raid->cylinders = raid->total_sectors / (63 * 255); + raid->offset_sectors = 0; + raid->rebuild_lba = meta->rebuild_lba; + raid->lun = array; + raid->status = AR_S_READY; + if (meta->status & NV_S_DEGRADED) + raid->status |= AR_S_DEGRADED; + + raid->disks[meta->disk_number].dev = parent; + raid->disks[meta->disk_number].sectors = + raid->total_sectors / raid->width; + raid->disks[meta->disk_number].flags = + (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE); + ars->raid = raid; + ars->disk_number = meta->disk_number; + retval = 1; + break; + } + +nvidia_out: + free(meta, M_AR); + return retval; +} + /* Promise FastTrak Metadata */ static int ata_raid_promise_read_meta(device_t dev, struct ar_softc **raidp, int native) @@ -3182,6 +3322,7 @@ ata_raid_format(struct ar_softc *rdp) case AR_F_ITE_RAID: return "Integrated Technology Express"; case AR_F_LSIV2_RAID: return "LSILogic v2 MegaRAID"; case AR_F_LSIV3_RAID: return "LSILogic v3 MegaRAID"; + case AR_F_NVIDIA_RAID: return "nVidia MediaShield"; 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 V-RAID"; @@ -3649,6 +3790,60 @@ ata_raid_lsiv3_print_meta(struct lsiv3_raid_conf *meta) } static char * +ata_raid_nvidia_type(int type) +{ + static char buffer[16]; + + switch (type) { + case NV_T_SPAN: return "SPAN"; + case NV_T_RAID0: return "RAID0"; + case NV_T_RAID1: return "RAID1"; + case NV_T_RAID3: return "RAID3"; + case NV_T_RAID5: return "RAID5"; + case NV_T_RAID01: return "RAID0+1"; + default: sprintf(buffer, "UNKNOWN 0x%02x", type); + return buffer; + } +} + +static void +ata_raid_nvidia_print_meta(struct nvidia_raid_conf *meta) +{ + printf("******** ATA nVidia MediaShield Metadata ********\n"); + printf("nvidia_id <%.8s>\n", meta->nvidia_id); + printf("config_size %d\n", meta->config_size); + printf("checksum 0x%08x\n", meta->checksum); + printf("version 0x%04x\n", meta->version); + printf("disk_number %d\n", meta->disk_number); + printf("dummy_0 0x%02x\n", meta->dummy_0); + printf("total_sectors %d\n", meta->total_sectors); + printf("sectors_size %d\n", meta->sector_size); + printf("serial %.16s\n", meta->serial); + printf("revision %.4s\n", meta->revision); + printf("dummy_1 0x%08x\n", meta->dummy_1); + printf("magic_0 0x%08x\n", meta->magic_0); + printf("magic_1 0x%016llx\n", meta->magic_1); + printf("magic_2 0x%016llx\n", meta->magic_2); + printf("flags 0x%02x\n", meta->flags); + printf("array_width %d\n", meta->array_width); + printf("total_disks %d\n", meta->total_disks); + printf("dummy_2 0x%02x\n", meta->dummy_2); + printf("type %s\n", ata_raid_nvidia_type(meta->type)); + printf("dummy_3 0x%04x\n", meta->dummy_3); + printf("stripe_sectors %d\n", meta->stripe_sectors); + printf("stripe_bytes %d\n", meta->stripe_bytes); + printf("stripe_shift %d\n", meta->stripe_shift); + printf("stripe_mask 0x%08x\n", meta->stripe_mask); + printf("stripe_sizesectors %d\n", meta->stripe_sizesectors); + printf("stripe_sizebytes %d\n", meta->stripe_sizebytes); + printf("rebuild_lba %d\n", meta->rebuild_lba); + printf("dummy_4 0x%08x\n", meta->dummy_4); + printf("dummy_5 0x%08x\n", meta->dummy_5); + printf("status 0x%08x\n", meta->status); + printf("=================================================\n"); +} + +static char * ata_raid_promise_type(int type) { static char buffer[16]; diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h index eed057af883b3..3fb959ce14cf6 100644 --- a/sys/dev/ata/ata-raid.h +++ b/sys/dev/ata/ata-raid.h @@ -70,10 +70,11 @@ struct ar_softc { #define AR_F_ITE_RAID 0x0020 #define AR_F_LSIV2_RAID 0x0040 #define AR_F_LSIV3_RAID 0x0080 -#define AR_F_PROMISE_RAID 0x0100 -#define AR_F_SII_RAID 0x0200 -#define AR_F_VIA_RAID 0x0400 -#define AR_F_FORMAT_MASK 0x07ff +#define AR_F_NVIDIA_RAID 0x0100 +#define AR_F_PROMISE_RAID 0x0200 +#define AR_F_SII_RAID 0x0400 +#define AR_F_VIA_RAID 0x0800 +#define AR_F_FORMAT_MASK 0x0fff u_int generation; /* generation of this array */ u_int64_t total_sectors; @@ -520,6 +521,60 @@ struct lsiv3_raid_conf { } __packed; +/* nVidia MediaShield Metadata */ +#define NVIDIA_LBA(dev) \ + (((struct ad_softc *)device_get_ivars(dev))->total_secs - 2) + +struct nvidia_raid_conf { + u_int8_t nvidia_id[8]; +#define NV_MAGIC "NVIDIA " + + u_int32_t config_size; + u_int32_t checksum; + u_int16_t version; + u_int8_t disk_number; + u_int8_t dummy_0; + u_int32_t total_sectors; + u_int32_t sector_size; + u_int8_t serial[16]; + u_int8_t revision[4]; + u_int32_t dummy_1; + + u_int32_t magic_0; +#define NV_MAGIC0 0x00640044 + + u_int64_t magic_1; + u_int64_t magic_2; + u_int8_t flags; + u_int8_t array_width; + u_int8_t total_disks; + u_int8_t dummy_2; + u_int16_t type; +#define NV_T_RAID0 0x00000080 +#define NV_T_RAID1 0x00000081 +#define NV_T_RAID3 0x00000083 +#define NV_T_RAID5 0x00000085 +#define NV_T_RAID01 0x00008180 +#define NV_T_SPAN 0x000000ff + + u_int16_t dummy_3; + u_int32_t stripe_sectors; + u_int32_t stripe_bytes; + u_int32_t stripe_shift; + u_int32_t stripe_mask; + u_int32_t stripe_sizesectors; + u_int32_t stripe_sizebytes; + u_int32_t rebuild_lba; + u_int32_t dummy_4; + u_int32_t dummy_5; + u_int32_t status; +#define NV_S_BOOTABLE 0x00000001 +#define NV_S_DEGRADED 0x00000002 + + u_int32_t filler[98]; +} __packed; + + /* Promise FastTrak Metadata */ #define PR_LBA(dev) \ (((((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) |
