diff options
author | Alexander Yurchenko <grange@cvs.openbsd.org> | 2009-02-09 20:20:16 +0000 |
---|---|---|
committer | Alexander Yurchenko <grange@cvs.openbsd.org> | 2009-02-09 20:20:16 +0000 |
commit | ecbbaa1f9ab967bf311786cdeed960e3a00fb165 (patch) | |
tree | d38afc3ccba7e0cf19e4a954842a18319f9f40d5 /sys | |
parent | 984eacb1af511448660dce89c1a623b3fc4da030 (diff) |
Start on bioctl support for ips. Only adapter and volume info for now.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/ips.c | 113 |
1 files changed, 111 insertions, 2 deletions
diff --git a/sys/dev/pci/ips.c b/sys/dev/pci/ips.c index fe8fdf2e6cd..8cac8fa82ee 100644 --- a/sys/dev/pci/ips.c +++ b/sys/dev/pci/ips.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ips.c,v 1.38 2009/02/09 20:17:43 grange Exp $ */ +/* $OpenBSD: ips.c,v 1.39 2009/02/09 20:20:15 grange Exp $ */ /* * Copyright (c) 2006, 2007 Alexander Yurchenko <grange@openbsd.org> @@ -20,10 +20,13 @@ * IBM (Adaptec) ServeRAID controller driver. */ +#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/kernel.h> #include <sys/malloc.h> #include <sys/timeout.h> @@ -35,6 +38,8 @@ #include <scsi/scsi_disk.h> #include <scsi/scsiconf.h> +#include <dev/biovar.h> + #include <dev/pci/pcidevs.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -214,6 +219,7 @@ struct ips_softc { struct device sc_dev; struct scsi_link sc_scsi_link; + struct scsibus_softc * sc_scsibus; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; @@ -237,6 +243,10 @@ void ips_attach(struct device *, struct device *, void *); int ips_scsi_cmd(struct scsi_xfer *); +int ips_ioctl(struct device *, u_long, caddr_t); +int ips_ioctl_inq(struct ips_softc *, struct bioc_inq *); +int ips_ioctl_vol(struct ips_softc *, struct bioc_vol *); + int ips_cmd(struct ips_softc *, int, int, u_int32_t, void *, size_t, int, struct scsi_xfer *); int ips_poll(struct ips_softc *, struct ips_ccb *); @@ -487,11 +497,18 @@ ips_attach(struct device *parent, struct device *self, void *aux) bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_scsi_link; - config_found(self, &saa, scsiprint); + sc->sc_scsibus = (struct scsibus_softc *)config_found(self, &saa, + scsiprint); /* Enable interrupts */ ips_intren(sc); +#if NBIO > 0 + /* Install ioctl handler */ + if (bio_register(&sc->sc_dev, ips_ioctl)) + printf("%s: no ioctl support\n", sc->sc_dev.dv_xname); +#endif + return; fail3: ips_ccb_free(sc, sc->sc_ccb, sc->sc_nccbs); @@ -631,6 +648,98 @@ ips_scsi_cmd(struct scsi_xfer *xs) return (COMPLETE); } +#if NBIO > 0 +int +ips_ioctl(struct device *dev, u_long cmd, caddr_t addr) +{ + struct ips_softc *sc = (struct ips_softc *)dev; + + DPRINTF(IPS_D_INFO, ("%s: ioctl %lu\n", sc->sc_dev.dv_xname, cmd)); + + switch (cmd) { + case BIOCINQ: + return (ips_ioctl_inq(sc, (struct bioc_inq *)addr)); + case BIOCVOL: + return (ips_ioctl_vol(sc, (struct bioc_vol *)addr)); + default: + return (ENOTTY); + } +} + +int +ips_ioctl_inq(struct ips_softc *sc, struct bioc_inq *bi) +{ + struct ips_adapterinfo ai; + + if (ips_getadapterinfo(sc, &ai)) + return (EIO); + + strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev)); + bi->bi_novol = sc->sc_nunits; + bi->bi_nodisk = ai.drivecnt; + + return (0); +} + +int +ips_ioctl_vol(struct ips_softc *sc, struct bioc_vol *bv) +{ + struct ips_driveinfo di; + struct ips_drive *drive; + struct device *dev; + struct scsi_link *link; + int id = bv->bv_volid, vol, i; + + if (id >= sc->sc_nunits) + return (EINVAL); + + if (ips_getdriveinfo(sc, &di)) + return (EIO); + drive = &di.drive[id]; + + switch (drive->state) { + case IPS_DS_ONLINE: + bv->bv_status = BIOC_SVONLINE; + break; + case IPS_DS_DEGRADED: + bv->bv_status = BIOC_SVDEGRADED; + break; + case IPS_DS_OFFLINE: + bv->bv_status = BIOC_SVOFFLINE; + break; + default: + bv->bv_status = BIOC_SVINVALID; + } + + bv->bv_size = (u_quad_t)drive->seccnt * IPS_SECSZ; + bv->bv_level = drive->raid; + bv->bv_nodisk = 0; /* XXX */ + + for (i = 0, vol = -1; i < sc->sc_nunits; 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 == id) { + 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; + } + } + + return (0); +} +#endif /* NBIO > 0 */ + int ips_cmd(struct ips_softc *sc, int code, int drive, u_int32_t lba, void *data, size_t size, int flags, struct scsi_xfer *xs) |