1d3c7b9a0SKenneth D. Merry /*- 2d3c7b9a0SKenneth D. Merry * Copyright (c) 2008 Yahoo!, Inc. 3d3c7b9a0SKenneth D. Merry * All rights reserved. 4d3c7b9a0SKenneth D. Merry * Written by: John Baldwin <jhb@FreeBSD.org> 5d3c7b9a0SKenneth D. Merry * 6d3c7b9a0SKenneth D. Merry * Redistribution and use in source and binary forms, with or without 7d3c7b9a0SKenneth D. Merry * modification, are permitted provided that the following conditions 8d3c7b9a0SKenneth D. Merry * are met: 9d3c7b9a0SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright 10d3c7b9a0SKenneth D. Merry * notice, this list of conditions and the following disclaimer. 11d3c7b9a0SKenneth D. Merry * 2. Redistributions in binary form must reproduce the above copyright 12d3c7b9a0SKenneth D. Merry * notice, this list of conditions and the following disclaimer in the 13d3c7b9a0SKenneth D. Merry * documentation and/or other materials provided with the distribution. 14d3c7b9a0SKenneth D. Merry * 3. Neither the name of the author nor the names of any co-contributors 15d3c7b9a0SKenneth D. Merry * may be used to endorse or promote products derived from this software 16d3c7b9a0SKenneth D. Merry * without specific prior written permission. 17d3c7b9a0SKenneth D. Merry * 18d3c7b9a0SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19d3c7b9a0SKenneth D. Merry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20d3c7b9a0SKenneth D. Merry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21d3c7b9a0SKenneth D. Merry * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22d3c7b9a0SKenneth D. Merry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23d3c7b9a0SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24d3c7b9a0SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25d3c7b9a0SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26d3c7b9a0SKenneth D. Merry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27d3c7b9a0SKenneth D. Merry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28d3c7b9a0SKenneth D. Merry * SUCH DAMAGE. 29d3c7b9a0SKenneth D. Merry * 30d3c7b9a0SKenneth D. Merry * LSI MPS-Fusion Host Adapter FreeBSD userland interface 31d3c7b9a0SKenneth D. Merry */ 32d3c7b9a0SKenneth D. Merry 33d3c7b9a0SKenneth D. Merry #include <sys/cdefs.h> 34d3c7b9a0SKenneth D. Merry __FBSDID("$FreeBSD$"); 35d3c7b9a0SKenneth D. Merry 365ef98042SMatthew D Fleming #include "opt_compat.h" 375ef98042SMatthew D Fleming 38d3c7b9a0SKenneth D. Merry #include <sys/types.h> 39d3c7b9a0SKenneth D. Merry #include <sys/param.h> 40d3c7b9a0SKenneth D. Merry #include <sys/systm.h> 41d3c7b9a0SKenneth D. Merry #include <sys/kernel.h> 42d3c7b9a0SKenneth D. Merry #include <sys/selinfo.h> 43d3c7b9a0SKenneth D. Merry #include <sys/module.h> 44d3c7b9a0SKenneth D. Merry #include <sys/bus.h> 45d3c7b9a0SKenneth D. Merry #include <sys/conf.h> 46d3c7b9a0SKenneth D. Merry #include <sys/bio.h> 47d3c7b9a0SKenneth D. Merry #include <sys/malloc.h> 48d3c7b9a0SKenneth D. Merry #include <sys/uio.h> 49d3c7b9a0SKenneth D. Merry #include <sys/sysctl.h> 50d3c7b9a0SKenneth D. Merry #include <sys/ioccom.h> 51d3c7b9a0SKenneth D. Merry #include <sys/endian.h> 525ef98042SMatthew D Fleming #include <sys/proc.h> 535ef98042SMatthew D Fleming #include <sys/sysent.h> 54d3c7b9a0SKenneth D. Merry 55d3c7b9a0SKenneth D. Merry #include <machine/bus.h> 56d3c7b9a0SKenneth D. Merry #include <machine/resource.h> 57d3c7b9a0SKenneth D. Merry #include <sys/rman.h> 58d3c7b9a0SKenneth D. Merry 59d3c7b9a0SKenneth D. Merry #include <cam/scsi/scsi_all.h> 60d3c7b9a0SKenneth D. Merry 61d3c7b9a0SKenneth D. Merry #include <dev/mps/mpi/mpi2_type.h> 62d3c7b9a0SKenneth D. Merry #include <dev/mps/mpi/mpi2.h> 63d3c7b9a0SKenneth D. Merry #include <dev/mps/mpi/mpi2_ioc.h> 64d3c7b9a0SKenneth D. Merry #include <dev/mps/mpi/mpi2_cnfg.h> 65d3c7b9a0SKenneth D. Merry #include <dev/mps/mpsvar.h> 66d3c7b9a0SKenneth D. Merry #include <dev/mps/mps_table.h> 67d3c7b9a0SKenneth D. Merry #include <dev/mps/mps_ioctl.h> 68d3c7b9a0SKenneth D. Merry 69d3c7b9a0SKenneth D. Merry static d_open_t mps_open; 70d3c7b9a0SKenneth D. Merry static d_close_t mps_close; 715ef98042SMatthew D Fleming static d_ioctl_t mps_ioctl_devsw; 72d3c7b9a0SKenneth D. Merry 73d3c7b9a0SKenneth D. Merry static struct cdevsw mps_cdevsw = { 74d3c7b9a0SKenneth D. Merry .d_version = D_VERSION, 75d3c7b9a0SKenneth D. Merry .d_flags = 0, 76d3c7b9a0SKenneth D. Merry .d_open = mps_open, 77d3c7b9a0SKenneth D. Merry .d_close = mps_close, 785ef98042SMatthew D Fleming .d_ioctl = mps_ioctl_devsw, 79d3c7b9a0SKenneth D. Merry .d_name = "mps", 80d3c7b9a0SKenneth D. Merry }; 81d3c7b9a0SKenneth D. Merry 82d3c7b9a0SKenneth D. Merry static MALLOC_DEFINE(M_MPSUSER, "mps_user", "Buffers for mps(4) ioctls"); 83d3c7b9a0SKenneth D. Merry 84d3c7b9a0SKenneth D. Merry int 85d3c7b9a0SKenneth D. Merry mps_attach_user(struct mps_softc *sc) 86d3c7b9a0SKenneth D. Merry { 87d3c7b9a0SKenneth D. Merry int unit; 88d3c7b9a0SKenneth D. Merry 89d3c7b9a0SKenneth D. Merry unit = device_get_unit(sc->mps_dev); 90d3c7b9a0SKenneth D. Merry sc->mps_cdev = make_dev(&mps_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640, 91d3c7b9a0SKenneth D. Merry "mps%d", unit); 92d3c7b9a0SKenneth D. Merry if (sc->mps_cdev == NULL) { 93d3c7b9a0SKenneth D. Merry return (ENOMEM); 94d3c7b9a0SKenneth D. Merry } 95d3c7b9a0SKenneth D. Merry sc->mps_cdev->si_drv1 = sc; 96d3c7b9a0SKenneth D. Merry return (0); 97d3c7b9a0SKenneth D. Merry } 98d3c7b9a0SKenneth D. Merry 99d3c7b9a0SKenneth D. Merry void 100d3c7b9a0SKenneth D. Merry mps_detach_user(struct mps_softc *sc) 101d3c7b9a0SKenneth D. Merry { 102d3c7b9a0SKenneth D. Merry 103d3c7b9a0SKenneth D. Merry /* XXX: do a purge of pending requests? */ 104d3c7b9a0SKenneth D. Merry destroy_dev(sc->mps_cdev); 105d3c7b9a0SKenneth D. Merry 106d3c7b9a0SKenneth D. Merry } 107d3c7b9a0SKenneth D. Merry 108d3c7b9a0SKenneth D. Merry static int 109d3c7b9a0SKenneth D. Merry mps_open(struct cdev *dev, int flags, int fmt, struct thread *td) 110d3c7b9a0SKenneth D. Merry { 111d3c7b9a0SKenneth D. Merry 112d3c7b9a0SKenneth D. Merry return (0); 113d3c7b9a0SKenneth D. Merry } 114d3c7b9a0SKenneth D. Merry 115d3c7b9a0SKenneth D. Merry static int 116d3c7b9a0SKenneth D. Merry mps_close(struct cdev *dev, int flags, int fmt, struct thread *td) 117d3c7b9a0SKenneth D. Merry { 118d3c7b9a0SKenneth D. Merry 119d3c7b9a0SKenneth D. Merry return (0); 120d3c7b9a0SKenneth D. Merry } 121d3c7b9a0SKenneth D. Merry 122d3c7b9a0SKenneth D. Merry static int 123d3c7b9a0SKenneth D. Merry mps_user_read_cfg_header(struct mps_softc *sc, 124d3c7b9a0SKenneth D. Merry struct mps_cfg_page_req *page_req) 125d3c7b9a0SKenneth D. Merry { 126d3c7b9a0SKenneth D. Merry MPI2_CONFIG_PAGE_HEADER *hdr; 127d3c7b9a0SKenneth D. Merry struct mps_config_params params; 128d3c7b9a0SKenneth D. Merry int error; 129d3c7b9a0SKenneth D. Merry 130d3c7b9a0SKenneth D. Merry hdr = ¶ms.hdr.Struct; 131d3c7b9a0SKenneth D. Merry params.action = MPI2_CONFIG_ACTION_PAGE_HEADER; 132d3c7b9a0SKenneth D. Merry params.page_address = le32toh(page_req->page_address); 133d3c7b9a0SKenneth D. Merry hdr->PageVersion = 0; 134d3c7b9a0SKenneth D. Merry hdr->PageLength = 0; 135d3c7b9a0SKenneth D. Merry hdr->PageNumber = page_req->header.PageNumber; 136d3c7b9a0SKenneth D. Merry hdr->PageType = page_req->header.PageType; 137d3c7b9a0SKenneth D. Merry params.buffer = NULL; 138d3c7b9a0SKenneth D. Merry params.length = 0; 139d3c7b9a0SKenneth D. Merry params.callback = NULL; 140d3c7b9a0SKenneth D. Merry 141d3c7b9a0SKenneth D. Merry if ((error = mps_read_config_page(sc, ¶ms)) != 0) { 142d3c7b9a0SKenneth D. Merry /* 143d3c7b9a0SKenneth D. Merry * Leave the request. Without resetting the chip, it's 144d3c7b9a0SKenneth D. Merry * still owned by it and we'll just get into trouble 145d3c7b9a0SKenneth D. Merry * freeing it now. Mark it as abandoned so that if it 146d3c7b9a0SKenneth D. Merry * shows up later it can be freed. 147d3c7b9a0SKenneth D. Merry */ 148d3c7b9a0SKenneth D. Merry mps_printf(sc, "read_cfg_header timed out\n"); 149d3c7b9a0SKenneth D. Merry return (ETIMEDOUT); 150d3c7b9a0SKenneth D. Merry } 151d3c7b9a0SKenneth D. Merry 152d3c7b9a0SKenneth D. Merry page_req->ioc_status = htole16(params.status); 153d3c7b9a0SKenneth D. Merry if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) == 154d3c7b9a0SKenneth D. Merry MPI2_IOCSTATUS_SUCCESS) { 155d3c7b9a0SKenneth D. Merry bcopy(hdr, &page_req->header, sizeof(page_req->header)); 156d3c7b9a0SKenneth D. Merry } 157d3c7b9a0SKenneth D. Merry 158d3c7b9a0SKenneth D. Merry return (0); 159d3c7b9a0SKenneth D. Merry } 160d3c7b9a0SKenneth D. Merry 161d3c7b9a0SKenneth D. Merry static int 162d3c7b9a0SKenneth D. Merry mps_user_read_cfg_page(struct mps_softc *sc, struct mps_cfg_page_req *page_req, 163d3c7b9a0SKenneth D. Merry void *buf) 164d3c7b9a0SKenneth D. Merry { 165d3c7b9a0SKenneth D. Merry MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; 166d3c7b9a0SKenneth D. Merry struct mps_config_params params; 167d3c7b9a0SKenneth D. Merry int error; 168d3c7b9a0SKenneth D. Merry 169d3c7b9a0SKenneth D. Merry reqhdr = buf; 170d3c7b9a0SKenneth D. Merry hdr = ¶ms.hdr.Struct; 171d3c7b9a0SKenneth D. Merry hdr->PageVersion = reqhdr->PageVersion; 172d3c7b9a0SKenneth D. Merry hdr->PageLength = reqhdr->PageLength; 173d3c7b9a0SKenneth D. Merry hdr->PageNumber = reqhdr->PageNumber; 174d3c7b9a0SKenneth D. Merry hdr->PageType = reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK; 175d3c7b9a0SKenneth D. Merry params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 176d3c7b9a0SKenneth D. Merry params.page_address = le32toh(page_req->page_address); 177d3c7b9a0SKenneth D. Merry params.buffer = buf; 178d3c7b9a0SKenneth D. Merry params.length = le32toh(page_req->len); 179d3c7b9a0SKenneth D. Merry params.callback = NULL; 180d3c7b9a0SKenneth D. Merry 181d3c7b9a0SKenneth D. Merry if ((error = mps_read_config_page(sc, ¶ms)) != 0) { 182d3c7b9a0SKenneth D. Merry mps_printf(sc, "mps_user_read_cfg_page timed out\n"); 183d3c7b9a0SKenneth D. Merry return (ETIMEDOUT); 184d3c7b9a0SKenneth D. Merry } 185d3c7b9a0SKenneth D. Merry 186d3c7b9a0SKenneth D. Merry page_req->ioc_status = htole16(params.status); 187d3c7b9a0SKenneth D. Merry return (0); 188d3c7b9a0SKenneth D. Merry } 189d3c7b9a0SKenneth D. Merry 190d3c7b9a0SKenneth D. Merry static int 191d3c7b9a0SKenneth D. Merry mps_user_read_extcfg_header(struct mps_softc *sc, 192d3c7b9a0SKenneth D. Merry struct mps_ext_cfg_page_req *ext_page_req) 193d3c7b9a0SKenneth D. Merry { 194d3c7b9a0SKenneth D. Merry MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr; 195d3c7b9a0SKenneth D. Merry struct mps_config_params params; 196d3c7b9a0SKenneth D. Merry int error; 197d3c7b9a0SKenneth D. Merry 198d3c7b9a0SKenneth D. Merry hdr = ¶ms.hdr.Ext; 199d3c7b9a0SKenneth D. Merry params.action = MPI2_CONFIG_ACTION_PAGE_HEADER; 200d3c7b9a0SKenneth D. Merry hdr->PageVersion = ext_page_req->header.PageVersion; 201d3c7b9a0SKenneth D. Merry hdr->ExtPageLength = 0; 202d3c7b9a0SKenneth D. Merry hdr->PageNumber = ext_page_req->header.PageNumber; 203d3c7b9a0SKenneth D. Merry hdr->ExtPageType = ext_page_req->header.ExtPageType; 204d3c7b9a0SKenneth D. Merry params.page_address = le32toh(ext_page_req->page_address); 205d3c7b9a0SKenneth D. Merry if ((error = mps_read_config_page(sc, ¶ms)) != 0) { 206d3c7b9a0SKenneth D. Merry /* 207d3c7b9a0SKenneth D. Merry * Leave the request. Without resetting the chip, it's 208d3c7b9a0SKenneth D. Merry * still owned by it and we'll just get into trouble 209d3c7b9a0SKenneth D. Merry * freeing it now. Mark it as abandoned so that if it 210d3c7b9a0SKenneth D. Merry * shows up later it can be freed. 211d3c7b9a0SKenneth D. Merry */ 212d3c7b9a0SKenneth D. Merry mps_printf(sc, "mps_user_read_extcfg_header timed out\n"); 213d3c7b9a0SKenneth D. Merry return (ETIMEDOUT); 214d3c7b9a0SKenneth D. Merry } 215d3c7b9a0SKenneth D. Merry 216d3c7b9a0SKenneth D. Merry ext_page_req->ioc_status = htole16(params.status); 217d3c7b9a0SKenneth D. Merry if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) == 218d3c7b9a0SKenneth D. Merry MPI2_IOCSTATUS_SUCCESS) { 219d3c7b9a0SKenneth D. Merry ext_page_req->header.PageVersion = hdr->PageVersion; 220d3c7b9a0SKenneth D. Merry ext_page_req->header.PageNumber = hdr->PageNumber; 221d3c7b9a0SKenneth D. Merry ext_page_req->header.PageType = hdr->PageType; 222d3c7b9a0SKenneth D. Merry ext_page_req->header.ExtPageLength = hdr->ExtPageLength; 223d3c7b9a0SKenneth D. Merry ext_page_req->header.ExtPageType = hdr->ExtPageType; 224d3c7b9a0SKenneth D. Merry } 225d3c7b9a0SKenneth D. Merry 226d3c7b9a0SKenneth D. Merry return (0); 227d3c7b9a0SKenneth D. Merry } 228d3c7b9a0SKenneth D. Merry 229d3c7b9a0SKenneth D. Merry static int 230d3c7b9a0SKenneth D. Merry mps_user_read_extcfg_page(struct mps_softc *sc, 231d3c7b9a0SKenneth D. Merry struct mps_ext_cfg_page_req *ext_page_req, void *buf) 232d3c7b9a0SKenneth D. Merry { 233d3c7b9a0SKenneth D. Merry MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr; 234d3c7b9a0SKenneth D. Merry struct mps_config_params params; 235d3c7b9a0SKenneth D. Merry int error; 236d3c7b9a0SKenneth D. Merry 237d3c7b9a0SKenneth D. Merry reqhdr = buf; 238d3c7b9a0SKenneth D. Merry hdr = ¶ms.hdr.Ext; 239d3c7b9a0SKenneth D. Merry params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 240d3c7b9a0SKenneth D. Merry params.page_address = le32toh(ext_page_req->page_address); 241d3c7b9a0SKenneth D. Merry hdr->PageVersion = reqhdr->PageVersion; 242d3c7b9a0SKenneth D. Merry hdr->PageNumber = reqhdr->PageNumber; 243d3c7b9a0SKenneth D. Merry hdr->ExtPageType = reqhdr->ExtPageType; 244d3c7b9a0SKenneth D. Merry hdr->ExtPageLength = reqhdr->ExtPageLength; 245d3c7b9a0SKenneth D. Merry params.buffer = buf; 246d3c7b9a0SKenneth D. Merry params.length = le32toh(ext_page_req->len); 247d3c7b9a0SKenneth D. Merry params.callback = NULL; 248d3c7b9a0SKenneth D. Merry 249d3c7b9a0SKenneth D. Merry if ((error = mps_read_config_page(sc, ¶ms)) != 0) { 250d3c7b9a0SKenneth D. Merry mps_printf(sc, "mps_user_read_extcfg_page timed out\n"); 251d3c7b9a0SKenneth D. Merry return (ETIMEDOUT); 252d3c7b9a0SKenneth D. Merry } 253d3c7b9a0SKenneth D. Merry 254d3c7b9a0SKenneth D. Merry ext_page_req->ioc_status = htole16(params.status); 255d3c7b9a0SKenneth D. Merry return (0); 256d3c7b9a0SKenneth D. Merry } 257d3c7b9a0SKenneth D. Merry 258d3c7b9a0SKenneth D. Merry static int 259d3c7b9a0SKenneth D. Merry mps_user_write_cfg_page(struct mps_softc *sc, 260d3c7b9a0SKenneth D. Merry struct mps_cfg_page_req *page_req, void *buf) 261d3c7b9a0SKenneth D. Merry { 262d3c7b9a0SKenneth D. Merry MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; 263d3c7b9a0SKenneth D. Merry struct mps_config_params params; 264d3c7b9a0SKenneth D. Merry u_int hdr_attr; 265d3c7b9a0SKenneth D. Merry int error; 266d3c7b9a0SKenneth D. Merry 267d3c7b9a0SKenneth D. Merry reqhdr = buf; 268d3c7b9a0SKenneth D. Merry hdr = ¶ms.hdr.Struct; 269d3c7b9a0SKenneth D. Merry hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK; 270d3c7b9a0SKenneth D. Merry if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE && 271d3c7b9a0SKenneth D. Merry hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) { 272d3c7b9a0SKenneth D. Merry mps_printf(sc, "page type 0x%x not changeable\n", 273d3c7b9a0SKenneth D. Merry reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK); 274d3c7b9a0SKenneth D. Merry return (EINVAL); 275d3c7b9a0SKenneth D. Merry } 276d3c7b9a0SKenneth D. Merry 277d3c7b9a0SKenneth D. Merry /* 278d3c7b9a0SKenneth D. Merry * There isn't any point in restoring stripped out attributes 279d3c7b9a0SKenneth D. Merry * if you then mask them going down to issue the request. 280d3c7b9a0SKenneth D. Merry */ 281d3c7b9a0SKenneth D. Merry 282d3c7b9a0SKenneth D. Merry hdr->PageVersion = reqhdr->PageVersion; 283d3c7b9a0SKenneth D. Merry hdr->PageLength = reqhdr->PageLength; 284d3c7b9a0SKenneth D. Merry hdr->PageNumber = reqhdr->PageNumber; 285d3c7b9a0SKenneth D. Merry hdr->PageType = reqhdr->PageType; 286d3c7b9a0SKenneth D. Merry params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 287d3c7b9a0SKenneth D. Merry params.page_address = le32toh(page_req->page_address); 288d3c7b9a0SKenneth D. Merry params.buffer = buf; 289d3c7b9a0SKenneth D. Merry params.length = le32toh(page_req->len); 290d3c7b9a0SKenneth D. Merry params.callback = NULL; 291d3c7b9a0SKenneth D. Merry 292d3c7b9a0SKenneth D. Merry if ((error = mps_write_config_page(sc, ¶ms)) != 0) { 293d3c7b9a0SKenneth D. Merry mps_printf(sc, "mps_write_cfg_page timed out\n"); 294d3c7b9a0SKenneth D. Merry return (ETIMEDOUT); 295d3c7b9a0SKenneth D. Merry } 296d3c7b9a0SKenneth D. Merry 297d3c7b9a0SKenneth D. Merry page_req->ioc_status = htole16(params.status); 298d3c7b9a0SKenneth D. Merry return (0); 299d3c7b9a0SKenneth D. Merry } 300d3c7b9a0SKenneth D. Merry 301d3c7b9a0SKenneth D. Merry struct mps_user_func { 302d3c7b9a0SKenneth D. Merry U8 Func; 303d3c7b9a0SKenneth D. Merry U8 SgOff; 304d3c7b9a0SKenneth D. Merry } mps_user_func_list[] = { 305d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_IOC_FACTS, 0 }, 306d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_PORT_FACTS, 0 }, 307d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_FW_DOWNLOAD, offsetof(Mpi2FWDownloadRequest,SGL)}, 308d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_FW_UPLOAD, offsetof(Mpi2FWUploadRequest_t,SGL)}, 309d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_SATA_PASSTHROUGH,offsetof(Mpi2SataPassthroughRequest_t,SGL)}, 310d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_SMP_PASSTHROUGH, offsetof(Mpi2SmpPassthroughRequest_t,SGL)}, 311d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_CONFIG, offsetof(Mpi2ConfigRequest_t,PageBufferSGE)}, 312d3c7b9a0SKenneth D. Merry { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL, 0 }, 313d3c7b9a0SKenneth D. Merry }; 314d3c7b9a0SKenneth D. Merry 315d3c7b9a0SKenneth D. Merry static int 316d3c7b9a0SKenneth D. Merry mps_user_verify_request(MPI2_REQUEST_HEADER *hdr, MPI2_SGE_IO_UNION **psgl) 317d3c7b9a0SKenneth D. Merry { 318d3c7b9a0SKenneth D. Merry int i, err = EINVAL; 319d3c7b9a0SKenneth D. Merry 320d3c7b9a0SKenneth D. Merry for (i = 0; i < sizeof(mps_user_func_list) / 321d3c7b9a0SKenneth D. Merry sizeof(mps_user_func_list[0]); i++ ) { 322d3c7b9a0SKenneth D. Merry struct mps_user_func *func = &mps_user_func_list[i]; 323d3c7b9a0SKenneth D. Merry 324d3c7b9a0SKenneth D. Merry if (hdr->Function == func->Func) { 325d3c7b9a0SKenneth D. Merry if (psgl != NULL) { 326d3c7b9a0SKenneth D. Merry if (func->SgOff != 0) 327d3c7b9a0SKenneth D. Merry *psgl = (PTR_MPI2_SGE_IO_UNION) 328d3c7b9a0SKenneth D. Merry ((char*)hdr + func->SgOff); 329d3c7b9a0SKenneth D. Merry else 330d3c7b9a0SKenneth D. Merry *psgl = NULL; 331d3c7b9a0SKenneth D. Merry err = 0; 332d3c7b9a0SKenneth D. Merry break; 333d3c7b9a0SKenneth D. Merry } 334d3c7b9a0SKenneth D. Merry } 335d3c7b9a0SKenneth D. Merry } 336d3c7b9a0SKenneth D. Merry 337d3c7b9a0SKenneth D. Merry return err; 338d3c7b9a0SKenneth D. Merry } 339d3c7b9a0SKenneth D. Merry 340d3c7b9a0SKenneth D. Merry static int 341d3c7b9a0SKenneth D. Merry mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd) 342d3c7b9a0SKenneth D. Merry { 343d3c7b9a0SKenneth D. Merry MPI2_REQUEST_HEADER *hdr; 344d3c7b9a0SKenneth D. Merry MPI2_DEFAULT_REPLY *rpl; 345d3c7b9a0SKenneth D. Merry MPI2_SGE_IO_UNION *sgl; 346*01095e3bSMatthew D Fleming void *buf = NULL; 347d3c7b9a0SKenneth D. Merry struct mps_command *cm; 348d3c7b9a0SKenneth D. Merry int err = 0; 349d3c7b9a0SKenneth D. Merry int sz; 350d3c7b9a0SKenneth D. Merry 351d3c7b9a0SKenneth D. Merry mps_lock(sc); 352d3c7b9a0SKenneth D. Merry cm = mps_alloc_command(sc); 353d3c7b9a0SKenneth D. Merry 354d3c7b9a0SKenneth D. Merry if (cm == NULL) { 355d3c7b9a0SKenneth D. Merry mps_printf(sc, "mps_user_command: no mps requests\n"); 356d3c7b9a0SKenneth D. Merry err = ENOMEM; 357d3c7b9a0SKenneth D. Merry goto Ret; 358d3c7b9a0SKenneth D. Merry } 359d3c7b9a0SKenneth D. Merry mps_unlock(sc); 360d3c7b9a0SKenneth D. Merry 361d3c7b9a0SKenneth D. Merry hdr = (MPI2_REQUEST_HEADER *)cm->cm_req; 362d3c7b9a0SKenneth D. Merry 363d3c7b9a0SKenneth D. Merry mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d rpl %p %d\n", 364d3c7b9a0SKenneth D. Merry cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len ); 365d3c7b9a0SKenneth D. Merry 366*01095e3bSMatthew D Fleming if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) { 367*01095e3bSMatthew D Fleming err = EINVAL; 368*01095e3bSMatthew D Fleming goto RetFreeUnlocked; 369*01095e3bSMatthew D Fleming } 370*01095e3bSMatthew D Fleming err = copyin(cmd->req, hdr, cmd->req_len); 371*01095e3bSMatthew D Fleming if (err != 0) 372*01095e3bSMatthew D Fleming goto RetFreeUnlocked; 373d3c7b9a0SKenneth D. Merry 374d3c7b9a0SKenneth D. Merry mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X " 375d3c7b9a0SKenneth D. Merry "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags ); 376d3c7b9a0SKenneth D. Merry 377d3c7b9a0SKenneth D. Merry err = mps_user_verify_request(hdr, &sgl); 378d3c7b9a0SKenneth D. Merry if (err != 0) { 379d3c7b9a0SKenneth D. Merry mps_printf(sc, "mps_user_command: unsupported function 0x%X\n", 380d3c7b9a0SKenneth D. Merry hdr->Function ); 381*01095e3bSMatthew D Fleming goto RetFreeUnlocked; 382d3c7b9a0SKenneth D. Merry } 383d3c7b9a0SKenneth D. Merry 384d3c7b9a0SKenneth D. Merry if (cmd->len > 0) { 385d3c7b9a0SKenneth D. Merry buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO); 386d3c7b9a0SKenneth D. Merry cm->cm_data = buf; 387d3c7b9a0SKenneth D. Merry cm->cm_length = cmd->len; 388d3c7b9a0SKenneth D. Merry } else { 389d3c7b9a0SKenneth D. Merry cm->cm_data = NULL; 390d3c7b9a0SKenneth D. Merry cm->cm_length = 0; 391d3c7b9a0SKenneth D. Merry } 392d3c7b9a0SKenneth D. Merry 393d3c7b9a0SKenneth D. Merry cm->cm_sge = sgl; 394d3c7b9a0SKenneth D. Merry cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 395d3c7b9a0SKenneth D. Merry cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_WAKEUP; 396d3c7b9a0SKenneth D. Merry cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 397d3c7b9a0SKenneth D. Merry 398d3c7b9a0SKenneth D. Merry mps_lock(sc); 399d3c7b9a0SKenneth D. Merry err = mps_map_command(sc, cm); 400d3c7b9a0SKenneth D. Merry 401d3c7b9a0SKenneth D. Merry if (err != 0) { 402d3c7b9a0SKenneth D. Merry mps_printf(sc, "mps_user_command: request timed out\n"); 403d3c7b9a0SKenneth D. Merry goto Ret; 404d3c7b9a0SKenneth D. Merry } 405d3c7b9a0SKenneth D. Merry msleep(cm, &sc->mps_mtx, 0, "mpsuser", 0); /* 30 seconds */ 406d3c7b9a0SKenneth D. Merry 407d3c7b9a0SKenneth D. Merry rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; 408d3c7b9a0SKenneth D. Merry sz = rpl->MsgLength * 4; 409d3c7b9a0SKenneth D. Merry 410d3c7b9a0SKenneth D. Merry if (sz > cmd->rpl_len) { 411d3c7b9a0SKenneth D. Merry mps_printf(sc, 412d3c7b9a0SKenneth D. Merry "mps_user_command: reply buffer too small %d required %d\n", 413d3c7b9a0SKenneth D. Merry cmd->rpl_len, sz ); 414d3c7b9a0SKenneth D. Merry err = EINVAL; 415d3c7b9a0SKenneth D. Merry sz = cmd->rpl_len; 416d3c7b9a0SKenneth D. Merry } 417d3c7b9a0SKenneth D. Merry 418d3c7b9a0SKenneth D. Merry mps_unlock(sc); 419d3c7b9a0SKenneth D. Merry copyout(rpl, cmd->rpl, sz); 420*01095e3bSMatthew D Fleming if (buf != NULL) 421d3c7b9a0SKenneth D. Merry copyout(buf, cmd->buf, cmd->len); 422d3c7b9a0SKenneth D. Merry mps_lock(sc); 423d3c7b9a0SKenneth D. Merry 424d3c7b9a0SKenneth D. Merry mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz ); 425d3c7b9a0SKenneth D. Merry 426d3c7b9a0SKenneth D. Merry mps_free_command(sc, cm); 427d3c7b9a0SKenneth D. Merry Ret: 428d3c7b9a0SKenneth D. Merry mps_unlock(sc); 429*01095e3bSMatthew D Fleming if (buf != NULL) 430*01095e3bSMatthew D Fleming free(buf, M_MPSUSER); 431*01095e3bSMatthew D Fleming return (err); 432*01095e3bSMatthew D Fleming 433*01095e3bSMatthew D Fleming RetFreeUnlocked: 434*01095e3bSMatthew D Fleming mps_lock(sc); 435*01095e3bSMatthew D Fleming mps_free_command(sc, cm); 436*01095e3bSMatthew D Fleming mps_unlock(sc); 437*01095e3bSMatthew D Fleming 438*01095e3bSMatthew D Fleming if (buf != NULL) 439*01095e3bSMatthew D Fleming free(buf, M_MPSUSER); 440*01095e3bSMatthew D Fleming return (err); 441d3c7b9a0SKenneth D. Merry } 442d3c7b9a0SKenneth D. Merry 443d3c7b9a0SKenneth D. Merry static int 4445ef98042SMatthew D Fleming mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag, 445d3c7b9a0SKenneth D. Merry struct thread *td) 446d3c7b9a0SKenneth D. Merry { 447d3c7b9a0SKenneth D. Merry struct mps_softc *sc; 448d3c7b9a0SKenneth D. Merry struct mps_cfg_page_req *page_req; 449d3c7b9a0SKenneth D. Merry struct mps_ext_cfg_page_req *ext_page_req; 450d3c7b9a0SKenneth D. Merry void *mps_page; 451d3c7b9a0SKenneth D. Merry int error; 452d3c7b9a0SKenneth D. Merry 453d3c7b9a0SKenneth D. Merry mps_page = NULL; 454d3c7b9a0SKenneth D. Merry sc = dev->si_drv1; 455d3c7b9a0SKenneth D. Merry page_req = (void *)arg; 456d3c7b9a0SKenneth D. Merry ext_page_req = (void *)arg; 457d3c7b9a0SKenneth D. Merry 458d3c7b9a0SKenneth D. Merry switch (cmd) { 459d3c7b9a0SKenneth D. Merry case MPSIO_READ_CFG_HEADER: 460d3c7b9a0SKenneth D. Merry mps_lock(sc); 461d3c7b9a0SKenneth D. Merry error = mps_user_read_cfg_header(sc, page_req); 462d3c7b9a0SKenneth D. Merry mps_unlock(sc); 463d3c7b9a0SKenneth D. Merry break; 464d3c7b9a0SKenneth D. Merry case MPSIO_READ_CFG_PAGE: 465d3c7b9a0SKenneth D. Merry mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK | M_ZERO); 466d3c7b9a0SKenneth D. Merry error = copyin(page_req->buf, mps_page, 467d3c7b9a0SKenneth D. Merry sizeof(MPI2_CONFIG_PAGE_HEADER)); 468d3c7b9a0SKenneth D. Merry if (error) 469d3c7b9a0SKenneth D. Merry break; 470d3c7b9a0SKenneth D. Merry mps_lock(sc); 471d3c7b9a0SKenneth D. Merry error = mps_user_read_cfg_page(sc, page_req, mps_page); 472d3c7b9a0SKenneth D. Merry mps_unlock(sc); 473d3c7b9a0SKenneth D. Merry if (error) 474d3c7b9a0SKenneth D. Merry break; 475d3c7b9a0SKenneth D. Merry error = copyout(mps_page, page_req->buf, page_req->len); 476d3c7b9a0SKenneth D. Merry break; 477d3c7b9a0SKenneth D. Merry case MPSIO_READ_EXT_CFG_HEADER: 478d3c7b9a0SKenneth D. Merry mps_lock(sc); 479d3c7b9a0SKenneth D. Merry error = mps_user_read_extcfg_header(sc, ext_page_req); 480d3c7b9a0SKenneth D. Merry mps_unlock(sc); 481d3c7b9a0SKenneth D. Merry break; 482d3c7b9a0SKenneth D. Merry case MPSIO_READ_EXT_CFG_PAGE: 483d3c7b9a0SKenneth D. Merry mps_page = malloc(ext_page_req->len, M_MPSUSER, M_WAITOK|M_ZERO); 484d3c7b9a0SKenneth D. Merry error = copyin(ext_page_req->buf, mps_page, 485d3c7b9a0SKenneth D. Merry sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 486d3c7b9a0SKenneth D. Merry if (error) 487d3c7b9a0SKenneth D. Merry break; 488d3c7b9a0SKenneth D. Merry mps_lock(sc); 489d3c7b9a0SKenneth D. Merry error = mps_user_read_extcfg_page(sc, ext_page_req, mps_page); 490d3c7b9a0SKenneth D. Merry mps_unlock(sc); 491d3c7b9a0SKenneth D. Merry if (error) 492d3c7b9a0SKenneth D. Merry break; 493d3c7b9a0SKenneth D. Merry error = copyout(mps_page, ext_page_req->buf, ext_page_req->len); 494d3c7b9a0SKenneth D. Merry break; 495d3c7b9a0SKenneth D. Merry case MPSIO_WRITE_CFG_PAGE: 496d3c7b9a0SKenneth D. Merry mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK|M_ZERO); 497d3c7b9a0SKenneth D. Merry error = copyin(page_req->buf, mps_page, page_req->len); 498d3c7b9a0SKenneth D. Merry if (error) 499d3c7b9a0SKenneth D. Merry break; 500d3c7b9a0SKenneth D. Merry mps_lock(sc); 501d3c7b9a0SKenneth D. Merry error = mps_user_write_cfg_page(sc, page_req, mps_page); 502d3c7b9a0SKenneth D. Merry mps_unlock(sc); 503d3c7b9a0SKenneth D. Merry break; 504d3c7b9a0SKenneth D. Merry case MPSIO_MPS_COMMAND: 505d3c7b9a0SKenneth D. Merry error = mps_user_command(sc, (struct mps_usr_command *)arg); 506d3c7b9a0SKenneth D. Merry break; 507d3c7b9a0SKenneth D. Merry default: 508d3c7b9a0SKenneth D. Merry error = ENOIOCTL; 509d3c7b9a0SKenneth D. Merry break; 510d3c7b9a0SKenneth D. Merry } 511d3c7b9a0SKenneth D. Merry 512d3c7b9a0SKenneth D. Merry if (mps_page != NULL) 513d3c7b9a0SKenneth D. Merry free(mps_page, M_MPSUSER); 514d3c7b9a0SKenneth D. Merry 515d3c7b9a0SKenneth D. Merry return (error); 5165ef98042SMatthew D Fleming } 517d3c7b9a0SKenneth D. Merry 5185ef98042SMatthew D Fleming #ifdef COMPAT_FREEBSD32 5195ef98042SMatthew D Fleming 5205ef98042SMatthew D Fleming /* Macros from compat/freebsd32/freebsd32.h */ 5215ef98042SMatthew D Fleming #define PTRIN(v) (void *)(uintptr_t)(v) 5225ef98042SMatthew D Fleming #define PTROUT(v) (uint32_t)(uintptr_t)(v) 5235ef98042SMatthew D Fleming 5245ef98042SMatthew D Fleming #define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) 5255ef98042SMatthew D Fleming #define PTRIN_CP(src,dst,fld) \ 5265ef98042SMatthew D Fleming do { (dst).fld = PTRIN((src).fld); } while (0) 5275ef98042SMatthew D Fleming #define PTROUT_CP(src,dst,fld) \ 5285ef98042SMatthew D Fleming do { (dst).fld = PTROUT((src).fld); } while (0) 5295ef98042SMatthew D Fleming 5305ef98042SMatthew D Fleming struct mps_cfg_page_req32 { 5315ef98042SMatthew D Fleming MPI2_CONFIG_PAGE_HEADER header; 5325ef98042SMatthew D Fleming uint32_t page_address; 5335ef98042SMatthew D Fleming uint32_t buf; 5345ef98042SMatthew D Fleming int len; 5355ef98042SMatthew D Fleming uint16_t ioc_status; 5365ef98042SMatthew D Fleming }; 5375ef98042SMatthew D Fleming 5385ef98042SMatthew D Fleming struct mps_ext_cfg_page_req32 { 5395ef98042SMatthew D Fleming MPI2_CONFIG_EXTENDED_PAGE_HEADER header; 5405ef98042SMatthew D Fleming uint32_t page_address; 5415ef98042SMatthew D Fleming uint32_t buf; 5425ef98042SMatthew D Fleming int len; 5435ef98042SMatthew D Fleming uint16_t ioc_status; 5445ef98042SMatthew D Fleming }; 5455ef98042SMatthew D Fleming 5465ef98042SMatthew D Fleming struct mps_raid_action32 { 5475ef98042SMatthew D Fleming uint8_t action; 5485ef98042SMatthew D Fleming uint8_t volume_bus; 5495ef98042SMatthew D Fleming uint8_t volume_id; 5505ef98042SMatthew D Fleming uint8_t phys_disk_num; 5515ef98042SMatthew D Fleming uint32_t action_data_word; 5525ef98042SMatthew D Fleming uint32_t buf; 5535ef98042SMatthew D Fleming int len; 5545ef98042SMatthew D Fleming uint32_t volume_status; 5555ef98042SMatthew D Fleming uint32_t action_data[4]; 5565ef98042SMatthew D Fleming uint16_t action_status; 5575ef98042SMatthew D Fleming uint16_t ioc_status; 5585ef98042SMatthew D Fleming uint8_t write; 5595ef98042SMatthew D Fleming }; 5605ef98042SMatthew D Fleming 5615ef98042SMatthew D Fleming struct mps_usr_command32 { 5625ef98042SMatthew D Fleming uint32_t req; 5635ef98042SMatthew D Fleming uint32_t req_len; 5645ef98042SMatthew D Fleming uint32_t rpl; 5655ef98042SMatthew D Fleming uint32_t rpl_len; 5665ef98042SMatthew D Fleming uint32_t buf; 5675ef98042SMatthew D Fleming int len; 5685ef98042SMatthew D Fleming uint32_t flags; 5695ef98042SMatthew D Fleming }; 5705ef98042SMatthew D Fleming 5715ef98042SMatthew D Fleming #define MPSIO_READ_CFG_HEADER32 _IOWR('M', 200, struct mps_cfg_page_req32) 5725ef98042SMatthew D Fleming #define MPSIO_READ_CFG_PAGE32 _IOWR('M', 201, struct mps_cfg_page_req32) 5735ef98042SMatthew D Fleming #define MPSIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mps_ext_cfg_page_req32) 5745ef98042SMatthew D Fleming #define MPSIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mps_ext_cfg_page_req32) 5755ef98042SMatthew D Fleming #define MPSIO_WRITE_CFG_PAGE32 _IOWR('M', 204, struct mps_cfg_page_req32) 5765ef98042SMatthew D Fleming #define MPSIO_RAID_ACTION32 _IOWR('M', 205, struct mps_raid_action32) 5775ef98042SMatthew D Fleming #define MPSIO_MPS_COMMAND32 _IOWR('M', 210, struct mps_usr_command32) 5785ef98042SMatthew D Fleming 5795ef98042SMatthew D Fleming static int 5805ef98042SMatthew D Fleming mps_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag, 5815ef98042SMatthew D Fleming struct thread *td) 5825ef98042SMatthew D Fleming { 5835ef98042SMatthew D Fleming struct mps_cfg_page_req32 *page32 = _arg; 5845ef98042SMatthew D Fleming struct mps_ext_cfg_page_req32 *ext32 = _arg; 5855ef98042SMatthew D Fleming struct mps_raid_action32 *raid32 = _arg; 5865ef98042SMatthew D Fleming struct mps_usr_command32 *user32 = _arg; 5875ef98042SMatthew D Fleming union { 5885ef98042SMatthew D Fleming struct mps_cfg_page_req page; 5895ef98042SMatthew D Fleming struct mps_ext_cfg_page_req ext; 5905ef98042SMatthew D Fleming struct mps_raid_action raid; 5915ef98042SMatthew D Fleming struct mps_usr_command user; 5925ef98042SMatthew D Fleming } arg; 5935ef98042SMatthew D Fleming u_long cmd; 5945ef98042SMatthew D Fleming int error; 5955ef98042SMatthew D Fleming 5965ef98042SMatthew D Fleming switch (cmd32) { 597d3c7b9a0SKenneth D. Merry case MPSIO_READ_CFG_HEADER32: 598d3c7b9a0SKenneth D. Merry case MPSIO_READ_CFG_PAGE32: 599d3c7b9a0SKenneth D. Merry case MPSIO_WRITE_CFG_PAGE32: 6005ef98042SMatthew D Fleming if (cmd32 == MPSIO_READ_CFG_HEADER32) 6015ef98042SMatthew D Fleming cmd = MPSIO_READ_CFG_HEADER; 6025ef98042SMatthew D Fleming else if (cmd32 == MPSIO_READ_CFG_PAGE32) 6035ef98042SMatthew D Fleming cmd = MPSIO_READ_CFG_PAGE; 6045ef98042SMatthew D Fleming else 6055ef98042SMatthew D Fleming cmd = MPSIO_WRITE_CFG_PAGE; 6065ef98042SMatthew D Fleming CP(*page32, arg.page, header); 6075ef98042SMatthew D Fleming CP(*page32, arg.page, page_address); 6085ef98042SMatthew D Fleming PTRIN_CP(*page32, arg.page, buf); 6095ef98042SMatthew D Fleming CP(*page32, arg.page, len); 6105ef98042SMatthew D Fleming CP(*page32, arg.page, ioc_status); 611d3c7b9a0SKenneth D. Merry break; 6125ef98042SMatthew D Fleming 613d3c7b9a0SKenneth D. Merry case MPSIO_READ_EXT_CFG_HEADER32: 614d3c7b9a0SKenneth D. Merry case MPSIO_READ_EXT_CFG_PAGE32: 6155ef98042SMatthew D Fleming if (cmd32 == MPSIO_READ_EXT_CFG_HEADER32) 6165ef98042SMatthew D Fleming cmd = MPSIO_READ_EXT_CFG_HEADER; 6175ef98042SMatthew D Fleming else 6185ef98042SMatthew D Fleming cmd = MPSIO_READ_EXT_CFG_PAGE; 6195ef98042SMatthew D Fleming CP(*ext32, arg.ext, header); 6205ef98042SMatthew D Fleming CP(*ext32, arg.ext, page_address); 6215ef98042SMatthew D Fleming PTRIN_CP(*ext32, arg.ext, buf); 6225ef98042SMatthew D Fleming CP(*ext32, arg.ext, len); 6235ef98042SMatthew D Fleming CP(*ext32, arg.ext, ioc_status); 6245ef98042SMatthew D Fleming break; 6255ef98042SMatthew D Fleming 6265ef98042SMatthew D Fleming case MPSIO_RAID_ACTION32: 6275ef98042SMatthew D Fleming cmd = MPSIO_RAID_ACTION; 6285ef98042SMatthew D Fleming CP(*raid32, arg.raid, action); 6295ef98042SMatthew D Fleming CP(*raid32, arg.raid, volume_bus); 6305ef98042SMatthew D Fleming CP(*raid32, arg.raid, volume_id); 6315ef98042SMatthew D Fleming CP(*raid32, arg.raid, phys_disk_num); 6325ef98042SMatthew D Fleming CP(*raid32, arg.raid, action_data_word); 6335ef98042SMatthew D Fleming PTRIN_CP(*raid32, arg.raid, buf); 6345ef98042SMatthew D Fleming CP(*raid32, arg.raid, len); 6355ef98042SMatthew D Fleming CP(*raid32, arg.raid, volume_status); 6365ef98042SMatthew D Fleming bcopy(raid32->action_data, arg.raid.action_data, 6375ef98042SMatthew D Fleming sizeof arg.raid.action_data); 6385ef98042SMatthew D Fleming CP(*raid32, arg.raid, ioc_status); 6395ef98042SMatthew D Fleming CP(*raid32, arg.raid, write); 6405ef98042SMatthew D Fleming break; 6415ef98042SMatthew D Fleming 6425ef98042SMatthew D Fleming case MPSIO_MPS_COMMAND32: 6435ef98042SMatthew D Fleming cmd = MPSIO_MPS_COMMAND; 6445ef98042SMatthew D Fleming PTRIN_CP(*user32, arg.user, req); 6455ef98042SMatthew D Fleming CP(*user32, arg.user, req_len); 6465ef98042SMatthew D Fleming PTRIN_CP(*user32, arg.user, rpl); 6475ef98042SMatthew D Fleming CP(*user32, arg.user, rpl_len); 6485ef98042SMatthew D Fleming PTRIN_CP(*user32, arg.user, buf); 6495ef98042SMatthew D Fleming CP(*user32, arg.user, len); 6505ef98042SMatthew D Fleming CP(*user32, arg.user, flags); 651d3c7b9a0SKenneth D. Merry break; 652d3c7b9a0SKenneth D. Merry default: 653d3c7b9a0SKenneth D. Merry return (ENOIOCTL); 654d3c7b9a0SKenneth D. Merry } 655d3c7b9a0SKenneth D. Merry 6565ef98042SMatthew D Fleming error = mps_ioctl(dev, cmd, &arg, flag, td); 6575ef98042SMatthew D Fleming if (error == 0 && (cmd32 & IOC_OUT) != 0) { 6585ef98042SMatthew D Fleming switch (cmd32) { 6595ef98042SMatthew D Fleming case MPSIO_READ_CFG_HEADER32: 6605ef98042SMatthew D Fleming case MPSIO_READ_CFG_PAGE32: 6615ef98042SMatthew D Fleming case MPSIO_WRITE_CFG_PAGE32: 6625ef98042SMatthew D Fleming CP(arg.page, *page32, header); 6635ef98042SMatthew D Fleming CP(arg.page, *page32, page_address); 6645ef98042SMatthew D Fleming PTROUT_CP(arg.page, *page32, buf); 6655ef98042SMatthew D Fleming CP(arg.page, *page32, len); 6665ef98042SMatthew D Fleming CP(arg.page, *page32, ioc_status); 6675ef98042SMatthew D Fleming break; 6685ef98042SMatthew D Fleming 6695ef98042SMatthew D Fleming case MPSIO_READ_EXT_CFG_HEADER32: 6705ef98042SMatthew D Fleming case MPSIO_READ_EXT_CFG_PAGE32: 6715ef98042SMatthew D Fleming CP(arg.ext, *ext32, header); 6725ef98042SMatthew D Fleming CP(arg.ext, *ext32, page_address); 6735ef98042SMatthew D Fleming PTROUT_CP(arg.ext, *ext32, buf); 6745ef98042SMatthew D Fleming CP(arg.ext, *ext32, len); 6755ef98042SMatthew D Fleming CP(arg.ext, *ext32, ioc_status); 6765ef98042SMatthew D Fleming break; 6775ef98042SMatthew D Fleming 6785ef98042SMatthew D Fleming case MPSIO_RAID_ACTION32: 6795ef98042SMatthew D Fleming CP(arg.raid, *raid32, action); 6805ef98042SMatthew D Fleming CP(arg.raid, *raid32, volume_bus); 6815ef98042SMatthew D Fleming CP(arg.raid, *raid32, volume_id); 6825ef98042SMatthew D Fleming CP(arg.raid, *raid32, phys_disk_num); 6835ef98042SMatthew D Fleming CP(arg.raid, *raid32, action_data_word); 6845ef98042SMatthew D Fleming PTROUT_CP(arg.raid, *raid32, buf); 6855ef98042SMatthew D Fleming CP(arg.raid, *raid32, len); 6865ef98042SMatthew D Fleming CP(arg.raid, *raid32, volume_status); 6875ef98042SMatthew D Fleming bcopy(arg.raid.action_data, raid32->action_data, 6885ef98042SMatthew D Fleming sizeof arg.raid.action_data); 6895ef98042SMatthew D Fleming CP(arg.raid, *raid32, ioc_status); 6905ef98042SMatthew D Fleming CP(arg.raid, *raid32, write); 6915ef98042SMatthew D Fleming break; 6925ef98042SMatthew D Fleming 6935ef98042SMatthew D Fleming case MPSIO_MPS_COMMAND32: 6945ef98042SMatthew D Fleming PTROUT_CP(arg.user, *user32, req); 6955ef98042SMatthew D Fleming CP(arg.user, *user32, req_len); 6965ef98042SMatthew D Fleming PTROUT_CP(arg.user, *user32, rpl); 6975ef98042SMatthew D Fleming CP(arg.user, *user32, rpl_len); 6985ef98042SMatthew D Fleming PTROUT_CP(arg.user, *user32, buf); 6995ef98042SMatthew D Fleming CP(arg.user, *user32, len); 7005ef98042SMatthew D Fleming CP(arg.user, *user32, flags); 7015ef98042SMatthew D Fleming break; 7025ef98042SMatthew D Fleming } 7035ef98042SMatthew D Fleming } 7045ef98042SMatthew D Fleming 7055ef98042SMatthew D Fleming return (error); 7065ef98042SMatthew D Fleming } 7075ef98042SMatthew D Fleming #endif /* COMPAT_FREEBSD32 */ 7085ef98042SMatthew D Fleming 7095ef98042SMatthew D Fleming static int 7105ef98042SMatthew D Fleming mps_ioctl_devsw(struct cdev *dev, u_long com, caddr_t arg, int flag, 7115ef98042SMatthew D Fleming struct thread *td) 7125ef98042SMatthew D Fleming { 7135ef98042SMatthew D Fleming #ifdef COMPAT_FREEBSD32 7145ef98042SMatthew D Fleming if (SV_CURPROC_FLAG(SV_ILP32)) 7155ef98042SMatthew D Fleming return (mps_ioctl32(dev, com, arg, flag, td)); 7165ef98042SMatthew D Fleming #endif 7175ef98042SMatthew D Fleming return (mps_ioctl(dev, com, arg, flag, td)); 718d3c7b9a0SKenneth D. Merry } 719