Module Name: src Committed By: msaitoh Date: Mon Sep 29 16:15:59 UTC 2014
Modified Files: src/share/man/man4 [netbsd-7]: bio.4 mpt.4 src/sys/dev/ic [netbsd-7]: mpt.c mpt.h mpt_netbsd.c Log Message: Pull up following revision(s) (requested by jmcneill in ticket #120): sys/dev/ic/mpt_netbsd.c: revision 1.28 sys/dev/ic/mpt_netbsd.c: revision 1.29 sys/dev/ic/mpt.c: revision 1.17 sys/dev/ic/mpt_netbsd.c: revision 1.30 sys/dev/ic/mpt_netbsd.c: revision 1.31 share/man/man4/bio.4: revision 1.12 share/man/man4/mpt.4: revision 1.6 sys/dev/ic/mpt.h: revision 1.8 sys/dev/ic/mpt_netbsd.c: revision 1.26 sys/dev/ic/mpt_netbsd.c: revision 1.27 - Add bio(4) support. - xref mpt(4) in bio(4). - xref bio(4) in mpt(4). - show "sd0" instead of "mpt0" for volume device name - include vendor/product/rev info for volumes and their disks. - implement BIOCDISK_NOVOL - for BIOCDISK_NOVOL, set bd_disknovol=true for any disk not associated with a volume for BIOCDISK_NOVOL, when setting bd_disknovol=false, also set bv_volid To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.11.4.1 src/share/man/man4/bio.4 cvs rdiff -u -r1.5 -r1.5.26.1 src/share/man/man4/mpt.4 cvs rdiff -u -r1.16 -r1.16.14.1 src/sys/dev/ic/mpt.c cvs rdiff -u -r1.7 -r1.7.34.1 src/sys/dev/ic/mpt.h cvs rdiff -u -r1.25 -r1.25.2.1 src/sys/dev/ic/mpt_netbsd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man4/bio.4 diff -u src/share/man/man4/bio.4:1.11 src/share/man/man4/bio.4:1.11.4.1 --- src/share/man/man4/bio.4:1.11 Tue Mar 18 18:20:39 2014 +++ src/share/man/man4/bio.4 Mon Sep 29 16:15:59 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: bio.4,v 1.11 2014/03/18 18:20:39 riastradh Exp $ +.\" $NetBSD: bio.4,v 1.11.4.1 2014/09/29 16:15:59 msaitoh Exp $ .\" $OpenBSD: bio.4,v 1.19 2006/09/20 22:22:37 jmc Exp $ .\" .\" Copyright (c) 2002 Niklas Hallqvist @@ -28,7 +28,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 25, 2008 +.Dd Sep 27, 2014 .Dt BIO 4 .Os .Sh NAME @@ -67,6 +67,8 @@ Compaq RAID array controller Compaq Smart ARRAY 5/6 SAS/SATA/SCSI RAID controller .It Xr mfi 4 LSI Logic \*[Am] Dell MegaRAID SAS RAID controller +.It Xr mpt 4 +LSI Fusion-MPT RAID controller .El .Pp The following ioctl calls apply to the Index: src/share/man/man4/mpt.4 diff -u src/share/man/man4/mpt.4:1.5 src/share/man/man4/mpt.4:1.5.26.1 --- src/share/man/man4/mpt.4:1.5 Tue Feb 16 10:11:47 2010 +++ src/share/man/man4/mpt.4 Mon Sep 29 16:15:59 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: mpt.4,v 1.5 2010/02/16 10:11:47 msaitoh Exp $ +.\" $NetBSD: mpt.4,v 1.5.26.1 2014/09/29 16:15:59 msaitoh Exp $ .\" .\" Copyright (c) 2003 Wasabi Systems, Inc. .\" All rights reserved. @@ -33,7 +33,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 16, 2009 +.Dd Sep 27, 2014 .Dt MPT 4 .Os .Sh NAME @@ -84,6 +84,7 @@ FC929X .Pq Dual 2Gb/s Tn Fibre Channel, PCI-X .El .Sh SEE ALSO +.Xr bio 4 , .Xr cd 4 , .Xr ch 4 , .Xr intro 4 , Index: src/sys/dev/ic/mpt.c diff -u src/sys/dev/ic/mpt.c:1.16 src/sys/dev/ic/mpt.c:1.16.14.1 --- src/sys/dev/ic/mpt.c:1.16 Sun Mar 18 21:05:21 2012 +++ src/sys/dev/ic/mpt.c Mon Sep 29 16:15:58 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: mpt.c,v 1.16 2012/03/18 21:05:21 martin Exp $ */ +/* $NetBSD: mpt.c,v 1.16.14.1 2014/09/29 16:15:58 msaitoh Exp $ */ /* * Copyright (c) 2000, 2001 by Greg Ansley @@ -110,7 +110,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.16 2012/03/18 21:05:21 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.16.14.1 2014/09/29 16:15:58 msaitoh Exp $"); #include <dev/ic/mpt.h> @@ -565,10 +565,7 @@ mpt_send_ioc_init(mpt_softc_t *mpt, u_in * Utiltity routine to read configuration headers and pages */ -static int -mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *); - -static int +int mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber, int PageAddress, fCONFIG_PAGE_HEADER *rslt) { @@ -1516,4 +1513,10 @@ mpt2host_config_page_raid_phys_disk_0(fC MPT_2_HOST16(rpd0, ErrorData.SmartCount); } +void +mpt2host_config_page_ioc_2(fCONFIG_PAGE_IOC_2 *ioc2) +{ + MPT_2_HOST32(ioc2, CapabilitiesFlags); +} + #endif Index: src/sys/dev/ic/mpt.h diff -u src/sys/dev/ic/mpt.h:1.7 src/sys/dev/ic/mpt.h:1.7.34.1 --- src/sys/dev/ic/mpt.h:1.7 Wed Apr 28 22:45:27 2010 +++ src/sys/dev/ic/mpt.h Mon Sep 29 16:15:58 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: mpt.h,v 1.7 2010/04/28 22:45:27 chs Exp $ */ +/* $NetBSD: mpt.h,v 1.7.34.1 2014/09/29 16:15:58 msaitoh Exp $ */ /* * Copyright (c) 2000, 2001 by Greg Ansley @@ -173,6 +173,7 @@ void mpt_free_request(mpt_softc_t *, req int mpt_intr(void *); void mpt_check_doorbell(mpt_softc_t *); +int mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *); int mpt_read_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); int mpt_write_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); @@ -212,6 +213,8 @@ void mpt2host_config_page_fc_port_1(fCON void host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *); void mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *); void mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *); +void mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *); +void mpt2host_config_page_ioc_2(fCONFIG_PAGE_IOC_2 *); #else #define mpt2host_sge_simple_union(x) do { ; } while (0) #define mpt2host_iocfacts_reply(x) do { ; } while (0) @@ -230,6 +233,7 @@ void mpt2host_config_page_raid_phys_disk #define mpt2host_config_page_raid_vol_0(x) do { ; } while (0) #define mpt2host_config_page_raid_phys_disk_0(x) \ do { ; } while (0) +#define mpt2host_config_page_ioc_2(x) do { ; } while (0) #endif #endif /* _KERNEL */ Index: src/sys/dev/ic/mpt_netbsd.c diff -u src/sys/dev/ic/mpt_netbsd.c:1.25 src/sys/dev/ic/mpt_netbsd.c:1.25.2.1 --- src/sys/dev/ic/mpt_netbsd.c:1.25 Tue Jul 8 14:18:54 2014 +++ src/sys/dev/ic/mpt_netbsd.c Mon Sep 29 16:15:58 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: mpt_netbsd.c,v 1.25 2014/07/08 14:18:54 chs Exp $ */ +/* $NetBSD: mpt_netbsd.c,v 1.25.2.1 2014/09/29 16:15:58 msaitoh Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -77,11 +77,17 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mpt_netbsd.c,v 1.25 2014/07/08 14:18:54 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mpt_netbsd.c,v 1.25.2.1 2014/09/29 16:15:58 msaitoh Exp $"); + +#include "bio.h" #include <dev/ic/mpt.h> /* pulls in all headers */ #include <sys/scsiio.h> +#if NBIO > 0 +#include <dev/biovar.h> +#endif + static int mpt_poll(mpt_softc_t *, struct scsipi_xfer *, int); static void mpt_timeout(void *); static void mpt_restart(mpt_softc_t *, request_t *); @@ -100,6 +106,16 @@ static void mpt_minphys(struct buf *); static int mpt_ioctl(struct scsipi_channel *, u_long, void *, int, struct proc *); +#if NBIO > 0 +static bool mpt_is_raid(mpt_softc_t *); +static int mpt_bio_ioctl(device_t, u_long, void *); +static int mpt_bio_ioctl_inq(mpt_softc_t *, struct bioc_inq *); +static int mpt_bio_ioctl_vol(mpt_softc_t *, struct bioc_vol *); +static int mpt_bio_ioctl_disk(mpt_softc_t *, struct bioc_disk *); +static int mpt_bio_ioctl_disk_novol(mpt_softc_t *, struct bioc_disk *); +static int mpt_bio_ioctl_setstate(mpt_softc_t *, struct bioc_setstate *); +#endif + void mpt_scsipi_attach(mpt_softc_t *mpt) { @@ -144,6 +160,14 @@ mpt_scsipi_attach(mpt_softc_t *mpt) */ mpt->sc_scsibus_dv = config_found(mpt->sc_dev, &mpt->sc_channel, scsiprint); + +#if NBIO > 0 + if (mpt_is_raid(mpt)) { + if (bio_register(mpt->sc_dev, mpt_bio_ioctl) != 0) + panic("%s: controller registration failed", + device_xname(mpt->sc_dev)); + } +#endif } int @@ -1585,3 +1609,457 @@ mpt_ioctl(struct scsipi_channel *chan, u return (ENOTTY); } } + +#if NBIO > 0 +static fCONFIG_PAGE_IOC_2 * +mpt_get_cfg_page_ioc2(mpt_softc_t *mpt) +{ + fCONFIG_PAGE_HEADER hdr; + fCONFIG_PAGE_IOC_2 *ioc2; + int rv; + + rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_IOC, 2, 0, &hdr); + if (rv) + return NULL; + + ioc2 = malloc(hdr.PageLength * 4, M_DEVBUF, M_WAITOK | M_ZERO); + if (ioc2 == NULL) + return NULL; + + memcpy(ioc2, &hdr, sizeof(hdr)); + + rv = mpt_read_cfg_page(mpt, 0, &ioc2->Header); + if (rv) + goto fail; + mpt2host_config_page_ioc_2(ioc2); + + return ioc2; + +fail: + free(ioc2, M_DEVBUF); + return NULL; +} + +static fCONFIG_PAGE_IOC_3 * +mpt_get_cfg_page_ioc3(mpt_softc_t *mpt) +{ + fCONFIG_PAGE_HEADER hdr; + fCONFIG_PAGE_IOC_3 *ioc3; + int rv; + + rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_IOC, 3, 0, &hdr); + if (rv) + return NULL; + + ioc3 = malloc(hdr.PageLength * 4, M_DEVBUF, M_WAITOK | M_ZERO); + if (ioc3 == NULL) + return NULL; + + memcpy(ioc3, &hdr, sizeof(hdr)); + + rv = mpt_read_cfg_page(mpt, 0, &ioc3->Header); + if (rv) + goto fail; + + return ioc3; + +fail: + free(ioc3, M_DEVBUF); + return NULL; +} + + +static fCONFIG_PAGE_RAID_VOL_0 * +mpt_get_cfg_page_raid_vol0(mpt_softc_t *mpt, int address) +{ + fCONFIG_PAGE_HEADER hdr; + fCONFIG_PAGE_RAID_VOL_0 *rvol0; + int rv; + + rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, + address, &hdr); + if (rv) + return NULL; + + rvol0 = malloc(hdr.PageLength * 4, M_DEVBUF, M_WAITOK | M_ZERO); + if (rvol0 == NULL) + return NULL; + + memcpy(rvol0, &hdr, sizeof(hdr)); + + rv = mpt_read_cfg_page(mpt, address, &rvol0->Header); + if (rv) + goto fail; + mpt2host_config_page_raid_vol_0(rvol0); + + return rvol0; + +fail: + free(rvol0, M_DEVBUF); + return NULL; +} + +static fCONFIG_PAGE_RAID_PHYS_DISK_0 * +mpt_get_cfg_page_raid_phys_disk0(mpt_softc_t *mpt, int address) +{ + fCONFIG_PAGE_HEADER hdr; + fCONFIG_PAGE_RAID_PHYS_DISK_0 *physdisk0; + int rv; + + rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, + address, &hdr); + if (rv) + return NULL; + + physdisk0 = malloc(hdr.PageLength * 4, M_DEVBUF, M_WAITOK | M_ZERO); + if (physdisk0 == NULL) + return NULL; + + memcpy(physdisk0, &hdr, sizeof(hdr)); + + rv = mpt_read_cfg_page(mpt, address, &physdisk0->Header); + if (rv) + goto fail; + mpt2host_config_page_raid_phys_disk_0(physdisk0); + + return physdisk0; + +fail: + free(physdisk0, M_DEVBUF); + return NULL; +} + +static bool +mpt_is_raid(mpt_softc_t *mpt) +{ + fCONFIG_PAGE_IOC_2 *ioc2; + bool is_raid = false; + + ioc2 = mpt_get_cfg_page_ioc2(mpt); + if (ioc2 == NULL) + return false; + + if (ioc2->CapabilitiesFlags != 0xdeadbeef) { + is_raid = !!(ioc2->CapabilitiesFlags & + (MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT| + MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT| + MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT)); + } + + free(ioc2, M_DEVBUF); + + return is_raid; +} + +static int +mpt_bio_ioctl(device_t dev, u_long cmd, void *addr) +{ + mpt_softc_t *mpt = device_private(dev); + int error, s; + + KERNEL_LOCK(1, curlwp); + s = splbio(); + + switch (cmd) { + case BIOCINQ: + error = mpt_bio_ioctl_inq(mpt, addr); + break; + case BIOCVOL: + error = mpt_bio_ioctl_vol(mpt, addr); + break; + case BIOCDISK_NOVOL: + error = mpt_bio_ioctl_disk_novol(mpt, addr); + break; + case BIOCDISK: + error = mpt_bio_ioctl_disk(mpt, addr); + break; + case BIOCSETSTATE: + error = mpt_bio_ioctl_setstate(mpt, addr); + break; + default: + error = EINVAL; + break; + } + + splx(s); + KERNEL_UNLOCK_ONE(curlwp); + + return error; +} + +static int +mpt_bio_ioctl_inq(mpt_softc_t *mpt, struct bioc_inq *bi) +{ + fCONFIG_PAGE_IOC_2 *ioc2; + fCONFIG_PAGE_IOC_3 *ioc3; + + ioc2 = mpt_get_cfg_page_ioc2(mpt); + if (ioc2 == NULL) + return EIO; + ioc3 = mpt_get_cfg_page_ioc3(mpt); + if (ioc3 == NULL) { + free(ioc2, M_DEVBUF); + return EIO; + } + + strlcpy(bi->bi_dev, device_xname(mpt->sc_dev), sizeof(bi->bi_dev)); + bi->bi_novol = ioc2->NumActiveVolumes; + bi->bi_nodisk = ioc3->NumPhysDisks; + + free(ioc2, M_DEVBUF); + free(ioc3, M_DEVBUF); + + return 0; +} + +static int +mpt_bio_ioctl_vol(mpt_softc_t *mpt, struct bioc_vol *bv) +{ + fCONFIG_PAGE_IOC_2 *ioc2 = NULL; + fCONFIG_PAGE_IOC_2_RAID_VOL *ioc2rvol; + fCONFIG_PAGE_RAID_VOL_0 *rvol0 = NULL; + struct scsipi_periph *periph; + struct scsipi_inquiry_data inqbuf; + char vendor[9], product[17], revision[5]; + int address; + + ioc2 = mpt_get_cfg_page_ioc2(mpt); + if (ioc2 == NULL) + return EIO; + + if (bv->bv_volid < 0 || bv->bv_volid >= ioc2->NumActiveVolumes) + goto fail; + + ioc2rvol = &ioc2->RaidVolume[bv->bv_volid]; + address = ioc2rvol->VolumeID | (ioc2rvol->VolumeBus << 8); + + rvol0 = mpt_get_cfg_page_raid_vol0(mpt, address); + if (rvol0 == NULL) + goto fail; + + bv->bv_dev[0] = '\0'; + bv->bv_vendor[0] = '\0'; + + periph = scsipi_lookup_periph(&mpt->sc_channel, ioc2rvol->VolumeBus, 0); + if (periph != NULL) { + if (periph->periph_dev != NULL) { + snprintf(bv->bv_dev, sizeof(bv->bv_dev), "%s", + device_xname(periph->periph_dev)); + } + memset(&inqbuf, 0, sizeof(inqbuf)); + if (scsipi_inquire(periph, &inqbuf, + XS_CTL_DISCOVERY | XS_CTL_SILENT) == 0) { + scsipi_strvis(vendor, sizeof(vendor), + inqbuf.vendor, sizeof(inqbuf.vendor)); + scsipi_strvis(product, sizeof(product), + inqbuf.product, sizeof(inqbuf.product)); + scsipi_strvis(revision, sizeof(revision), + inqbuf.revision, sizeof(inqbuf.revision)); + + snprintf(bv->bv_vendor, sizeof(bv->bv_vendor), + "%s %s %s", vendor, product, revision); + } + + snprintf(bv->bv_dev, sizeof(bv->bv_dev), "%s", + device_xname(periph->periph_dev)); + } + bv->bv_nodisk = rvol0->NumPhysDisks; + bv->bv_size = (uint64_t)rvol0->MaxLBA * 512; + bv->bv_stripe_size = rvol0->StripeSize; + bv->bv_percent = -1; + bv->bv_seconds = 0; + + switch (rvol0->VolumeStatus.State) { + case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: + bv->bv_status = BIOC_SVONLINE; + break; + case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: + bv->bv_status = BIOC_SVDEGRADED; + break; + case MPI_RAIDVOL0_STATUS_STATE_FAILED: + bv->bv_status = BIOC_SVOFFLINE; + break; + default: + bv->bv_status = BIOC_SVINVALID; + break; + } + + switch (ioc2rvol->VolumeType) { + case MPI_RAID_VOL_TYPE_IS: + bv->bv_level = 0; + break; + case MPI_RAID_VOL_TYPE_IME: + case MPI_RAID_VOL_TYPE_IM: + bv->bv_level = 1; + break; + default: + bv->bv_level = -1; + break; + } + + free(ioc2, M_DEVBUF); + free(rvol0, M_DEVBUF); + + return 0; + +fail: + if (ioc2) free(ioc2, M_DEVBUF); + if (rvol0) free(rvol0, M_DEVBUF); + return EINVAL; +} + +static void +mpt_bio_ioctl_disk_common(mpt_softc_t *mpt, struct bioc_disk *bd, + int address) +{ + fCONFIG_PAGE_RAID_PHYS_DISK_0 *phys = NULL; + char vendor_id[9], product_id[17], product_rev_level[5]; + + phys = mpt_get_cfg_page_raid_phys_disk0(mpt, address); + if (phys == NULL) + return; + + scsipi_strvis(vendor_id, sizeof(vendor_id), + phys->InquiryData.VendorID, sizeof(phys->InquiryData.VendorID)); + scsipi_strvis(product_id, sizeof(product_id), + phys->InquiryData.ProductID, sizeof(phys->InquiryData.ProductID)); + scsipi_strvis(product_rev_level, sizeof(product_rev_level), + phys->InquiryData.ProductRevLevel, + sizeof(phys->InquiryData.ProductRevLevel)); + + snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s %s", + vendor_id, product_id, product_rev_level); + strlcpy(bd->bd_serial, phys->InquiryData.Info, sizeof(bd->bd_serial)); + bd->bd_procdev[0] = '\0'; + bd->bd_channel = phys->PhysDiskBus; + bd->bd_target = phys->PhysDiskID; + bd->bd_lun = 0; + bd->bd_size = (uint64_t)phys->MaxLBA * 512; + + switch (phys->PhysDiskStatus.State) { + case MPI_PHYSDISK0_STATUS_ONLINE: + bd->bd_status = BIOC_SDONLINE; + break; + case MPI_PHYSDISK0_STATUS_MISSING: + case MPI_PHYSDISK0_STATUS_FAILED: + bd->bd_status = BIOC_SDFAILED; + break; + case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED: + case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED: + case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE: + bd->bd_status = BIOC_SDOFFLINE; + break; + case MPI_PHYSDISK0_STATUS_INITIALIZING: + bd->bd_status = BIOC_SDSCRUB; + break; + case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE: + default: + bd->bd_status = BIOC_SDINVALID; + break; + } + + free(phys, M_DEVBUF); +} + +static int +mpt_bio_ioctl_disk_novol(mpt_softc_t *mpt, struct bioc_disk *bd) +{ + fCONFIG_PAGE_IOC_2 *ioc2 = NULL; + fCONFIG_PAGE_IOC_3 *ioc3 = NULL; + fCONFIG_PAGE_RAID_VOL_0 *rvol0 = NULL; + fCONFIG_PAGE_IOC_2_RAID_VOL *ioc2rvol; + int address, v, d; + + ioc2 = mpt_get_cfg_page_ioc2(mpt); + if (ioc2 == NULL) + return EIO; + ioc3 = mpt_get_cfg_page_ioc3(mpt); + if (ioc3 == NULL) { + free(ioc2, M_DEVBUF); + return EIO; + } + + if (bd->bd_diskid < 0 || bd->bd_diskid >= ioc3->NumPhysDisks) + goto fail; + + address = ioc3->PhysDisk[bd->bd_diskid].PhysDiskNum; + + mpt_bio_ioctl_disk_common(mpt, bd, address); + + bd->bd_disknovol = true; + for (v = 0; bd->bd_disknovol && v < ioc2->NumActiveVolumes; v++) { + ioc2rvol = &ioc2->RaidVolume[v]; + address = ioc2rvol->VolumeID | (ioc2rvol->VolumeBus << 8); + + rvol0 = mpt_get_cfg_page_raid_vol0(mpt, address); + if (rvol0 == NULL) + continue; + + for (d = 0; d < rvol0->NumPhysDisks; d++) { + if (rvol0->PhysDisk[d].PhysDiskNum == + ioc3->PhysDisk[bd->bd_diskid].PhysDiskNum) { + bd->bd_disknovol = false; + bd->bd_volid = v; + break; + } + } + free(rvol0, M_DEVBUF); + } + + free(ioc3, M_DEVBUF); + free(ioc2, M_DEVBUF); + + return 0; + +fail: + if (ioc3) free(ioc3, M_DEVBUF); + if (ioc2) free(ioc2, M_DEVBUF); + return EINVAL; +} + + +static int +mpt_bio_ioctl_disk(mpt_softc_t *mpt, struct bioc_disk *bd) +{ + fCONFIG_PAGE_IOC_2 *ioc2 = NULL; + fCONFIG_PAGE_RAID_VOL_0 *rvol0 = NULL; + fCONFIG_PAGE_IOC_2_RAID_VOL *ioc2rvol; + int address; + + ioc2 = mpt_get_cfg_page_ioc2(mpt); + if (ioc2 == NULL) + return EIO; + + if (bd->bd_volid < 0 || bd->bd_volid >= ioc2->NumActiveVolumes) + goto fail; + + ioc2rvol = &ioc2->RaidVolume[bd->bd_volid]; + address = ioc2rvol->VolumeID | (ioc2rvol->VolumeBus << 8); + + rvol0 = mpt_get_cfg_page_raid_vol0(mpt, address); + if (rvol0 == NULL) + goto fail; + + if (bd->bd_diskid < 0 || bd->bd_diskid >= rvol0->NumPhysDisks) + goto fail; + + address = rvol0->PhysDisk[bd->bd_diskid].PhysDiskNum; + + mpt_bio_ioctl_disk_common(mpt, bd, address); + + free(ioc2, M_DEVBUF); + + return 0; + +fail: + if (ioc2) free(ioc2, M_DEVBUF); + return EINVAL; +} + +static int +mpt_bio_ioctl_setstate(mpt_softc_t *mpt, struct bioc_setstate *bs) +{ + return ENOTTY; +} +#endif +