diff --git a/share/man/man4/ataraid.4 b/share/man/man4/ataraid.4 index 837434dfc8f8..e0615cae92b7 100644 --- a/share/man/man4/ataraid.4 +++ b/share/man/man4/ataraid.4 @@ -1,4 +1,4 @@ -.\" $NetBSD: ataraid.4,v 1.6 2008/04/30 13:10:53 martin Exp $ +.\" $NetBSD: ataraid.4,v 1.7 2008/08/20 15:00:34 tacha Exp $ .\" .\" Copyright (c) 2005 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -53,6 +53,8 @@ Promise FastTrak Adaptec HostRAID (found in Intel 6300ESB) .It Via V-RAID (found in many VIA-based motherboards) +.It +nVidia MediaSheild .El .Sh SEE ALSO .Xr ld 4 diff --git a/sys/dev/ata/ata_raid.c b/sys/dev/ata/ata_raid.c index 5a876bb1b736..2a611161fda4 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.29 2008/06/17 14:53:10 reinoud Exp $ */ +/* $NetBSD: ata_raid.c,v 1.30 2008/08/20 15:00:34 tacha Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ata_raid.c,v 1.29 2008/06/17 14:53:10 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_raid.c,v 1.30 2008/08/20 15:00:34 tacha Exp $"); #include #include @@ -115,6 +115,7 @@ ata_raid_type_name(u_int type) "Promise", "Adaptec", "VIA V-RAID", + "nVidia", }; if (type < sizeof(ata_raid_type_names) / sizeof(ata_raid_type_names[0])) @@ -244,6 +245,8 @@ ata_raid_check_component(device_t self) return; if (ata_raid_read_config_via(sc) == 0) return; + if (ata_raid_read_config_nvidia(sc) == 0) + return; } struct ataraid_array_info * diff --git a/sys/dev/ata/ata_raid_nvidia.c b/sys/dev/ata/ata_raid_nvidia.c new file mode 100644 index 000000000000..64e4bd87d297 --- /dev/null +++ b/sys/dev/ata/ata_raid_nvidia.c @@ -0,0 +1,261 @@ +/* $NetBSD: ata_raid_nvidia.c,v 1.1 2008/08/20 15:00:34 tacha Exp $ */ + +/*- + * Copyright (c) 2000 - 2008 Søren Schmidt + * 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 nVIDIA MediaShield RAID controller configuration blocks. + * + * Adapted to NetBSD by Tatoku Ogaito (tacha@NetBSD.org) + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: ata_raid_nvidia.c,v 1.1 2008/08/20 15:00:34 tacha Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#ifdef ATA_RAID_DEBUG +#define DPRINTF(x) printf x +#else +#define DPRINTF(x) /* nothing */ +#endif + +#ifdef ATA_RAID_DEBUG +static const 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_info(struct nvidia_raid_conf *info) +{ + printf("******** ATA nVidia MediaShield Metadata ********\n"); + printf("nvidia_id <%.8s>\n", info->nvidia_id); + printf("config_size %d\n", info->config_size); + printf("checksum 0x%08x\n", info->checksum); + printf("version 0x%04x\n", info->version); + printf("disk_number %d\n", info->disk_number); + printf("dummy_0 0x%02x\n", info->dummy_0); + printf("total_sectors %d\n", info->total_sectors); + printf("sectors_size %d\n", info->sector_size); + printf("serial %.16s\n", info->serial); + printf("revision %.4s\n", info->revision); + printf("dummy_1 0x%08x\n", info->dummy_1); + printf("magic_0 0x%08x\n", info->magic_0); + printf("magic_1 0x%016jx\n", info->magic_1); + printf("magic_2 0x%016jx\n", info->magic_2); + printf("flags 0x%02x\n", info->flags); + printf("array_width %d\n", info->array_width); + printf("total_disks %d\n", info->total_disks); + printf("dummy_2 0x%02x\n", info->dummy_2); + printf("type %s\n", ata_raid_nvidia_type(info->type)); + printf("dummy_3 0x%04x\n", info->dummy_3); + printf("stripe_sectors %d\n", info->stripe_sectors); + printf("stripe_bytes %d\n", info->stripe_bytes); + printf("stripe_shift %d\n", info->stripe_shift); + printf("stripe_mask 0x%08x\n", info->stripe_mask); + printf("stripe_sizesectors %d\n", info->stripe_sizesectors); + printf("stripe_sizebytes %d\n", info->stripe_sizebytes); + printf("rebuild_lba %d\n", info->rebuild_lba); + printf("dummy_4 0x%08x\n", info->dummy_4); + printf("dummy_5 0x%08x\n", info->dummy_5); + printf("status 0x%08x\n", info->status); + printf("=================================================\n"); +} +#endif + +int +ata_raid_read_config_nvidia(struct wd_softc *sc) +{ + struct nvidia_raid_conf *info; + struct vnode *vp; + int bmajor, error, count; + dev_t dev; + uint32_t cksum, *ckptr; + struct ataraid_array_info *aai; + struct ataraid_disk_info *adi; + static struct _arrayno { + uint64_t magic1; + uint64_t magic2; + struct _arrayno *next; + } arrayno = { 0, 0, NULL}, *anptr; + + info = malloc(sizeof(*info), M_DEVBUF, M_WAITOK); + + 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, NVIDIA_LBA(sc), info, + sizeof(*info), B_READ); + VOP_CLOSE(vp, FREAD, NOCRED); + vput(vp); + if (error) { + aprint_error_dev(sc->sc_dev, + "error %d reading nVidia MediaShield config block\n", error); + goto out; + } + +#ifdef ATA_RAID_DEBUG + ata_raid_nvidia_print_info(info); +#endif + + /* Check the signature. */ + if (strncmp(info->nvidia_id, NV_MAGIC, strlen(NV_MAGIC)) != 0) { + DPRINTF(("%s: nVidia signature check failed\n", + device_xname(sc->sc_dev))); + error = ESRCH; + goto out; + } + + /* check if the checksum is OK */ + for (cksum = 0, ckptr = (uint32_t *)info, count = 0; count < info->config_size; + count++) + cksum += *ckptr++; + if (cksum) { + DPRINTF(("%s: nVidia checksum failed (0x%02x)\n", + device_xname(sc->sc_dev), cksum)); + error = ESRCH; + goto out; + } + + /* + * Lookup or allocate a new array info structure for + * this array. Since nVidia raid information does not + * provides array# directory, we must count the number. + * The available traces are magic_1 and magic_2. + */ + for (anptr = &arrayno, count = 0; anptr->next; anptr = anptr->next, count++) { + if (anptr->magic1 == info->magic_1 && + anptr->magic2 == info->magic_2) + break; + } + if (anptr->next == NULL) { + /* new array */ + anptr->magic1 = info->magic_1; + anptr->magic2 = info->magic_2; + anptr->next = malloc(sizeof(arrayno), M_DEVBUF, M_WAITOK); + } + aai = ata_raid_get_array_info(ATA_RAID_TYPE_NVIDIA, count); + + aai->aai_status = AAI_S_READY; + if (info->status & NV_S_DEGRADED) + aai->aai_status |= AAI_S_DEGRADED; + + switch (info->type) { + case NV_T_RAID0: + aai->aai_level = AAI_L_RAID0; + break; + + case NV_T_RAID1: + aai->aai_level = AAI_L_RAID1; + break; + + case NV_T_RAID5: + aai->aai_level = AAI_L_RAID5; + break; + + case NV_T_RAID01: + aai->aai_level = AAI_L_RAID0 | AAI_L_RAID1; + break; + + case NV_T_SPAN: + aai->aai_level = AAI_L_SPAN; + break; + + default: + aprint_error_dev(sc->sc_dev, + "unknown nVidia type 0x%02x\n", info->type); + error = EINVAL; + goto out; + } + + aai->aai_type = ATA_RAID_TYPE_NVIDIA; + aai->aai_interleave = info->stripe_sectors; + aai->aai_width = info->array_width; + + aai->aai_ndisks = info->total_disks; + aai->aai_capacity = info->total_sectors; + aai->aai_heads = 255; + aai->aai_sectors = 63; + aai->aai_cylinders = aai->aai_capacity / (aai->aai_heads * aai->aai_sectors); + aai->aai_offset = 0; + aai->aai_reserved = 2; + + adi = &aai->aai_disks[info->disk_number]; + adi->adi_dev = sc->sc_dev; + adi->adi_status = ADI_S_ONLINE | ADI_S_ASSIGNED; + adi->adi_sectors = aai->aai_capacity; + adi->adi_compsize = aai->aai_capacity / info->array_width; + + 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 af73b291a5e6..1ab2f7dc0e30 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.5 2007/12/25 18:33:36 perry Exp $ */ +/* $NetBSD: ata_raidreg.h,v 1.6 2008/08/20 15:00:34 tacha Exp $ */ /*- * Copyright (c) 2000,2001,2002 Søren Schmidt @@ -202,4 +202,57 @@ struct via_raid_conf { uint8_t pad_0[461]; } __packed; +/* nVidia MediaShield Metadata */ +/* taken from FreeBSD ata-raid.h 1.47 */ +#define NVIDIA_LBA(wd) ((wd)->sc_capacity - 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; + #endif /* _DEV_PCI_PCIIDE_PROMISE_RAID_H_ */ diff --git a/sys/dev/ata/ata_raidvar.h b/sys/dev/ata/ata_raidvar.h index 50ee7072d6a0..fc146e96ec21 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.5 2007/03/27 00:10:20 garbled Exp $ */ +/* $NetBSD: ata_raidvar.h,v 1.6 2008/08/20 15:00:34 tacha Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -51,7 +51,8 @@ #define ATA_RAID_TYPE_PROMISE 0 #define ATA_RAID_TYPE_ADAPTEC 1 #define ATA_RAID_TYPE_VIA 2 -#define ATA_RAID_TYPE_MAX 2 +#define ATA_RAID_TYPE_NVIDIA 3 +#define ATA_RAID_TYPE_MAX 3 /* * Max # of disks supported by a single array. This is limited by @@ -130,4 +131,7 @@ int ata_raid_read_config_adaptec(struct wd_softc *); /* VIA V-RAID support */ int ata_raid_read_config_via(struct wd_softc *); +/* nVidia MediaShield support */ +int ata_raid_read_config_nvidia(struct wd_softc *); + #endif /* _DEV_ATA_ATA_RAIDVAR_H_ */ diff --git a/sys/dev/ata/files.ata b/sys/dev/ata/files.ata index 9a93db660ec0..264cd29cf24c 100644 --- a/sys/dev/ata/files.ata +++ b/sys/dev/ata/files.ata @@ -1,4 +1,4 @@ -# $NetBSD: files.ata,v 1.16 2008/06/10 12:49:16 drochner Exp $ +# $NetBSD: files.ata,v 1.17 2008/08/20 15:00:34 tacha 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 @@ defpseudodev 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_nvidia.c ataraid file dev/ata/ata_raid_via.c ataraid attach ld at ataraid with ld_ataraid