diff options
| author | garbled <garbled@NetBSD.org> | 2007-03-27 00:10:20 +0000 |
|---|---|---|
| committer | garbled <garbled@NetBSD.org> | 2007-03-27 00:10:20 +0000 |
| commit | 47dfabcdf70aa765067db01cd071d166cb3f256e (patch) | |
| tree | 99dbcc8ddde00863b3f6a030df12f6b76f5772fd /sys | |
| parent | 4398c0d8cd3ac0c8a0d9c05387fca5ec44e3efc7 (diff) | |
Add support for VIA V-TECH ata raid. Tested on 4.0 with RAID0, RAID1 and
SPAN over a pair of sata drives on a VT8237A SATA Controller.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/dev/ata/ata_raid.c | 7 | ||||
| -rw-r--r-- | sys/dev/ata/ata_raid_via.c | 258 | ||||
| -rw-r--r-- | sys/dev/ata/ata_raidreg.h | 34 | ||||
| -rw-r--r-- | sys/dev/ata/ata_raidvar.h | 9 | ||||
| -rw-r--r-- | sys/dev/ata/files.ata | 3 |
5 files changed, 305 insertions, 6 deletions
diff --git a/sys/dev/ata/ata_raid.c b/sys/dev/ata/ata_raid.c index 620b2b8d041..94f70fc3172 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.21 2007/03/09 15:41:02 drochner Exp $ */ +/* $NetBSD: ata_raid.c,v 1.22 2007/03/27 00:10:20 garbled Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata_raid.c,v 1.21 2007/03/09 15:41:02 drochner Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_raid.c,v 1.22 2007/03/27 00:10:20 garbled Exp $"); #include <sys/param.h> #include <sys/buf.h> @@ -113,6 +113,7 @@ ata_raid_type_name(u_int type) static const char *ata_raid_type_names[] = { "Promise", "Adaptec", + "VIA V-RAID", }; if (type < sizeof(ata_raid_type_names) / sizeof(ata_raid_type_names[0])) @@ -240,6 +241,8 @@ ata_raid_check_component(struct device *self) return; if (ata_raid_read_config_promise(sc) == 0) return; + if (ata_raid_read_config_via(sc) == 0) + return; } struct ataraid_array_info * diff --git a/sys/dev/ata/ata_raid_via.c b/sys/dev/ata/ata_raid_via.c new file mode 100644 index 00000000000..68c90b6a89f --- /dev/null +++ b/sys/dev/ata/ata_raid_via.c @@ -0,0 +1,258 @@ +/* $NetBSD: ata_raid_via.c,v 1.1 2007/03/27 00:10:20 garbled Exp $ */ + +/*- + * Copyright (c) 2000,2001,2002 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 VIA V-RAID ATA RAID controller configuration blocks. + * + * Adapted to NetBSD by Tim Rightnour (garbled@netbsd.org) + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: ata_raid_via.c,v 1.1 2007/03/27 00:10:20 garbled 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_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_RAID5: return "RAID5"; + case VIA_T_RAID01: return "RAID0+1"; + case VIA_T_SPAN: return "SPAN"; + default: + sprintf(buffer, "UNKNOWN 0x%02x", type); + return buffer; + } +} + +static void +ata_raid_via_print_info(struct via_raid_conf *info) +{ + int i; + + printf("*************** ATA VIA Metadata ****************\n"); + printf("magic 0x%02x\n", info->magic); + printf("dummy_0 0x%02x\n", info->dummy_0); + printf("type %s\n", + ata_raid_via_type(info->type & VIA_T_MASK)); + printf("bootable %d\n", info->type & VIA_T_BOOTABLE); + printf("unknown %d\n", info->type & VIA_T_UNKNOWN); + printf("disk_index 0x%02x\n", info->disk_index); + printf("stripe_layout 0x%02x\n", info->stripe_layout); + printf(" stripe_disks %d\n", info->stripe_layout & VIA_L_DISKS); + printf(" stripe_sectors %d\n", + 0x08 << ((info->stripe_layout & VIA_L_MASK) >> VIA_L_SHIFT)); + printf("disk_sectors %ju\n", info->disk_sectors); + printf("disk_id 0x%08x\n", info->disk_id); + printf("DISK# disk_id\n"); + for (i = 0; i < 8; i++) { + if (info->disks[i]) + printf(" %d 0x%08x\n", i, info->disks[i]); + } + printf("checksum 0x%02x\n", info->checksum); + printf("=================================================\n"); +} +#endif + +int +ata_raid_read_config_via(struct wd_softc *sc) +{ + struct via_raid_conf *info; + struct atabus_softc *atabus; + struct vnode *vp; + int bmajor, error; + dev_t dev; + uint32_t drive; + uint8_t checksum, *ptr; + int count, disk; + struct ataraid_array_info *aai; + struct ataraid_disk_info *adi; + + info = malloc(sizeof(*info), M_DEVBUF, M_WAITOK); + + bmajor = devsw_name2blk(sc->sc_dev.dv_xname, 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, 0); + if (error) { + vput(vp); + goto out; + } + + error = ata_raid_config_block_rw(vp, VIA_LBA(sc), info, + sizeof(*info), B_READ); + vput(vp); + if (error) { + printf("%s: error %d reading VIA V-RAID config block\n", + sc->sc_dev.dv_xname, error); + goto out; + } + +#ifdef ATA_RAID_DEBUG + ata_raid_via_print_info(info); +#endif + + printf("MAGIC == 0x%02x\n", info->magic); + /* Check the signature. */ + if (info->magic != VIA_MAGIC) { + DPRINTF(("%s: VIA V-RAID signature check failed\n", + sc->sc_dev.dv_xname)); + error = ESRCH; + goto out; + } + + /* calculate checksum and compare for valid */ + for (checksum = 0, ptr = (uint8_t *)info, count = 0; count < 50; + count++) + if (count == 3) + checksum += *ptr++ & ~ VIA_T_BOOTABLE; + else + checksum += *ptr++; + if (checksum != info->checksum) { + DPRINTF(("%s: VIA V-RAID checksum failed 0x%02x != 0x%02x\n", + sc->sc_dev.dv_xname, checksum, info->checksum)); + error = ESRCH; + goto out; + } + + /* + * Lookup or allocate a new array info structure for + * this array. Use the serial number of disk0 as the array# + */ + aai = ata_raid_get_array_info(ATA_RAID_TYPE_VIA, info->disks[0]); + + aai->aai_status = AAI_S_READY; + + switch (info->type & VIA_T_MASK) { + case VIA_T_RAID0: + aai->aai_level = AAI_L_RAID0; + aai->aai_width = info->stripe_layout & VIA_L_DISKS; + aai->aai_capacity = aai->aai_width * info->disk_sectors; + break; + + case VIA_T_RAID1: + aai->aai_level = AAI_L_RAID1; + aai->aai_width = 1; + aai->aai_capacity = aai->aai_width * info->disk_sectors; + break; + + case VIA_T_RAID5: + aai->aai_level = AAI_L_RAID5; + aai->aai_width = info->stripe_layout & VIA_L_DISKS; + aai->aai_capacity = (aai->aai_width - 1) * info->disk_sectors; + break; + + case VIA_T_SPAN: + aai->aai_level = AAI_L_SPAN; + aai->aai_width = 1; + aai->aai_capacity += info->disk_sectors; /* XXX ??? */ + break; + + default: + aprint_error("%s: unknown VIA V-RAID type 0x%02x\n", + sc->sc_dev.dv_xname, info->type); + error = EINVAL; + goto out; + } + + aai->aai_type = ATA_RAID_TYPE_VIA; + for (count = 0, disk = 0; disk < 8; disk++) + if (info->disks[disk]) + count++; + aai->aai_interleave = + 0x08 << ((info->stripe_layout & VIA_L_MASK) >> VIA_L_SHIFT); + aai->aai_ndisks = count; + aai->aai_heads = 255; + aai->aai_sectors = 63; + aai->aai_cylinders = aai->aai_capacity / (63 * 255); + aai->aai_offset = 0; + aai->aai_reserved = 1; + + /* XXX - bogus. RAID1 shouldn't really have an interleave */ + if (aai->aai_interleave == 0) + aai->aai_interleave = aai->aai_capacity; + + atabus = (struct atabus_softc *) device_parent(&sc->sc_dev); + drive = atabus->sc_chan->ch_channel; + if (drive >= aai->aai_ndisks) { + aprint_error("%s: drive number %d doesn't make sense within " + "%d-disk array\n", + sc->sc_dev.dv_xname, drive, aai->aai_ndisks); + error = EINVAL; + goto out; + } + + adi = &aai->aai_disks[drive]; + adi->adi_dev = &sc->sc_dev; + adi->adi_status = ADI_S_ONLINE | ADI_S_ASSIGNED; + adi->adi_sectors = aai->aai_capacity; + adi->adi_compsize = info->disk_sectors; + + error = 0; + + out: + free(info, M_DEVBUF); + return (error); +} diff --git a/sys/dev/ata/ata_raidreg.h b/sys/dev/ata/ata_raidreg.h index c88be7db7ea..04dd5bef061 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.3 2005/12/11 12:21:14 christos Exp $ */ +/* $NetBSD: ata_raidreg.h,v 1.4 2007/03/27 00:10:20 garbled Exp $ */ /*- * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> @@ -170,4 +170,36 @@ struct adaptec_raid_conf { uint32_t dummy_9[62]; } __attribute__((__packed__)); +/* VIA Tech V-RAID Metadata */ +/* Derrived from FreeBSD ata-raid.h 1.46 */ +#define VIA_LBA(wd) ((wd)->sc_capacity - 1) + +struct via_raid_conf { + uint16_t magic; +#define VIA_MAGIC 0xaa55 + uint8_t dummy_0; + uint8_t type; +#define VIA_T_MASK 0x7e +#define VIA_T_BOOTABLE 0x01 +#define VIA_T_RAID0 0x04 +#define VIA_T_RAID1 0x0c +#define VIA_T_RAID01 0x4c +#define VIA_T_RAID5 0x2c +#define VIA_T_SPAN 0x44 +#define VIA_T_UNKNOWN 0x80 + uint8_t disk_index; +#define VIA_D_MASK 0x0f +#define VIA_D_DEGRADED 0x10 +#define VIA_D_HIGH_IDX 0x20 + uint8_t stripe_layout; +#define VIA_L_DISKS 0x07 +#define VIA_L_MASK 0xf0 +#define VIA_L_SHIFT 4 + uint64_t disk_sectors; + uint32_t disk_id; + uint32_t disks[8]; + uint8_t checksum; + uint8_t pad_0[461]; +} __attribute__((__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 6ffd4ed5baa..50ee7072d6a 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.4 2005/12/11 12:21:14 christos Exp $ */ +/* $NetBSD: ata_raidvar.h,v 1.5 2007/03/27 00:10:20 garbled Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -50,7 +50,8 @@ */ #define ATA_RAID_TYPE_PROMISE 0 #define ATA_RAID_TYPE_ADAPTEC 1 -#define ATA_RAID_TYPE_MAX 1 +#define ATA_RAID_TYPE_VIA 2 +#define ATA_RAID_TYPE_MAX 2 /* * Max # of disks supported by a single array. This is limited by @@ -101,6 +102,7 @@ struct ataraid_array_info { #define AAI_L_SPAN 0x01 #define AAI_L_RAID0 0x02 #define AAI_L_RAID1 0x04 +#define AAI_L_RAID5 0x08 /* aai_status */ #define AAI_S_READY 0x01 @@ -125,4 +127,7 @@ int ata_raid_read_config_promise(struct wd_softc *); /* Adaptec HostRAID support */ int ata_raid_read_config_adaptec(struct wd_softc *); +/* VIA V-RAID support */ +int ata_raid_read_config_via(struct wd_softc *); + #endif /* _DEV_ATA_ATA_RAIDVAR_H_ */ diff --git a/sys/dev/ata/files.ata b/sys/dev/ata/files.ata index 023cc83212e..0420620eb4a 100644 --- a/sys/dev/ata/files.ata +++ b/sys/dev/ata/files.ata @@ -1,4 +1,4 @@ -# $NetBSD: files.ata,v 1.14 2006/10/25 20:14:00 bouyer Exp $ +# $NetBSD: files.ata,v 1.15 2007/03/27 00:10:20 garbled Exp $ # # Config file and device description for machine-independent devices # which attach to ATA busses. Included by ports that need it. Ports @@ -20,6 +20,7 @@ defpseudo ataraid {[vendtype = -1], [unit = -1]} file dev/ata/ata_raid.c ataraid needs-flag file dev/ata/ata_raid_promise.c ataraid file dev/ata/ata_raid_adaptec.c ataraid +file dev/ata/ata_raid_via.c ataraid attach ld at ataraid with ld_ataraid file dev/ata/ld_ataraid.c ld_ataraid |
