diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2016-10-24 03:11:59 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2016-10-24 03:11:59 +0000 |
commit | 861f776aa565f874b0642b16fda8c58b6afd9455 (patch) | |
tree | 167a1fc3fb482916b6c07baf6211b8f2aa05e426 | |
parent | d823c55d6e4b52be771013a1d80d120f6c90f5c4 (diff) |
Add scsi ioctl hook to do a special treatment for DIOC{G,S}CACHE which
is already done in mfi(4).
ok dlg
-rw-r--r-- | sys/dev/pci/mfii.c | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/sys/dev/pci/mfii.c b/sys/dev/pci/mfii.c index ff74525e75f..c880ed10a58 100644 --- a/sys/dev/pci/mfii.c +++ b/sys/dev/pci/mfii.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mfii.c,v 1.25 2015/03/14 03:38:48 jsg Exp $ */ +/* $OpenBSD: mfii.c,v 1.26 2016/10/24 03:11:58 yasuoka Exp $ */ /* * Copyright (c) 2012 David Gwynne <dlg@openbsd.org> @@ -22,6 +22,7 @@ #include <sys/systm.h> #include <sys/malloc.h> #include <sys/device.h> +#include <sys/dkio.h> #include <sys/types.h> #include <sys/pool.h> @@ -255,6 +256,7 @@ struct mfii_softc { int mfii_match(struct device *, void *, void *); void mfii_attach(struct device *, struct device *, void *); int mfii_detach(struct device *, int); +int mfii_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int); struct cfattach mfii_ca = { sizeof(struct mfii_softc), @@ -277,7 +279,7 @@ struct scsi_adapter mfii_switch = { scsi_minphys, NULL, /* probe */ NULL, /* unprobe */ - NULL /* ioctl */ + mfii_scsi_ioctl }; void mfii_pd_scsi_cmd(struct scsi_xfer *); @@ -334,6 +336,8 @@ int mfii_scsi_cmd_cdb(struct mfii_softc *, struct scsi_xfer *); int mfii_pd_scsi_cmd_cdb(struct mfii_softc *, struct scsi_xfer *); +int mfii_scsi_ioctl_cache(struct scsi_link *, u_int, + struct dk_cache *); #define mfii_fw_state(_sc) mfii_read((_sc), MFI_OSP) @@ -1796,3 +1800,87 @@ destroy: return (1); } +int +mfii_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag) +{ + switch (cmd) { + case DIOCGCACHE: + case DIOCSCACHE: + return mfii_scsi_ioctl_cache(link, cmd, + (struct dk_cache *)addr); + default: + break; + } + return (ENOTTY); +} + +int +mfii_scsi_ioctl_cache(struct scsi_link *link, u_int cmd, struct dk_cache *dc) +{ + struct mfii_softc *sc = (struct mfii_softc *)link->adapter_softc; + struct mfi_ld_prop ldp; + uint8_t mbox[MFI_MBOX_SIZE]; + struct mfii_ccb *ccb; + int rv, wrenable, rdenable; + + memset(mbox, 0, sizeof(mbox)); + *((uint16_t *)&mbox[0]) = htole16(link->target); + ccb = scsi_io_get(&sc->sc_iopool, 0); + rv = mfii_mgmt(sc, ccb, MR_DCMD_LD_GET_PROPERTIES, mbox, + &ldp, sizeof(ldp), SCSI_DATA_IN|SCSI_NOSLEEP); + scsi_io_put(&sc->sc_iopool, ccb); + if (rv != 0) + return (rv); + + if (letoh16(sc->sc_info.mci_memory_size) > 0) { + wrenable = ISSET(ldp.mlp_cur_cache_policy, + MR_LD_CACHE_ALLOW_WRITE_CACHE)? 1 : 0; + rdenable = ISSET(ldp.mlp_cur_cache_policy, + MR_LD_CACHE_ALLOW_READ_CACHE)? 1 : 0; + } else { + wrenable = ISSET(ldp.mlp_diskcache_policy, + MR_LD_DISK_CACHE_ENABLE)? 1 : 0; + rdenable = 0; + } + + if (cmd == DIOCGCACHE) { + dc->wrcache = wrenable; + dc->rdcache = rdenable; + return (0); + } + if (((dc->wrcache) ? 1 : 0) == wrenable && + ((dc->rdcache) ? 1 : 0) == rdenable) + return (0); + + mbox[0] = ldp.mlp_ld.mld_target; + mbox[1] = ldp.mlp_ld.mld_res; + *(uint16_t *)&mbox[2] = ldp.mlp_ld.mld_seq; + if (letoh16(sc->sc_info.mci_memory_size) > 0) { + if (dc->rdcache) + SET(ldp.mlp_cur_cache_policy, + MR_LD_CACHE_ALLOW_READ_CACHE); + else + CLR(ldp.mlp_cur_cache_policy, + MR_LD_CACHE_ALLOW_READ_CACHE); + if (dc->wrcache) + SET(ldp.mlp_cur_cache_policy, + MR_LD_CACHE_ALLOW_WRITE_CACHE); + else + CLR(ldp.mlp_cur_cache_policy, + MR_LD_CACHE_ALLOW_WRITE_CACHE); + } else { + if (dc->rdcache) + return (EOPNOTSUPP); + if (dc->wrcache) + ldp.mlp_diskcache_policy = MR_LD_DISK_CACHE_ENABLE; + else + ldp.mlp_diskcache_policy = MR_LD_DISK_CACHE_DISABLE; + } + + ccb = scsi_io_get(&sc->sc_iopool, 0); + rv = mfii_mgmt(sc, ccb, MR_DCMD_LD_SET_PROPERTIES, mbox, + &ldp, sizeof(ldp), SCSI_DATA_OUT|SCSI_NOSLEEP); + scsi_io_put(&sc->sc_iopool, ccb); + + return (rv); +} |