summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2008-10-28 11:00:41 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2008-10-28 11:00:41 +0000
commit61cb552b1a1935425b2f367e08d30751c4d3692d (patch)
tree3ff29202012e7f497001176872ff94c6b9823dcd /sys
parent2ee80d0303a231b6478223626a6f89587dc6a975 (diff)
Add beginings of bio. Disabled for now.
dlg "go go go"
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/mpi.c305
-rw-r--r--sys/dev/ic/mpireg.h4
-rw-r--r--sys/dev/ic/mpivar.h14
-rw-r--r--sys/dev/pci/mpi_pci.c5
4 files changed, 309 insertions, 19 deletions
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 <dlg@openbsd.org>
@@ -17,19 +17,25 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "bio.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
+#include <sys/ioctl.h>
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/rwlock.h>
+#include <sys/sensors.h>
#include <machine/bus.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
+#include <dev/biovar.h>
#include <dev/ic/mpireg.h>
#include <dev/ic/mpivar.h>
@@ -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 <dlg@openbsd.org>
@@ -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 <dlg@openbsd.org>
@@ -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 <dlg@openbsd.org>
@@ -17,11 +17,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "bio.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#include <sys/rwlock.h>
#include <machine/bus.h>