From 61cb552b1a1935425b2f367e08d30751c4d3692d Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Tue, 28 Oct 2008 11:00:41 +0000 Subject: Add beginings of bio. Disabled for now. dlg "go go go" --- sys/dev/ic/mpi.c | 305 +++++++++++++++++++++++++++++++++++++++++++++++--- sys/dev/ic/mpireg.h | 4 +- sys/dev/ic/mpivar.h | 14 ++- sys/dev/pci/mpi_pci.c | 5 +- 4 files changed, 309 insertions(+), 19 deletions(-) (limited to 'sys') diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c index e8b0698410a..232df036827 100644 --- a/sys/dev/ic/mpi.c +++ b/sys/dev/ic/mpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi.c,v 1.98 2008/10/07 12:34:30 dlg Exp $ */ +/* $OpenBSD: mpi.c,v 1.99 2008/10/28 11:00:40 marco Exp $ */ /* * Copyright (c) 2005, 2006 David Gwynne @@ -17,19 +17,25 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "bio.h" + #include #include #include #include +#include #include #include #include +#include +#include #include #include #include +#include #include #include @@ -138,6 +144,18 @@ int mpi_req_cfg_header(struct mpi_softc *, u_int8_t, int mpi_req_cfg_page(struct mpi_softc *, u_int32_t, int, void *, int, void *, size_t); +#if NBIO > 0 +int mpi_ioctl(struct device *, u_long, caddr_t); +int mpi_ioctl_inq(struct mpi_softc *, struct bioc_inq *); +int mpi_ioctl_vol(struct mpi_softc *, struct bioc_vol *); +int mpi_ioctl_disk(struct mpi_softc *, struct bioc_disk *); +int mpi_ioctl_setstate(struct mpi_softc *, struct bioc_setstate *); +#ifndef SMALL_KERNEL +int mpi_create_sensors(struct mpi_softc *); +void mpi_refresh_sensors(void *); +#endif /* SMALL_KERNEL */ +#endif /* NBIO > 0 */ + #define DEVNAME(s) ((s)->sc_dev.dv_xname) #define dwordsof(s) (sizeof(s) / sizeof(u_int32_t)) @@ -241,6 +259,8 @@ mpi_attach(struct mpi_softc *sc) mpi_squash_ppr(sc); } + rw_init(&sc->sc_lock, "mpi_lock"); + /* we should be good to go now, attach scsibus */ sc->sc_link.device = &mpi_dev; sc->sc_link.adapter = &mpi_switch; @@ -266,6 +286,37 @@ mpi_attach(struct mpi_softc *sc) /* enable interrupts */ mpi_write(sc, MPI_INTR_MASK, MPI_INTR_MASK_DOORBELL); +#ifdef notyet +#if NBIO > 0 + if (bio_register(&sc->sc_dev, mpi_ioctl) != 0) + panic("%s: controller registration failed", DEVNAME(sc)); + else { + if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 2, 0, + &sc->sc_cfg_hdr) != 0) { + printf("%s: can't get IOC page 2 hdr, bio disabled\n", + DEVNAME(sc)); + goto done; + } + sc->sc_vol_page = malloc(sc->sc_cfg_hdr.page_length * 4, M_TEMP, + M_WAITOK | M_CANFAIL); + if (sc->sc_vol_page == NULL) { + printf("%s: can't get memory for IOC page 2, " + "bio disabled\n", DEVNAME(sc)); + goto done; + } + sc->sc_vol_list = (struct mpi_cfg_raid_vol *) + (sc->sc_vol_page + 1); + + sc->sc_ioctl = mpi_ioctl; + } +#ifndef SMALL_KERNEL + if (mpi_create_sensors(sc) != 0) + printf("%s: unable to create sensors\n", DEVNAME(sc)); +#endif /* SMALL_KERNEL */ +done: +#endif /* NBIO > 0 */ +#endif /* notyet */ + return (0); free_replies: @@ -1408,26 +1459,26 @@ mpi_scsi_probe(struct scsi_link *link) if (mpi_ecfg_page(sc, address, &ehdr, 1, &pg0, sizeof(pg0)) != 0) return (0); - DPRINTF(MPI_D_MISC, "%s: mpi_scsi_probe sas dev pg 0 for target %d:\n", + DNPRINTF(MPI_D_MISC, "%s: mpi_scsi_probe sas dev pg 0 for target %d:\n", DEVNAME(sc), link->target); - DPRINTF(MPI_D_MISC, "%s: slot: 0x%04x enc_handle: 0x%04x\n", + DNPRINTF(MPI_D_MISC, "%s: slot: 0x%04x enc_handle: 0x%04x\n", DEVNAME(sc), letoh16(pg0.slot), letoh16(pg0.enc_handle)); - DPRINTF(MPI_D_MISC, "%s: sas_addr: 0x%016llx\n", DEVNAME(sc), + DNPRINTF(MPI_D_MISC, "%s: sas_addr: 0x%016llx\n", DEVNAME(sc), letoh64(pg0.sas_addr)); - DPRINTF(MPI_D_MISC, "%s: parent_dev_handle: 0x%04x phy_num: 0x%02x " + DNPRINTF(MPI_D_MISC, "%s: parent_dev_handle: 0x%04x phy_num: 0x%02x " "access_status: 0x%02x\n", DEVNAME(sc), letoh16(pg0.parent_dev_handle), pg0.phy_num, pg0.access_status); - DPRINTF(MPI_D_MISC, "%s: dev_handle: 0x%04x " + DNPRINTF(MPI_D_MISC, "%s: dev_handle: 0x%04x " "bus: 0x%02x target: 0x%02x\n", DEVNAME(sc), letoh16(pg0.dev_handle), pg0.bus, pg0.target); - DPRINTF(MPI_D_MISC, "%s: device_info: 0x%08x\n", DEVNAME(sc), + DNPRINTF(MPI_D_MISC, "%s: device_info: 0x%08x\n", DEVNAME(sc), letoh32(pg0.device_info)); - DPRINTF(MPI_D_MISC, "%s: flags: 0x%04x physical_port: 0x%02x\n", + DNPRINTF(MPI_D_MISC, "%s: flags: 0x%04x physical_port: 0x%02x\n", DEVNAME(sc), letoh16(pg0.flags), pg0.physical_port); if (ISSET(letoh32(pg0.device_info), MPI_CFG_SAS_DEV_0_DEVINFO_ATAPI_DEVICE)) { - DPRINTF(MPI_D_MISC, "%s: target %d is an ATAPI device\n", + DNPRINTF(MPI_D_MISC, "%s: target %d is an ATAPI device\n", DEVNAME(sc), link->target); link->flags |= SDEV_ATAPI; link->quirks |= SDEV_ONLYBIG; @@ -1436,12 +1487,6 @@ mpi_scsi_probe(struct scsi_link *link) return (0); } -int -mpi_scsi_ioctl(struct scsi_link *a, u_long b, caddr_t c, int d, struct proc *e) -{ - return (ENOTTY); -} - u_int32_t mpi_read(struct mpi_softc *sc, bus_size_t r) { @@ -2522,3 +2567,233 @@ mpi_req_cfg_page(struct mpi_softc *sc, u_int32_t address, int extended, return (rv); } + +int +mpi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag, + struct proc *p) +{ + struct mpi_softc *sc = (struct mpi_softc *)link->adapter_softc; + + DNPRINTF(MPI_D_IOCTL, "%s: mpi_scsi_ioctl\n", DEVNAME(sc)); + + if (sc->sc_ioctl) + return (sc->sc_ioctl(link->adapter_softc, cmd, addr)); + else + return (ENOTTY); +} + +#if NBIO > 0 +int +mpi_ioctl(struct device *dev, u_long cmd, caddr_t addr) +{ + struct mpi_softc *sc = (struct mpi_softc *)dev; + int error = 0; + + DNPRINTF(MPI_D_IOCTL, "%s: mpi_ioctl ", DEVNAME(sc)); + + if (!(sc->sc_flags & MPI_F_RAID)) + return (EINVAL); + + /* make sure we have bio enabled */ + if (sc->sc_ioctl != mpi_ioctl) + return (EINVAL); + + rw_enter_write(&sc->sc_lock); + + switch (cmd) { + case BIOCINQ: + DNPRINTF(MPI_D_IOCTL, "inq\n"); + error = mpi_ioctl_inq(sc, (struct bioc_inq *)addr); + break; + + case BIOCVOL: + DNPRINTF(MPI_D_IOCTL, "vol\n"); + error = mpi_ioctl_vol(sc, (struct bioc_vol *)addr); + break; + + case BIOCDISK: + DNPRINTF(MPI_D_IOCTL, "disk\n"); + error = mpi_ioctl_disk(sc, (struct bioc_disk *)addr); + break; + + case BIOCALARM: + DNPRINTF(MPI_D_IOCTL, "alarm\n"); + break; + + case BIOCBLINK: + DNPRINTF(MPI_D_IOCTL, "blink\n"); + break; + + case BIOCSETSTATE: + DNPRINTF(MPI_D_IOCTL, "setstate\n"); + error = mpi_ioctl_setstate(sc, (struct bioc_setstate *)addr); + break; + + default: + DNPRINTF(MPI_D_IOCTL, " invalid ioctl\n"); + error = EINVAL; + } + + rw_exit_write(&sc->sc_lock); + + return (error); +} + +int +mpi_ioctl_inq(struct mpi_softc *sc, struct bioc_inq *bi) +{ + if (mpi_cfg_page(sc, 0, &sc->sc_cfg_hdr, 1, sc->sc_vol_page, + sc->sc_cfg_hdr.page_length * 4) != 0) { + DNPRINTF(MPI_D_IOCTL, "%s: mpi_get_raid unable to fetch IOC " + "page 2\n", DEVNAME(sc)); + return (EINVAL); + } + + DNPRINTF(MPI_D_IOCTL, "%s: active_vols: %d max_vols: %d " + "active_physdisks: %d max_physdisks: %d\n", DEVNAME(sc), + sc->sc_vol_page->active_vols, sc->sc_vol_page->max_vols, + sc->sc_vol_page->active_physdisks, sc->sc_vol_page->max_physdisks); + + bi->bi_novol = sc->sc_vol_page->active_vols; + bi->bi_nodisk = sc->sc_vol_page->active_physdisks; + strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev)); + + return (0); +} + +int +mpi_ioctl_vol(struct mpi_softc *sc, struct bioc_vol *bv) +{ + int i, vol, id, len, rv = EINVAL; + u_int32_t address; + struct device *dev; + struct scsi_link *link; + struct mpi_cfg_hdr hdr;; + struct mpi_cfg_raid_vol_pg0 *rpg0; + struct mpi_cfg_raid_vol_pg0_physdisk *physdisk; + + if (mpi_cfg_page(sc, 0, &sc->sc_cfg_hdr, 1, sc->sc_vol_page, + sc->sc_cfg_hdr.page_length * 4) != 0) { + DNPRINTF(MPI_D_IOCTL, "%s: mpi_get_raid unable to fetch IOC " + "page 2\n", DEVNAME(sc)); + return (EINVAL); + } + + id = bv->bv_volid; + if (id > sc->sc_vol_page->active_vols) + return (EINVAL); /* XXX deal with hot spares */ + + len = sizeof(rpg0) + sc->sc_vol_page->max_physdisks * sizeof(physdisk); + rpg0 = malloc(len, M_TEMP, M_WAITOK | M_CANFAIL); + if (rpg0 == NULL) { + printf("%s: can't get memory for RAID page 0, " + "bio disabled\n", DEVNAME(sc)); + goto done; + } + physdisk = (struct mpi_cfg_raid_vol_pg0_physdisk *)(rpg0 + 1); + + /* get raid vol page 0 */ + address = sc->sc_vol_list[id].vol_id | + (sc->sc_vol_list[id].vol_bus << 8); + if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0, + address, &hdr) != 0) + goto done; + if (mpi_cfg_page(sc, address, &hdr, 1, rpg0, len)) { + printf("%s: can't get RAID vol cfg page 0\n", DEVNAME(sc)); + goto done; + } + + /* determine status */ + switch (rpg0->volume_state) { + case MPI_CFG_RAID_VOL_0_STATE_OPTIMAL: + bv->bv_status = BIOC_SVONLINE; + break; + case MPI_CFG_RAID_VOL_0_STATE_DEGRADED: + bv->bv_status = BIOC_SVDEGRADED; + break; + case MPI_CFG_RAID_VOL_0_STATE_FAILED: + case MPI_CFG_RAID_VOL_0_STATE_MISSING: + bv->bv_status = BIOC_SVOFFLINE; + break; + default: + bv->bv_status = BIOC_SVINVALID; + } + + /* override status if scrubbing or something */ + if (rpg0->volume_status == MPI_CFG_RAID_VOL_0_STATUS_RESYNCING) + bv->bv_status = BIOC_SVREBUILD; + + bv->bv_size = (u_quad_t)letoh32(rpg0->max_lba); + + switch (sc->sc_vol_list[id].vol_type) { + case MPI_CFG_RAID_TYPE_RAID_IS: + bv->bv_level = 0; + break; + case MPI_CFG_RAID_TYPE_RAID_IME: + case MPI_CFG_RAID_TYPE_RAID_IM: + bv->bv_level = 1; + break; + case MPI_CFG_RAID_TYPE_RAID_5: + bv->bv_level = 5; + break; + case MPI_CFG_RAID_TYPE_RAID_6: + bv->bv_level = 6; + break; + case MPI_CFG_RAID_TYPE_RAID_10: + bv->bv_level = 10; + break; + case MPI_CFG_RAID_TYPE_RAID_50: + bv->bv_level = 50; + break; + default: + bv->bv_level = -1; + } + + bv->bv_nodisk = rpg0->num_phys_disks; + + for (i = 0, vol = -1; i < sc->sc_buswidth; i++) { + link = sc->sc_scsibus->sc_link[i][0]; + if (link == NULL) + continue; + + /* skip if not a virtual disk */ + if (!(link->flags & SDEV_VIRTUAL)) + continue; + + vol++; + /* are we it? */ + if (vol == bv->bv_volid) { + dev = link->device_softc; + memcpy(bv->bv_vendor, link->inqdata.vendor, + sizeof bv->bv_vendor); + bv->bv_vendor[sizeof(bv->bv_vendor) - 1] = '\0'; + strlcpy(bv->bv_dev, dev->dv_xname, sizeof bv->bv_dev); + break; + } + } + rv = 0; +done: + free(rpg0, M_DEVBUF); + return (rv); +} + +int +mpi_ioctl_disk(struct mpi_softc *sc, struct bioc_disk *bd) +{ + return (ENOTTY); +} + +int +mpi_ioctl_setstate(struct mpi_softc *sc, struct bioc_setstate *bs) +{ + return (ENOTTY); +} + +#ifndef SMALL_KERNEL +int +mpi_create_sensors(struct mpi_softc *sc) +{ + return (1); +} +#endif /* SMALL_KERNEL */ +#endif /* NBIO > 0 */ diff --git a/sys/dev/ic/mpireg.h b/sys/dev/ic/mpireg.h index 29d7da7845a..b07e3d1cabf 100644 --- a/sys/dev/ic/mpireg.h +++ b/sys/dev/ic/mpireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpireg.h,v 1.34 2008/10/26 19:51:20 marco Exp $ */ +/* $OpenBSD: mpireg.h,v 1.35 2008/10/28 11:00:40 marco Exp $ */ /* * Copyright (c) 2005 David Gwynne @@ -1321,10 +1321,12 @@ struct mpi_cfg_raid_vol_pg0 { #define MPI_CFG_RAID_VOL_0_STATUS_QUIESCED (1<<1) #define MPI_CFG_RAID_VOL_0_STATUS_RESYNCING (1<<2) #define MPI_CFG_RAID_VOL_0_STATUS_ACTIVE (1<<3) +#define MPI_CFG_RAID_VOL_0_STATUS_BADBLOCK_FULL (1<<4) u_int8_t volume_state; #define MPI_CFG_RAID_VOL_0_STATE_OPTIMAL (0x00) #define MPI_CFG_RAID_VOL_0_STATE_DEGRADED (0x01) #define MPI_CFG_RAID_VOL_0_STATE_FAILED (0x02) +#define MPI_CFG_RAID_VOL_0_STATE_MISSING (0x03) u_int16_t reserved1; u_int16_t volume_settings; diff --git a/sys/dev/ic/mpivar.h b/sys/dev/ic/mpivar.h index bc34fb953ff..39f87b0feab 100644 --- a/sys/dev/ic/mpivar.h +++ b/sys/dev/ic/mpivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpivar.h,v 1.22 2007/03/17 10:25:39 dlg Exp $ */ +/* $OpenBSD: mpivar.h,v 1.23 2008/10/28 11:00:40 marco Exp $ */ /* * Copyright (c) 2005 David Gwynne @@ -17,7 +17,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - /* #define MPI_DEBUG */ #ifdef MPI_DEBUG extern uint32_t mpi_debug; @@ -131,6 +130,17 @@ struct mpi_softc { size_t sc_fw_len; struct mpi_dmamem *sc_fw; + + /* scsi ioctl from sd device */ + int (*sc_ioctl)(struct device *, u_long, caddr_t); + + struct rwlock sc_lock; + struct mpi_cfg_hdr sc_cfg_hdr; + struct mpi_cfg_ioc_pg2 *sc_vol_page; + struct mpi_cfg_raid_vol *sc_vol_list; + + struct ksensor *sc_sensors; + struct ksensordev sc_sensordev; }; int mpi_attach(struct mpi_softc *); diff --git a/sys/dev/pci/mpi_pci.c b/sys/dev/pci/mpi_pci.c index b7573eb6878..7531437f3b1 100644 --- a/sys/dev/pci/mpi_pci.c +++ b/sys/dev/pci/mpi_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi_pci.c,v 1.20 2008/05/27 21:52:28 dlg Exp $ */ +/* $OpenBSD: mpi_pci.c,v 1.21 2008/10/28 11:00:40 marco Exp $ */ /* * Copyright (c) 2005 David Gwynne @@ -17,11 +17,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "bio.h" + #include #include #include #include #include +#include #include -- cgit v1.2.3