From 25f901a460d2754af44a5d5e1fd9a9e08c3bce23 Mon Sep 17 00:00:00 2001 From: tron Date: Mon, 15 Sep 2008 11:44:50 +0000 Subject: [PATCH] Add support for status reports via bio(4) to ataraid(4). The code was contributed by Juan RP in PR kern/39514. --- share/man/man4/ataraid.4 | 12 ++- sys/dev/ata/ata_raid_adaptec.c | 7 +- sys/dev/ata/ata_raid_intel.c | 6 +- sys/dev/ata/ata_raid_jmicron.c | 6 +- sys/dev/ata/ata_raidvar.h | 4 +- sys/dev/ata/ld_ataraid.c | 163 ++++++++++++++++++++++++++++++++- 6 files changed, 186 insertions(+), 12 deletions(-) diff --git a/share/man/man4/ataraid.4 b/share/man/man4/ataraid.4 index 911dca2fc8ec..10f22c67f5d2 100644 --- a/share/man/man4/ataraid.4 +++ b/share/man/man4/ataraid.4 @@ -1,4 +1,4 @@ -.\" $NetBSD: ataraid.4,v 1.12 2008/09/11 11:18:11 wiz Exp $ +.\" $NetBSD: ataraid.4,v 1.13 2008/09/15 11:44:50 tron Exp $ .\" .\" Copyright (c) 2005 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd September 11, 2008 +.Dd September 15, 2008 .Dt ATARAID 4 .Os .Sh NAME @@ -61,8 +61,14 @@ Promise FastTrak .It Via V-RAID (found in many VIA-based motherboards) .El +.Pp +Status of the logical disk as well as the disks associated with it, +can be viewed through the +.Xr bioctl 8 +utility. .Sh SEE ALSO -.Xr ld 4 +.Xr ld 4 , +.Xr bioctl 8 .Sh HISTORY The .Nm diff --git a/sys/dev/ata/ata_raid_adaptec.c b/sys/dev/ata/ata_raid_adaptec.c index 1bb9cb115806..e2969cbec3b6 100644 --- a/sys/dev/ata/ata_raid_adaptec.c +++ b/sys/dev/ata/ata_raid_adaptec.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata_raid_adaptec.c,v 1.8 2008/03/18 20:46:36 cube Exp $ */ +/* $NetBSD: ata_raid_adaptec.c,v 1.9 2008/09/15 11:44:50 tron Exp $ */ /*- * Copyright (c) 2000,2001,2002 Søren Schmidt @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ata_raid_adaptec.c,v 1.8 2008/03/18 20:46:36 cube Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_raid_adaptec.c,v 1.9 2008/09/15 11:44:50 tron Exp $"); #include #include @@ -160,6 +160,9 @@ ata_raid_read_config_adaptec(struct wd_softc *sc) aai->aai_cylinders = aai->aai_capacity / (63 * 255); aai->aai_offset = 0; aai->aai_reserved = 17; + if (info->configs[0].name) + strlcpy(aai->aai_name, info->configs[0].name, + sizeof(aai->aai_name)); /* XXX - bogus. RAID1 shouldn't really have an interleave */ if (aai->aai_interleave == 0) diff --git a/sys/dev/ata/ata_raid_intel.c b/sys/dev/ata/ata_raid_intel.c index 2afc07869a1f..0c1f2b1e3aec 100644 --- a/sys/dev/ata/ata_raid_intel.c +++ b/sys/dev/ata/ata_raid_intel.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata_raid_intel.c,v 1.1 2008/09/11 11:08:50 tron Exp $ */ +/* $NetBSD: ata_raid_intel.c,v 1.2 2008/09/15 11:44:50 tron Exp $ */ /*- * Copyright (c) 2000-2008 Søren Schmidt @@ -33,7 +33,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ata_raid_intel.c,v 1.1 2008/09/11 11:08:50 tron Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_raid_intel.c,v 1.2 2008/09/15 11:44:50 tron Exp $"); #include #include @@ -252,6 +252,8 @@ ata_raid_read_config_intel(struct wd_softc *sc) aai->aai_capacity / (aai->aai_heads * aai->aai_sectors); aai->aai_offset = map->offset; aai->aai_reserved = 3; + if (map->name) + strlcpy(aai->aai_name, map->name, sizeof(aai->aai_name)); /* Fill in disk info */ adi = &aai->aai_disks[curdrive]; diff --git a/sys/dev/ata/ata_raid_jmicron.c b/sys/dev/ata/ata_raid_jmicron.c index d10861978474..ac4e3a17bb2b 100644 --- a/sys/dev/ata/ata_raid_jmicron.c +++ b/sys/dev/ata/ata_raid_jmicron.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata_raid_jmicron.c,v 1.2 2008/09/10 16:59:32 tron Exp $ */ +/* $NetBSD: ata_raid_jmicron.c,v 1.3 2008/09/15 11:44:50 tron Exp $ */ /*- * Copyright (c) 2000-2008 Søren Schmidt @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ata_raid_jmicron.c,v 1.2 2008/09/10 16:59:32 tron Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_raid_jmicron.c,v 1.3 2008/09/15 11:44:50 tron Exp $"); #include #include @@ -240,6 +240,8 @@ ata_raid_read_config_jmicron(struct wd_softc *sc) aai->aai_capacity / (aai->aai_heads * aai->aai_sectors); aai->aai_offset = info->offset * 16; aai->aai_reserved = 2; + if (info->name) + strlcpy(aai->aai_name, info->name, sizeof(aai->aai_name)); atabus = device_private(device_parent(sc->sc_dev)); drive = atabus->sc_chan->ch_channel; diff --git a/sys/dev/ata/ata_raidvar.h b/sys/dev/ata/ata_raidvar.h index 085221fc19db..72266717c8cf 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.8 2008/09/11 11:08:50 tron Exp $ */ +/* $NetBSD: ata_raidvar.h,v 1.9 2008/09/15 11:44:50 tron Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -98,6 +98,8 @@ struct ataraid_array_info { u_int aai_offset; /* component start offset */ u_int aai_reserved; /* component reserved sectors */ + char aai_name[32]; /* array volume name */ + struct ataraid_disk_info aai_disks[ATA_RAID_MAX_DISKS]; }; diff --git a/sys/dev/ata/ld_ataraid.c b/sys/dev/ata/ld_ataraid.c index 0a020fc51c67..2fc683d9fb01 100644 --- a/sys/dev/ata/ld_ataraid.c +++ b/sys/dev/ata/ld_ataraid.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_ataraid.c,v 1.29 2008/09/09 12:45:39 tron Exp $ */ +/* $NetBSD: ld_ataraid.c,v 1.30 2008/09/15 11:44:50 tron Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -42,11 +42,14 @@ * controllers we're dealing with (Promise, etc.) only support * configuration data on the component disks, with the BIOS supporting * booting from the RAID volumes. + * + * bio(4) support was written by Juan Romero Pardines . */ #include -__KERNEL_RCSID(0, "$NetBSD: ld_ataraid.c,v 1.29 2008/09/09 12:45:39 tron Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_ataraid.c,v 1.30 2008/09/15 11:44:50 tron Exp $"); +#include "bio.h" #include "rnd.h" #include @@ -66,6 +69,13 @@ __KERNEL_RCSID(0, "$NetBSD: ld_ataraid.c,v 1.29 2008/09/09 12:45:39 tron Exp $") #if NRND > 0 #include #endif +#if NBIO > 0 +#include +#include +#include +#include +#include /* for scsipi_strvis() */ +#endif #include @@ -92,6 +102,14 @@ static int ld_ataraid_start_span(struct ld_softc *, struct buf *); static int ld_ataraid_start_raid0(struct ld_softc *, struct buf *); static void ld_ataraid_iodone_raid0(struct buf *); +#if NBIO > 0 +static int ld_ataraid_bioctl(device_t, u_long, void *); +static int ld_ataraid_bioinq(struct ld_ataraid_softc *, struct bioc_inq *); +static int ld_ataraid_biovol(struct ld_ataraid_softc *, struct bioc_vol *); +static int ld_ataraid_biodisk(struct ld_ataraid_softc *, + struct bioc_disk *); +#endif + CFATTACH_DECL_NEW(ld_ataraid, sizeof(struct ld_ataraid_softc), ld_ataraid_match, ld_ataraid_attach, NULL, NULL); @@ -233,6 +251,11 @@ ld_ataraid_attach(device_t parent, device_t self, void *aux) } finish: +#if NBIO > 0 + if (bio_register(self, ld_ataraid_bioctl) != 0) + panic("%s: bioctl registration failed\n", + device_xname(ld->sc_dv)); +#endif ldattach(ld); } @@ -541,3 +564,139 @@ ld_ataraid_dump(struct ld_softc *sc, void *data, return (EIO); } + +#if NBIO > 0 +static int +ld_ataraid_bioctl(device_t self, u_long cmd, void *addr) +{ + struct ld_ataraid_softc *sc = device_private(self); + int error = 0; + + switch (cmd) { + case BIOCINQ: + error = ld_ataraid_bioinq(sc, (struct bioc_inq *)addr); + break; + case BIOCVOL: + error = ld_ataraid_biovol(sc, (struct bioc_vol *)addr); + break; + case BIOCDISK: + error = ld_ataraid_biodisk(sc, (struct bioc_disk *)addr); + break; + default: + error = ENOTTY; + break; + } + + return error; +} + +static int +ld_ataraid_bioinq(struct ld_ataraid_softc *sc, struct bioc_inq *bi) +{ + struct ataraid_array_info *aai = sc->sc_aai; + + /* there's always one volume per ld device */ + bi->bi_novol = 1; + bi->bi_nodisk = aai->aai_ndisks; + + return 0; +} + +static int +ld_ataraid_biovol(struct ld_ataraid_softc *sc, struct bioc_vol *bv) +{ + struct ataraid_array_info *aai = sc->sc_aai; + struct ld_softc *ld = &sc->sc_ld; + + /* Fill in data for _this_ volume */ + bv->bv_percent = -1; + bv->bv_seconds = 0; + + switch (aai->aai_status) { + case AAI_S_READY: + bv->bv_status = BIOC_SVONLINE; + break; + case AAI_S_DEGRADED: + bv->bv_status = BIOC_SVDEGRADED; + break; + } + + bv->bv_size = ld->sc_secsize * ld->sc_secperunit; + + switch (aai->aai_level) { + case AAI_L_SPAN: + case AAI_L_RAID0: + bv->bv_stripe_size = aai->aai_interleave; + bv->bv_level = 0; + break; + case AAI_L_RAID1: + bv->bv_stripe_size = 0; + bv->bv_level = 1; + break; + case AAI_L_RAID5: + bv->bv_stripe_size = aai->aai_interleave; + bv->bv_level = 5; + break; + } + + bv->bv_nodisk = aai->aai_ndisks; + strlcpy(bv->bv_dev, device_xname(ld->sc_dv), sizeof(bv->bv_dev)); + if (aai->aai_name) + strlcpy(bv->bv_vendor, aai->aai_name, + sizeof(bv->bv_vendor)); + + return 0; +} + +static int +ld_ataraid_biodisk(struct ld_ataraid_softc *sc, struct bioc_disk *bd) +{ + struct ataraid_array_info *aai = sc->sc_aai; + struct ataraid_disk_info *adi; + struct ld_softc *ld = &sc->sc_ld; + struct atabus_softc *atabus; + struct wd_softc *wd; + char model[81], serial[41], rev[17]; + + /* sanity check */ + if (bd->bd_diskid > aai->aai_ndisks) + return EINVAL; + + adi = &aai->aai_disks[bd->bd_diskid]; + atabus = device_private(device_parent(adi->adi_dev)); + wd = device_private(adi->adi_dev); + + /* fill in data for _this_ disk */ + switch (adi->adi_status) { + case ADI_S_ONLINE | ADI_S_ASSIGNED: + bd->bd_status = BIOC_SDONLINE; + break; + case ADI_S_SPARE: + bd->bd_status = BIOC_SDHOTSPARE; + break; + default: + bd->bd_status = BIOC_SDOFFLINE; + break; + } + + bd->bd_channel = 0; + bd->bd_target = atabus->sc_chan->ch_channel; + bd->bd_lun = 0; + bd->bd_size = (wd->sc_capacity * ld->sc_secsize) - aai->aai_reserved; + + strlcpy(bd->bd_procdev, device_xname(adi->adi_dev), + sizeof(bd->bd_procdev)); + + scsipi_strvis(serial, sizeof(serial), wd->sc_params.atap_serial, + sizeof(wd->sc_params.atap_serial)); + scsipi_strvis(model, sizeof(model), wd->sc_params.atap_model, + sizeof(wd->sc_params.atap_model)); + scsipi_strvis(rev, sizeof(rev), wd->sc_params.atap_revision, + sizeof(wd->sc_params.atap_revision)); + + snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s", model, rev); + strlcpy(bd->bd_serial, serial, sizeof(bd->bd_serial)); + + return 0; +} +#endif /* NBIO > 0 */