diff options
| author | tron <tron@NetBSD.org> | 2008-09-11 11:08:50 +0000 |
|---|---|---|
| committer | tron <tron@NetBSD.org> | 2008-09-11 11:08:50 +0000 |
| commit | 2b3ca19215621da75a014f8dcaafba2ce195e9bb (patch) | |
| tree | 5fd19cd81983148db5fa8afab5fe0e9d89ced5ab /sys/dev | |
| parent | 31cd18f961f163732167d5e3c9fa3153e3064fe7 (diff) | |
Add support for Intel MatrixRAID to ataraid(4). It is currently limited
to one volume.
The driver was provided by Juan RP in PR kern/39511.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ata/ata_raid.c | 9 | ||||
| -rw-r--r-- | sys/dev/ata/ata_raid_intel.c | 281 | ||||
| -rw-r--r-- | sys/dev/ata/ata_raidreg.h | 65 | ||||
| -rw-r--r-- | sys/dev/ata/ata_raidvar.h | 8 | ||||
| -rw-r--r-- | sys/dev/ata/files.ata | 3 |
5 files changed, 359 insertions, 7 deletions
diff --git a/sys/dev/ata/ata_raid.c b/sys/dev/ata/ata_raid.c index dddb002ff2a..ced54a2ceb5 100644 --- a/sys/dev/ata/ata_raid.c +++ b/sys/dev/ata/ata_raid.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata_raid.c,v 1.31 2008/09/05 12:37:13 tron Exp $ */ +/* $NetBSD: ata_raid.c,v 1.32 2008/09/11 11:08:50 tron Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata_raid.c,v 1.31 2008/09/05 12:37:13 tron Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_raid.c,v 1.32 2008/09/11 11:08:50 tron Exp $"); #include <sys/param.h> #include <sys/buf.h> @@ -116,7 +116,8 @@ ata_raid_type_name(u_int type) "Adaptec", "VIA V-RAID", "nVidia", - "JMicron" + "JMicron", + "Intel MatrixRAID" }; if (type < __arraycount(ata_raid_type_names)) @@ -250,6 +251,8 @@ ata_raid_check_component(device_t self) return; if (ata_raid_read_config_jmicron(sc) == 0) return; + if (ata_raid_read_config_intel(sc) == 0) + return; } struct ataraid_array_info * diff --git a/sys/dev/ata/ata_raid_intel.c b/sys/dev/ata/ata_raid_intel.c new file mode 100644 index 00000000000..2afc07869a1 --- /dev/null +++ b/sys/dev/ata/ata_raid_intel.c @@ -0,0 +1,281 @@ +/* $NetBSD: ata_raid_intel.c,v 1.1 2008/09/11 11:08:50 tron Exp $ */ + +/*- + * Copyright (c) 2000-2008 Søren Schmidt <sos@FreeBSD.org> + * 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, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, 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 DAMAGE. + */ + +/* + * Support for parsing Intel MatrixRAID controller configuration blocks. + * + * Adapted to NetBSD by Juan Romero Pardines (xtraeme@gmail.org). + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: ata_raid_intel.c,v 1.1 2008/09/11 11:08:50 tron Exp $"); + +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/bufq.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/disk.h> +#include <sys/disklabel.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/vnode.h> +#include <sys/kauth.h> + +#include <miscfs/specfs/specdev.h> + +#include <dev/ata/atareg.h> +#include <dev/ata/atavar.h> +#include <dev/ata/wdvar.h> + +#include <dev/ata/ata_raidreg.h> +#include <dev/ata/ata_raidvar.h> + +#ifdef ATA_RAID_DEBUG +#define DPRINTF(x) printf x +#else +#define DPRINTF(x) /* nothing */ +#endif + +#ifdef ATA_RAID_DEBUG +static const char * +ata_raid_intel_type(int type) +{ + static char buffer[16]; + + switch (type) { + case INTEL_T_RAID0: + return "RAID0"; + case INTEL_T_RAID1: + return "RAID1"; + case INTEL_T_RAID5: + return "RAID5"; + default: + sprintf(buffer, "UNKNOWN 0x%02x", type); + return buffer; + } +} + +static void +ata_raid_intel_print_info(struct intel_raid_conf *info) +{ + struct intel_raid_mapping *map; + int i, j; + + printf("********* ATA Intel MatrixRAID Metadata *********\n"); + printf("intel_id <%.24s>\n", info->intel_id); + printf("version <%.6s>\n", info->version); + printf("checksum 0x%08x\n", info->checksum); + printf("config_size 0x%08x\n", info->config_size); + printf("config_id 0x%08x\n", info->config_id); + printf("generation 0x%08x\n", info->generation); + printf("total_disks %u\n", info->total_disks); + printf("total_volumes %u\n", info->total_volumes); + printf("DISK# serial disk sectors disk_id flags\n"); + for (i = 0; i < info->total_disks; i++) { + printf(" %d <%.16s> %u 0x%08x 0x%08x\n", + i, info->disk[i].serial, info->disk[i].sectors, + info->disk[i].id, info->disk[i].flags); + } + + map = (struct intel_raid_mapping *)&info->disk[info->total_disks]; + for (j = 0; j < info->total_volumes; j++) { + printf("name %.16s\n", map->name); + printf("total_sectors %ju\n", map->total_sectors); + printf("state %u\n", map->state); + printf("reserved %u\n", map->reserved); + printf("offset %u\n", map->offset); + printf("disk_sectors %u\n", map->disk_sectors); + printf("stripe_count %u\n", map->stripe_count); + printf("stripe_sectors %u\n", map->stripe_sectors); + printf("status %u\n", map->status); + printf("type %s\n", ata_raid_intel_type(map->type)); + printf("total_disks %u\n", map->total_disks); + printf("magic[0] 0x%02x\n", map->magic[0]); + printf("magic[1] 0x%02x\n", map->magic[1]); + printf("magic[2] 0x%02x\n", map->magic[2]); + for (i = 0; i < map->total_disks; i++) + printf(" disk %d at disk_idx 0x%08x\n", + i, map->disk_idx[i]); + + map = (struct intel_raid_mapping *) + &map->disk_idx[map->total_disks]; + } + printf("=================================================\n"); +} +#endif + +int +ata_raid_read_config_intel(struct wd_softc *sc) +{ + struct intel_raid_conf *info; + struct intel_raid_mapping *map; + struct ataraid_array_info *aai; + struct ataraid_disk_info *adi; + struct vnode *vp; + uint32_t checksum, *ptr; + static int curdrive; + int bmajor, count, error = 0; + char *tmp; + dev_t dev; + + info = malloc(1536, M_DEVBUF, M_WAITOK|M_ZERO); + + bmajor = devsw_name2blk(device_xname(sc->sc_dev), NULL, 0); + + /* Get a vnode for the raw partition of this disk. */ + dev = MAKEDISKDEV(bmajor, device_unit(sc->sc_dev), RAW_PART); + error = bdevvp(dev, &vp); + if (error) + goto out; + + error = VOP_OPEN(vp, FREAD, NOCRED); + if (error) { + vput(vp); + goto out; + } + + error = ata_raid_config_block_rw(vp, INTEL_LBA(sc), info, + 1024, B_READ); + VOP_CLOSE(vp, FREAD, NOCRED); + vput(vp); + if (error) { + DPRINTF(("%s: error %d reading Intel MatrixRAID config block\n", + device_xname(sc->sc_dev), error)); + goto out; + } + + tmp = (char *)info; + (void)memcpy(tmp + 1024, tmp, 512); + (void)memcpy(tmp, tmp + 512, 1024); + (void)memset(tmp + 1024, 0, 512); + + /* Check if this is a Intel RAID struct */ + if (strncmp(info->intel_id, INTEL_MAGIC, strlen(INTEL_MAGIC))) { + DPRINTF(("%s: Intel MatrixRAID signature check failed\n", + device_xname(sc->sc_dev))); + error = ESRCH; + goto out; + } + + /* calculate checksum and compare for valid */ + for (checksum = 0, ptr = (uint32_t *)info, count = 0; + count < (info->config_size / sizeof(uint32_t)); count++) + checksum += *ptr++; + + checksum -= info->checksum; + if (checksum != info->checksum) { + DPRINTF(("%s: Intel MatrixRAID checksum failed 0x%x != 0x%x\n", + device_xname(sc->sc_dev), checksum, info->checksum)); + error = ESRCH; + goto out; + } + +#ifdef ATA_RAID_DEBUG + ata_raid_intel_print_info(info); +#endif + + /* This one points to the first volume */ + map = (struct intel_raid_mapping *)&info->disk[info->total_disks]; + + /* + * Lookup or allocate a new array info structure for this array. + * + * TODO: + * We only look at the first volume. Need to solve a few issues before + * multiple volumes are working correctly. + */ + aai = ata_raid_get_array_info(ATA_RAID_TYPE_INTEL, 0); + + /* Fill in array info */ + aai->aai_generation = info->generation; + aai->aai_status = AAI_S_READY; + + switch (map->type) { + case INTEL_T_RAID0: + aai->aai_level = AAI_L_RAID0; + aai->aai_width = map->total_disks; + break; + case INTEL_T_RAID1: + aai->aai_level = AAI_L_RAID1; + aai->aai_width = 1; + break; + default: + DPRINTF(("%s: unknown Intel MatrixRAID type 0x%02x\n", + sc->sc_dev->dv_xname, map->type)); + error = EINVAL; + goto out; + } + + switch (map->state) { + case INTEL_S_DEGRADED: + aai->aai_status |= AAI_S_DEGRADED; + break; + case INTEL_S_DISABLED: + case INTEL_S_FAILURE: + aai->aai_status &= ~AAI_S_READY; + break; + } + + aai->aai_type = ATA_RAID_TYPE_INTEL; + aai->aai_capacity = map->total_sectors; + aai->aai_interleave = map->stripe_sectors; + aai->aai_ndisks = map->total_disks; + aai->aai_heads = 255; + aai->aai_sectors = 63; + aai->aai_cylinders = + aai->aai_capacity / (aai->aai_heads * aai->aai_sectors); + aai->aai_offset = map->offset; + aai->aai_reserved = 3; + + /* Fill in disk info */ + adi = &aai->aai_disks[curdrive]; + adi->adi_status = 0; + + if (info->disk[curdrive].flags & INTEL_F_ONLINE) + adi->adi_status |= ADI_S_ONLINE; + if (info->disk[curdrive].flags & INTEL_F_ASSIGNED) + adi->adi_status |= ADI_S_ASSIGNED; + if (info->disk[curdrive].flags & INTEL_F_SPARE) { + adi->adi_status &= ~ADI_S_ONLINE; + adi->adi_status |= ADI_S_SPARE; + } + if (info->disk[curdrive].flags & INTEL_F_DOWN) + adi->adi_status &= ~ADI_S_ONLINE; + + if (adi->adi_status) { + adi->adi_dev = sc->sc_dev; + adi->adi_sectors = info->disk[curdrive].sectors; + adi->adi_compsize = adi->adi_sectors - aai->aai_reserved; + curdrive++; + } + + out: + free(info, M_DEVBUF); + return error; +} diff --git a/sys/dev/ata/ata_raidreg.h b/sys/dev/ata/ata_raidreg.h index 38ba01cfebc..3fddd342aec 100644 --- a/sys/dev/ata/ata_raidreg.h +++ b/sys/dev/ata/ata_raidreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: ata_raidreg.h,v 1.7 2008/09/05 12:37:13 tron Exp $ */ +/* $NetBSD: ata_raidreg.h,v 1.8 2008/09/11 11:08:50 tron Exp $ */ /*- * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> @@ -293,4 +293,67 @@ struct jmicron_raid_conf { uint8_t filler_5[384]; }; +/* Intel MatrixRAID metadata */ +#define INTEL_LBA(wd) ((wd)->sc_capacity - 3) + +struct intel_raid_conf { + uint8_t intel_id[24]; +#define INTEL_MAGIC "Intel Raid ISM Cfg Sig. " + + uint8_t version[6]; +#define INTEL_VERSION_1100 "1.1.00" +#define INTEL_VERSION_1201 "1.2.01" +#define INTEL_VERSION_1202 "1.2.02" + + uint8_t dummy_0[2]; + uint32_t checksum; + uint32_t config_size; + uint32_t config_id; + uint32_t generation; + uint32_t dummy_1[2]; + uint8_t total_disks; + uint8_t total_volumes; + uint8_t dummy_2[2]; + uint32_t filler_0[39]; + struct { + uint8_t serial[16]; + uint32_t sectors; + uint32_t id; + uint32_t flags; +#define INTEL_F_SPARE 0x01 +#define INTEL_F_ASSIGNED 0x02 +#define INTEL_F_DOWN 0x04 +#define INTEL_F_ONLINE 0x08 + uint32_t filler[5]; + } __packed disk[1]; + uint32_t filler_1[62]; +} __packed; + +struct intel_raid_mapping { + uint8_t name[16]; + uint64_t total_sectors __packed; + uint32_t state; + uint32_t reserved; + uint32_t filler_0[20]; + uint32_t offset; + uint32_t disk_sectors; + uint32_t stripe_count; + uint16_t stripe_sectors; + uint8_t status; +#define INTEL_S_READY 0x00 +#define INTEL_S_DISABLED 0x01 +#define INTEL_S_DEGRADED 0x02 +#define INTEL_S_FAILURE 0x03 + + uint8_t type; +#define INTEL_T_RAID0 0x00 +#define INTEL_T_RAID1 0x01 +#define INTEL_T_RAID5 0x05 + + uint8_t total_disks; + uint8_t magic[3]; + uint32_t filler_1[7]; + uint32_t disk_idx[1]; +} __packed; + #endif /* _DEV_PCI_PCIIDE_PROMISE_RAID_H_ */ diff --git a/sys/dev/ata/ata_raidvar.h b/sys/dev/ata/ata_raidvar.h index 9a2286848fc..085221fc19d 100644 --- a/sys/dev/ata/ata_raidvar.h +++ b/sys/dev/ata/ata_raidvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ata_raidvar.h,v 1.7 2008/09/05 12:37:13 tron Exp $ */ +/* $NetBSD: ata_raidvar.h,v 1.8 2008/09/11 11:08:50 tron Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -53,7 +53,8 @@ #define ATA_RAID_TYPE_VIA 2 #define ATA_RAID_TYPE_NVIDIA 3 #define ATA_RAID_TYPE_JMICRON 4 -#define ATA_RAID_TYPE_MAX 4 +#define ATA_RAID_TYPE_INTEL 5 +#define ATA_RAID_TYPE_MAX 5 /* * Max # of disks supported by a single array. This is limited by @@ -138,4 +139,7 @@ int ata_raid_read_config_nvidia(struct wd_softc *); /* JMicron RAID support */ int ata_raid_read_config_jmicron(struct wd_softc *); +/* Intel MatrixRAID support */ +int ata_raid_read_config_intel(struct wd_softc *); + #endif /* _DEV_ATA_ATA_RAIDVAR_H_ */ diff --git a/sys/dev/ata/files.ata b/sys/dev/ata/files.ata index 9928861ed47..ed5a44c06ea 100644 --- a/sys/dev/ata/files.ata +++ b/sys/dev/ata/files.ata @@ -1,4 +1,4 @@ -# $NetBSD: files.ata,v 1.18 2008/09/05 12:37:13 tron Exp $ +# $NetBSD: files.ata,v 1.19 2008/09/11 11:08:50 tron Exp $ # # Config file and device description for machine-independent devices # which attach to ATA busses. Included by ports that need it. Ports @@ -23,6 +23,7 @@ file dev/ata/ata_raid_adaptec.c ataraid file dev/ata/ata_raid_nvidia.c ataraid file dev/ata/ata_raid_via.c ataraid file dev/ata/ata_raid_jmicron.c ataraid +file dev/ata/ata_raid_intel.c ataraid attach ld at ataraid with ld_ataraid file dev/ata/ld_ataraid.c ld_ataraid |
