1ee98c4a5SJohn Baldwin /*- 27282444bSPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 37282444bSPedro F. Giffuni * 4ee98c4a5SJohn Baldwin * Copyright (c) 2008 Yahoo!, Inc. 5ee98c4a5SJohn Baldwin * All rights reserved. 6ee98c4a5SJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 7ee98c4a5SJohn Baldwin * 8ee98c4a5SJohn Baldwin * Redistribution and use in source and binary forms, with or without 9ee98c4a5SJohn Baldwin * modification, are permitted provided that the following conditions 10ee98c4a5SJohn Baldwin * are met: 11ee98c4a5SJohn Baldwin * 1. Redistributions of source code must retain the above copyright 12ee98c4a5SJohn Baldwin * notice, this list of conditions and the following disclaimer. 13ee98c4a5SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 14ee98c4a5SJohn Baldwin * notice, this list of conditions and the following disclaimer in the 15ee98c4a5SJohn Baldwin * documentation and/or other materials provided with the distribution. 16ee98c4a5SJohn Baldwin * 3. Neither the name of the author nor the names of any co-contributors 17ee98c4a5SJohn Baldwin * may be used to endorse or promote products derived from this software 18ee98c4a5SJohn Baldwin * without specific prior written permission. 19ee98c4a5SJohn Baldwin * 20ee98c4a5SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21ee98c4a5SJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22ee98c4a5SJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23ee98c4a5SJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24ee98c4a5SJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25ee98c4a5SJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26ee98c4a5SJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27ee98c4a5SJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28ee98c4a5SJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29ee98c4a5SJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30ee98c4a5SJohn Baldwin * SUCH DAMAGE. 31ee98c4a5SJohn Baldwin * 32ee98c4a5SJohn Baldwin * LSI MPT-Fusion Host Adapter FreeBSD userland interface 33ee98c4a5SJohn Baldwin */ 34ee98c4a5SJohn Baldwin 35ee98c4a5SJohn Baldwin #include <sys/cdefs.h> 36ee98c4a5SJohn Baldwin __FBSDID("$FreeBSD$"); 37ee98c4a5SJohn Baldwin 38ee98c4a5SJohn Baldwin #include <sys/param.h> 39562894f0SBrooks Davis #ifdef __amd64__ 40562894f0SBrooks Davis #include <sys/abi_compat.h> 41562894f0SBrooks Davis #endif 42ee98c4a5SJohn Baldwin #include <sys/conf.h> 43ee98c4a5SJohn Baldwin #include <sys/errno.h> 44ee98c4a5SJohn Baldwin #include <sys/ioccom.h> 45ee98c4a5SJohn Baldwin #include <sys/mpt_ioctl.h> 46ee98c4a5SJohn Baldwin 47ee98c4a5SJohn Baldwin #include <dev/mpt/mpt.h> 48ee98c4a5SJohn Baldwin 49ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result { 50ee98c4a5SJohn Baldwin uint32_t volume_status; 51ee98c4a5SJohn Baldwin uint32_t action_data[4]; 52ee98c4a5SJohn Baldwin uint16_t action_status; 53ee98c4a5SJohn Baldwin }; 54ee98c4a5SJohn Baldwin 554124f62eSJohn Baldwin struct mpt_page_memory { 564124f62eSJohn Baldwin bus_dma_tag_t tag; 574124f62eSJohn Baldwin bus_dmamap_t map; 584124f62eSJohn Baldwin bus_addr_t paddr; 594124f62eSJohn Baldwin void *vaddr; 604124f62eSJohn Baldwin }; 614124f62eSJohn Baldwin 62ee98c4a5SJohn Baldwin static mpt_probe_handler_t mpt_user_probe; 63ee98c4a5SJohn Baldwin static mpt_attach_handler_t mpt_user_attach; 64ee98c4a5SJohn Baldwin static mpt_enable_handler_t mpt_user_enable; 65ee98c4a5SJohn Baldwin static mpt_ready_handler_t mpt_user_ready; 66ee98c4a5SJohn Baldwin static mpt_event_handler_t mpt_user_event; 67ee98c4a5SJohn Baldwin static mpt_reset_handler_t mpt_user_reset; 68ee98c4a5SJohn Baldwin static mpt_detach_handler_t mpt_user_detach; 69ee98c4a5SJohn Baldwin 70ee98c4a5SJohn Baldwin static struct mpt_personality mpt_user_personality = { 71ee98c4a5SJohn Baldwin .name = "mpt_user", 72ee98c4a5SJohn Baldwin .probe = mpt_user_probe, 73ee98c4a5SJohn Baldwin .attach = mpt_user_attach, 74ee98c4a5SJohn Baldwin .enable = mpt_user_enable, 75ee98c4a5SJohn Baldwin .ready = mpt_user_ready, 76ee98c4a5SJohn Baldwin .event = mpt_user_event, 77ee98c4a5SJohn Baldwin .reset = mpt_user_reset, 78ee98c4a5SJohn Baldwin .detach = mpt_user_detach, 79ee98c4a5SJohn Baldwin }; 80ee98c4a5SJohn Baldwin 81ee98c4a5SJohn Baldwin DECLARE_MPT_PERSONALITY(mpt_user, SI_ORDER_SECOND); 82ee98c4a5SJohn Baldwin 83ee98c4a5SJohn Baldwin static mpt_reply_handler_t mpt_user_reply_handler; 84ee98c4a5SJohn Baldwin 85ee98c4a5SJohn Baldwin static d_open_t mpt_open; 86ee98c4a5SJohn Baldwin static d_close_t mpt_close; 87ee98c4a5SJohn Baldwin static d_ioctl_t mpt_ioctl; 88ee98c4a5SJohn Baldwin 89ee98c4a5SJohn Baldwin static struct cdevsw mpt_cdevsw = { 90ee98c4a5SJohn Baldwin .d_version = D_VERSION, 91ee98c4a5SJohn Baldwin .d_flags = 0, 92ee98c4a5SJohn Baldwin .d_open = mpt_open, 93ee98c4a5SJohn Baldwin .d_close = mpt_close, 94ee98c4a5SJohn Baldwin .d_ioctl = mpt_ioctl, 95ee98c4a5SJohn Baldwin .d_name = "mpt", 96ee98c4a5SJohn Baldwin }; 97ee98c4a5SJohn Baldwin 98ee98c4a5SJohn Baldwin static MALLOC_DEFINE(M_MPTUSER, "mpt_user", "Buffers for mpt(4) ioctls"); 99ee98c4a5SJohn Baldwin 100ee98c4a5SJohn Baldwin static uint32_t user_handler_id = MPT_HANDLER_ID_NONE; 101ee98c4a5SJohn Baldwin 10287e255acSMarius Strobl static int 103ee98c4a5SJohn Baldwin mpt_user_probe(struct mpt_softc *mpt) 104ee98c4a5SJohn Baldwin { 105ee98c4a5SJohn Baldwin 106ee98c4a5SJohn Baldwin /* Attach to every controller. */ 107ee98c4a5SJohn Baldwin return (0); 108ee98c4a5SJohn Baldwin } 109ee98c4a5SJohn Baldwin 11087e255acSMarius Strobl static int 111ee98c4a5SJohn Baldwin mpt_user_attach(struct mpt_softc *mpt) 112ee98c4a5SJohn Baldwin { 113ee98c4a5SJohn Baldwin mpt_handler_t handler; 114ee98c4a5SJohn Baldwin int error, unit; 115ee98c4a5SJohn Baldwin 116ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 117ee98c4a5SJohn Baldwin handler.reply_handler = mpt_user_reply_handler; 118ee98c4a5SJohn Baldwin error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 119ee98c4a5SJohn Baldwin &user_handler_id); 120ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 121ee98c4a5SJohn Baldwin if (error != 0) { 122ee98c4a5SJohn Baldwin mpt_prt(mpt, "Unable to register user handler!\n"); 123ee98c4a5SJohn Baldwin return (error); 124ee98c4a5SJohn Baldwin } 125ee98c4a5SJohn Baldwin unit = device_get_unit(mpt->dev); 126ee98c4a5SJohn Baldwin mpt->cdev = make_dev(&mpt_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640, 127ee98c4a5SJohn Baldwin "mpt%d", unit); 128ee98c4a5SJohn Baldwin if (mpt->cdev == NULL) { 129ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 130ee98c4a5SJohn Baldwin mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 131ee98c4a5SJohn Baldwin user_handler_id); 132ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 133ee98c4a5SJohn Baldwin return (ENOMEM); 134ee98c4a5SJohn Baldwin } 135ee98c4a5SJohn Baldwin mpt->cdev->si_drv1 = mpt; 136ee98c4a5SJohn Baldwin return (0); 137ee98c4a5SJohn Baldwin } 138ee98c4a5SJohn Baldwin 13987e255acSMarius Strobl static int 140ee98c4a5SJohn Baldwin mpt_user_enable(struct mpt_softc *mpt) 141ee98c4a5SJohn Baldwin { 142ee98c4a5SJohn Baldwin 143ee98c4a5SJohn Baldwin return (0); 144ee98c4a5SJohn Baldwin } 145ee98c4a5SJohn Baldwin 14687e255acSMarius Strobl static void 147ee98c4a5SJohn Baldwin mpt_user_ready(struct mpt_softc *mpt) 148ee98c4a5SJohn Baldwin { 14987e255acSMarius Strobl 150ee98c4a5SJohn Baldwin } 151ee98c4a5SJohn Baldwin 15287e255acSMarius Strobl static int 153ee98c4a5SJohn Baldwin mpt_user_event(struct mpt_softc *mpt, request_t *req, 154ee98c4a5SJohn Baldwin MSG_EVENT_NOTIFY_REPLY *msg) 155ee98c4a5SJohn Baldwin { 156ee98c4a5SJohn Baldwin 157ee98c4a5SJohn Baldwin /* Someday we may want to let a user daemon listen for events? */ 158ee98c4a5SJohn Baldwin return (0); 159ee98c4a5SJohn Baldwin } 160ee98c4a5SJohn Baldwin 16187e255acSMarius Strobl static void 162ee98c4a5SJohn Baldwin mpt_user_reset(struct mpt_softc *mpt, int type) 163ee98c4a5SJohn Baldwin { 16487e255acSMarius Strobl 165ee98c4a5SJohn Baldwin } 166ee98c4a5SJohn Baldwin 16787e255acSMarius Strobl static void 168ee98c4a5SJohn Baldwin mpt_user_detach(struct mpt_softc *mpt) 169ee98c4a5SJohn Baldwin { 170ee98c4a5SJohn Baldwin mpt_handler_t handler; 171ee98c4a5SJohn Baldwin 172ee98c4a5SJohn Baldwin /* XXX: do a purge of pending requests? */ 173ee98c4a5SJohn Baldwin destroy_dev(mpt->cdev); 174ee98c4a5SJohn Baldwin 175ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 176ee98c4a5SJohn Baldwin handler.reply_handler = mpt_user_reply_handler; 177ee98c4a5SJohn Baldwin mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 178ee98c4a5SJohn Baldwin user_handler_id); 179ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 180ee98c4a5SJohn Baldwin } 181ee98c4a5SJohn Baldwin 182ee98c4a5SJohn Baldwin static int 18300b4e54aSWarner Losh mpt_open(struct cdev *dev, int flags, int fmt, struct thread *td) 184ee98c4a5SJohn Baldwin { 185ee98c4a5SJohn Baldwin 186ee98c4a5SJohn Baldwin return (0); 187ee98c4a5SJohn Baldwin } 188ee98c4a5SJohn Baldwin 189ee98c4a5SJohn Baldwin static int 19000b4e54aSWarner Losh mpt_close(struct cdev *dev, int flags, int fmt, struct thread *td) 191ee98c4a5SJohn Baldwin { 192ee98c4a5SJohn Baldwin 193ee98c4a5SJohn Baldwin return (0); 194ee98c4a5SJohn Baldwin } 195ee98c4a5SJohn Baldwin 196ee98c4a5SJohn Baldwin static int 1974124f62eSJohn Baldwin mpt_alloc_buffer(struct mpt_softc *mpt, struct mpt_page_memory *page_mem, 1984124f62eSJohn Baldwin size_t len) 1994124f62eSJohn Baldwin { 2004124f62eSJohn Baldwin struct mpt_map_info mi; 2014124f62eSJohn Baldwin int error; 2024124f62eSJohn Baldwin 2034124f62eSJohn Baldwin page_mem->vaddr = NULL; 2044124f62eSJohn Baldwin 2054124f62eSJohn Baldwin /* Limit requests to 16M. */ 2064124f62eSJohn Baldwin if (len > 16 * 1024 * 1024) 2074124f62eSJohn Baldwin return (ENOSPC); 2084124f62eSJohn Baldwin error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 0, 2094124f62eSJohn Baldwin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 2104124f62eSJohn Baldwin len, 1, len, 0, &page_mem->tag); 2114124f62eSJohn Baldwin if (error) 2124124f62eSJohn Baldwin return (error); 2134124f62eSJohn Baldwin error = bus_dmamem_alloc(page_mem->tag, &page_mem->vaddr, 2146c5276c8SMarius Strobl BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &page_mem->map); 2154124f62eSJohn Baldwin if (error) { 2164124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2174124f62eSJohn Baldwin return (error); 2184124f62eSJohn Baldwin } 2194124f62eSJohn Baldwin mi.mpt = mpt; 2204124f62eSJohn Baldwin error = bus_dmamap_load(page_mem->tag, page_mem->map, page_mem->vaddr, 2214124f62eSJohn Baldwin len, mpt_map_rquest, &mi, BUS_DMA_NOWAIT); 2224124f62eSJohn Baldwin if (error == 0) 2234124f62eSJohn Baldwin error = mi.error; 2244124f62eSJohn Baldwin if (error) { 2254124f62eSJohn Baldwin bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map); 2264124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2274124f62eSJohn Baldwin page_mem->vaddr = NULL; 2284124f62eSJohn Baldwin return (error); 2294124f62eSJohn Baldwin } 2304124f62eSJohn Baldwin page_mem->paddr = mi.phys; 2314124f62eSJohn Baldwin return (0); 2324124f62eSJohn Baldwin } 2334124f62eSJohn Baldwin 2344124f62eSJohn Baldwin static void 2354124f62eSJohn Baldwin mpt_free_buffer(struct mpt_page_memory *page_mem) 2364124f62eSJohn Baldwin { 2374124f62eSJohn Baldwin 2384124f62eSJohn Baldwin if (page_mem->vaddr == NULL) 2394124f62eSJohn Baldwin return; 2404124f62eSJohn Baldwin bus_dmamap_unload(page_mem->tag, page_mem->map); 2414124f62eSJohn Baldwin bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map); 2424124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2434124f62eSJohn Baldwin page_mem->vaddr = NULL; 2444124f62eSJohn Baldwin } 2454124f62eSJohn Baldwin 2464124f62eSJohn Baldwin static int 247ee98c4a5SJohn Baldwin mpt_user_read_cfg_header(struct mpt_softc *mpt, 248ee98c4a5SJohn Baldwin struct mpt_cfg_page_req *page_req) 249ee98c4a5SJohn Baldwin { 250ee98c4a5SJohn Baldwin request_t *req; 251ee98c4a5SJohn Baldwin cfgparms_t params; 252ee98c4a5SJohn Baldwin MSG_CONFIG *cfgp; 253ee98c4a5SJohn Baldwin int error; 254ee98c4a5SJohn Baldwin 255ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 256ee98c4a5SJohn Baldwin if (req == NULL) { 257ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_header: Get request failed!\n"); 258ee98c4a5SJohn Baldwin return (ENOMEM); 259ee98c4a5SJohn Baldwin } 260ee98c4a5SJohn Baldwin 261ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_HEADER; 262ee98c4a5SJohn Baldwin params.PageVersion = 0; 263ee98c4a5SJohn Baldwin params.PageLength = 0; 264ee98c4a5SJohn Baldwin params.PageNumber = page_req->header.PageNumber; 265ee98c4a5SJohn Baldwin params.PageType = page_req->header.PageType; 2667ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 267ee98c4a5SJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0, 268ee98c4a5SJohn Baldwin TRUE, 5000); 269ee98c4a5SJohn Baldwin if (error != 0) { 270ee98c4a5SJohn Baldwin /* 271ee98c4a5SJohn Baldwin * Leave the request. Without resetting the chip, it's 272ee98c4a5SJohn Baldwin * still owned by it and we'll just get into trouble 273ee98c4a5SJohn Baldwin * freeing it now. Mark it as abandoned so that if it 274ee98c4a5SJohn Baldwin * shows up later it can be freed. 275ee98c4a5SJohn Baldwin */ 276ee98c4a5SJohn Baldwin mpt_prt(mpt, "read_cfg_header timed out\n"); 277ee98c4a5SJohn Baldwin return (ETIMEDOUT); 278ee98c4a5SJohn Baldwin } 279ee98c4a5SJohn Baldwin 2807ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 281ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) { 282ee98c4a5SJohn Baldwin cfgp = req->req_vbuf; 283ee98c4a5SJohn Baldwin bcopy(&cfgp->Header, &page_req->header, 284ee98c4a5SJohn Baldwin sizeof(page_req->header)); 285ee98c4a5SJohn Baldwin } 286ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 287ee98c4a5SJohn Baldwin return (0); 288ee98c4a5SJohn Baldwin } 289ee98c4a5SJohn Baldwin 290ee98c4a5SJohn Baldwin static int 291ee98c4a5SJohn Baldwin mpt_user_read_cfg_page(struct mpt_softc *mpt, struct mpt_cfg_page_req *page_req, 2924124f62eSJohn Baldwin struct mpt_page_memory *mpt_page) 293ee98c4a5SJohn Baldwin { 294ee98c4a5SJohn Baldwin CONFIG_PAGE_HEADER *hdr; 295ee98c4a5SJohn Baldwin request_t *req; 296ee98c4a5SJohn Baldwin cfgparms_t params; 297ee98c4a5SJohn Baldwin int error; 298ee98c4a5SJohn Baldwin 299ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 300ee98c4a5SJohn Baldwin if (req == NULL) { 301ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_page: Get request failed!\n"); 302ee98c4a5SJohn Baldwin return (ENOMEM); 303ee98c4a5SJohn Baldwin } 304ee98c4a5SJohn Baldwin 3054124f62eSJohn Baldwin hdr = mpt_page->vaddr; 306ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 307ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 308ee98c4a5SJohn Baldwin params.PageLength = hdr->PageLength; 309ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 310ee98c4a5SJohn Baldwin params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK; 3117ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 3126c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, 3136c5276c8SMarius Strobl BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3144124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 3157ee37807SMarius Strobl le32toh(page_req->len), TRUE, 5000); 316ee98c4a5SJohn Baldwin if (error != 0) { 317ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_page timed out\n"); 318ee98c4a5SJohn Baldwin return (ETIMEDOUT); 319ee98c4a5SJohn Baldwin } 320ee98c4a5SJohn Baldwin 3217ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 3224124f62eSJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) 3234124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 3246c5276c8SMarius Strobl BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 325ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 326ee98c4a5SJohn Baldwin return (0); 327ee98c4a5SJohn Baldwin } 328ee98c4a5SJohn Baldwin 329ee98c4a5SJohn Baldwin static int 330ee98c4a5SJohn Baldwin mpt_user_read_extcfg_header(struct mpt_softc *mpt, 331ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req) 332ee98c4a5SJohn Baldwin { 333ee98c4a5SJohn Baldwin request_t *req; 334ee98c4a5SJohn Baldwin cfgparms_t params; 335ee98c4a5SJohn Baldwin MSG_CONFIG_REPLY *cfgp; 336ee98c4a5SJohn Baldwin int error; 337ee98c4a5SJohn Baldwin 338ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 339ee98c4a5SJohn Baldwin if (req == NULL) { 340ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_header: Get request failed!\n"); 341ee98c4a5SJohn Baldwin return (ENOMEM); 342ee98c4a5SJohn Baldwin } 343ee98c4a5SJohn Baldwin 344ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_HEADER; 345ee98c4a5SJohn Baldwin params.PageVersion = ext_page_req->header.PageVersion; 346ee98c4a5SJohn Baldwin params.PageLength = 0; 347ee98c4a5SJohn Baldwin params.PageNumber = ext_page_req->header.PageNumber; 348ee98c4a5SJohn Baldwin params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 3497ee37807SMarius Strobl params.PageAddress = le32toh(ext_page_req->page_address); 350ee98c4a5SJohn Baldwin params.ExtPageType = ext_page_req->header.ExtPageType; 351ee98c4a5SJohn Baldwin params.ExtPageLength = 0; 352ee98c4a5SJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0, 353ee98c4a5SJohn Baldwin TRUE, 5000); 354ee98c4a5SJohn Baldwin if (error != 0) { 355ee98c4a5SJohn Baldwin /* 356ee98c4a5SJohn Baldwin * Leave the request. Without resetting the chip, it's 357ee98c4a5SJohn Baldwin * still owned by it and we'll just get into trouble 358ee98c4a5SJohn Baldwin * freeing it now. Mark it as abandoned so that if it 359ee98c4a5SJohn Baldwin * shows up later it can be freed. 360ee98c4a5SJohn Baldwin */ 361ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_header timed out\n"); 362ee98c4a5SJohn Baldwin return (ETIMEDOUT); 363ee98c4a5SJohn Baldwin } 364ee98c4a5SJohn Baldwin 3657ee37807SMarius Strobl ext_page_req->ioc_status = htole16(req->IOCStatus); 366ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) { 367ee98c4a5SJohn Baldwin cfgp = req->req_vbuf; 368ee98c4a5SJohn Baldwin ext_page_req->header.PageVersion = cfgp->Header.PageVersion; 369ee98c4a5SJohn Baldwin ext_page_req->header.PageNumber = cfgp->Header.PageNumber; 370ee98c4a5SJohn Baldwin ext_page_req->header.PageType = cfgp->Header.PageType; 371ee98c4a5SJohn Baldwin ext_page_req->header.ExtPageLength = cfgp->ExtPageLength; 372ee98c4a5SJohn Baldwin ext_page_req->header.ExtPageType = cfgp->ExtPageType; 373ee98c4a5SJohn Baldwin } 374ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 375ee98c4a5SJohn Baldwin return (0); 376ee98c4a5SJohn Baldwin } 377ee98c4a5SJohn Baldwin 378ee98c4a5SJohn Baldwin static int 379ee98c4a5SJohn Baldwin mpt_user_read_extcfg_page(struct mpt_softc *mpt, 3804124f62eSJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req, struct mpt_page_memory *mpt_page) 381ee98c4a5SJohn Baldwin { 382ee98c4a5SJohn Baldwin CONFIG_EXTENDED_PAGE_HEADER *hdr; 383ee98c4a5SJohn Baldwin request_t *req; 384ee98c4a5SJohn Baldwin cfgparms_t params; 385ee98c4a5SJohn Baldwin int error; 386ee98c4a5SJohn Baldwin 387ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 388ee98c4a5SJohn Baldwin if (req == NULL) { 389ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_page: Get request failed!\n"); 390ee98c4a5SJohn Baldwin return (ENOMEM); 391ee98c4a5SJohn Baldwin } 392ee98c4a5SJohn Baldwin 3934124f62eSJohn Baldwin hdr = mpt_page->vaddr; 394ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 395ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 396ee98c4a5SJohn Baldwin params.PageLength = 0; 397ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 398ee98c4a5SJohn Baldwin params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 3997ee37807SMarius Strobl params.PageAddress = le32toh(ext_page_req->page_address); 400ee98c4a5SJohn Baldwin params.ExtPageType = hdr->ExtPageType; 401ee98c4a5SJohn Baldwin params.ExtPageLength = hdr->ExtPageLength; 4026c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, 4036c5276c8SMarius Strobl BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 4044124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 4057ee37807SMarius Strobl le32toh(ext_page_req->len), TRUE, 5000); 406ee98c4a5SJohn Baldwin if (error != 0) { 407ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_page timed out\n"); 408ee98c4a5SJohn Baldwin return (ETIMEDOUT); 409ee98c4a5SJohn Baldwin } 410ee98c4a5SJohn Baldwin 4117ee37807SMarius Strobl ext_page_req->ioc_status = htole16(req->IOCStatus); 4124124f62eSJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) 4134124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 4146c5276c8SMarius Strobl BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 415ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 416ee98c4a5SJohn Baldwin return (0); 417ee98c4a5SJohn Baldwin } 418ee98c4a5SJohn Baldwin 419ee98c4a5SJohn Baldwin static int 420ee98c4a5SJohn Baldwin mpt_user_write_cfg_page(struct mpt_softc *mpt, 4214124f62eSJohn Baldwin struct mpt_cfg_page_req *page_req, struct mpt_page_memory *mpt_page) 422ee98c4a5SJohn Baldwin { 423ee98c4a5SJohn Baldwin CONFIG_PAGE_HEADER *hdr; 424ee98c4a5SJohn Baldwin request_t *req; 425ee98c4a5SJohn Baldwin cfgparms_t params; 426ee98c4a5SJohn Baldwin u_int hdr_attr; 427ee98c4a5SJohn Baldwin int error; 428ee98c4a5SJohn Baldwin 4294124f62eSJohn Baldwin hdr = mpt_page->vaddr; 430ee98c4a5SJohn Baldwin hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK; 431ee98c4a5SJohn Baldwin if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE && 432ee98c4a5SJohn Baldwin hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) { 433ee98c4a5SJohn Baldwin mpt_prt(mpt, "page type 0x%x not changeable\n", 434ee98c4a5SJohn Baldwin hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); 435ee98c4a5SJohn Baldwin return (EINVAL); 436ee98c4a5SJohn Baldwin } 437ee98c4a5SJohn Baldwin 438ee98c4a5SJohn Baldwin #if 0 439ee98c4a5SJohn Baldwin /* 440ee98c4a5SJohn Baldwin * We shouldn't mask off other bits here. 441ee98c4a5SJohn Baldwin */ 442ee98c4a5SJohn Baldwin hdr->PageType &= ~MPI_CONFIG_PAGETYPE_MASK; 443ee98c4a5SJohn Baldwin #endif 444ee98c4a5SJohn Baldwin 445ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 446ee98c4a5SJohn Baldwin if (req == NULL) 447ee98c4a5SJohn Baldwin return (ENOMEM); 448ee98c4a5SJohn Baldwin 4496c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_PREREAD | 4506c5276c8SMarius Strobl BUS_DMASYNC_PREWRITE); 451ee98c4a5SJohn Baldwin 452ee98c4a5SJohn Baldwin /* 453ee98c4a5SJohn Baldwin * There isn't any point in restoring stripped out attributes 454ee98c4a5SJohn Baldwin * if you then mask them going down to issue the request. 455ee98c4a5SJohn Baldwin */ 456ee98c4a5SJohn Baldwin 457ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; 458ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 459ee98c4a5SJohn Baldwin params.PageLength = hdr->PageLength; 460ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 4617ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 462ee98c4a5SJohn Baldwin #if 0 463ee98c4a5SJohn Baldwin /* Restore stripped out attributes */ 464ee98c4a5SJohn Baldwin hdr->PageType |= hdr_attr; 465ee98c4a5SJohn Baldwin params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK; 466ee98c4a5SJohn Baldwin #else 467ee98c4a5SJohn Baldwin params.PageType = hdr->PageType; 468ee98c4a5SJohn Baldwin #endif 4694124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 4707ee37807SMarius Strobl le32toh(page_req->len), TRUE, 5000); 471ee98c4a5SJohn Baldwin if (error != 0) { 472ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_write_cfg_page timed out\n"); 473ee98c4a5SJohn Baldwin return (ETIMEDOUT); 474ee98c4a5SJohn Baldwin } 475ee98c4a5SJohn Baldwin 4767ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 4776c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_POSTREAD | 4786c5276c8SMarius Strobl BUS_DMASYNC_POSTWRITE); 479ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 480ee98c4a5SJohn Baldwin return (0); 481ee98c4a5SJohn Baldwin } 482ee98c4a5SJohn Baldwin 483ee98c4a5SJohn Baldwin static int 484ee98c4a5SJohn Baldwin mpt_user_reply_handler(struct mpt_softc *mpt, request_t *req, 485ee98c4a5SJohn Baldwin uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame) 486ee98c4a5SJohn Baldwin { 487ee98c4a5SJohn Baldwin MSG_RAID_ACTION_REPLY *reply; 488ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result *res; 489ee98c4a5SJohn Baldwin 490ee98c4a5SJohn Baldwin if (req == NULL) 491ee98c4a5SJohn Baldwin return (TRUE); 492ee98c4a5SJohn Baldwin 493ee98c4a5SJohn Baldwin if (reply_frame != NULL) { 494ee98c4a5SJohn Baldwin reply = (MSG_RAID_ACTION_REPLY *)reply_frame; 495ee98c4a5SJohn Baldwin req->IOCStatus = le16toh(reply->IOCStatus); 496ee98c4a5SJohn Baldwin res = (struct mpt_user_raid_action_result *) 497ee98c4a5SJohn Baldwin (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt)); 498ee98c4a5SJohn Baldwin res->action_status = reply->ActionStatus; 499ee98c4a5SJohn Baldwin res->volume_status = reply->VolumeStatus; 500ee98c4a5SJohn Baldwin bcopy(&reply->ActionData, res->action_data, 501ee98c4a5SJohn Baldwin sizeof(res->action_data)); 502ee98c4a5SJohn Baldwin } 503ee98c4a5SJohn Baldwin 504ee98c4a5SJohn Baldwin req->state &= ~REQ_STATE_QUEUED; 505ee98c4a5SJohn Baldwin req->state |= REQ_STATE_DONE; 506ee98c4a5SJohn Baldwin TAILQ_REMOVE(&mpt->request_pending_list, req, links); 507ee98c4a5SJohn Baldwin 508ee98c4a5SJohn Baldwin if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) { 509ee98c4a5SJohn Baldwin wakeup(req); 510ee98c4a5SJohn Baldwin } else if ((req->state & REQ_STATE_TIMEDOUT) != 0) { 511ee98c4a5SJohn Baldwin /* 512ee98c4a5SJohn Baldwin * Whew- we can free this request (late completion) 513ee98c4a5SJohn Baldwin */ 514ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 515ee98c4a5SJohn Baldwin } 516ee98c4a5SJohn Baldwin 517ee98c4a5SJohn Baldwin return (TRUE); 518ee98c4a5SJohn Baldwin } 519ee98c4a5SJohn Baldwin 520ee98c4a5SJohn Baldwin /* 521ee98c4a5SJohn Baldwin * We use the first part of the request buffer after the request frame 522ee98c4a5SJohn Baldwin * to hold the action data and action status from the RAID reply. The 523ee98c4a5SJohn Baldwin * rest of the request buffer is used to hold the buffer for the 524ee98c4a5SJohn Baldwin * action SGE. 525ee98c4a5SJohn Baldwin */ 526ee98c4a5SJohn Baldwin static int 527ee98c4a5SJohn Baldwin mpt_user_raid_action(struct mpt_softc *mpt, struct mpt_raid_action *raid_act, 5284124f62eSJohn Baldwin struct mpt_page_memory *mpt_page) 529ee98c4a5SJohn Baldwin { 530ee98c4a5SJohn Baldwin request_t *req; 531ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result *res; 532ee98c4a5SJohn Baldwin MSG_RAID_ACTION_REQUEST *rap; 533ee98c4a5SJohn Baldwin SGE_SIMPLE32 *se; 534ee98c4a5SJohn Baldwin int error; 535ee98c4a5SJohn Baldwin 536ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 537ee98c4a5SJohn Baldwin if (req == NULL) 538ee98c4a5SJohn Baldwin return (ENOMEM); 539ee98c4a5SJohn Baldwin rap = req->req_vbuf; 540ee98c4a5SJohn Baldwin memset(rap, 0, sizeof *rap); 541ee98c4a5SJohn Baldwin rap->Action = raid_act->action; 542ee98c4a5SJohn Baldwin rap->ActionDataWord = raid_act->action_data_word; 543ee98c4a5SJohn Baldwin rap->Function = MPI_FUNCTION_RAID_ACTION; 544ee98c4a5SJohn Baldwin rap->VolumeID = raid_act->volume_id; 545ee98c4a5SJohn Baldwin rap->VolumeBus = raid_act->volume_bus; 546ee98c4a5SJohn Baldwin rap->PhysDiskNum = raid_act->phys_disk_num; 547ee98c4a5SJohn Baldwin se = (SGE_SIMPLE32 *)&rap->ActionDataSGE; 5484124f62eSJohn Baldwin if (mpt_page->vaddr != NULL && raid_act->len != 0) { 5494124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 5506c5276c8SMarius Strobl BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 5517ee37807SMarius Strobl se->Address = htole32(mpt_page->paddr); 5527ee37807SMarius Strobl MPI_pSGE_SET_LENGTH(se, le32toh(raid_act->len)); 553ee98c4a5SJohn Baldwin MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 554ee98c4a5SJohn Baldwin MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 555ee98c4a5SJohn Baldwin MPI_SGE_FLAGS_END_OF_LIST | 556cb5a9183SXin LI (raid_act->write ? MPI_SGE_FLAGS_HOST_TO_IOC : 557cb5a9183SXin LI MPI_SGE_FLAGS_IOC_TO_HOST))); 558ee98c4a5SJohn Baldwin } 5597ee37807SMarius Strobl se->FlagsLength = htole32(se->FlagsLength); 560ee98c4a5SJohn Baldwin rap->MsgContext = htole32(req->index | user_handler_id); 561ee98c4a5SJohn Baldwin 562ee98c4a5SJohn Baldwin mpt_check_doorbell(mpt); 563ee98c4a5SJohn Baldwin mpt_send_cmd(mpt, req); 564ee98c4a5SJohn Baldwin 565ee98c4a5SJohn Baldwin error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, TRUE, 566ee98c4a5SJohn Baldwin 2000); 567ee98c4a5SJohn Baldwin if (error != 0) { 568ee98c4a5SJohn Baldwin /* 569ee98c4a5SJohn Baldwin * Leave request so it can be cleaned up later. 570ee98c4a5SJohn Baldwin */ 571ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_raid_action timed out\n"); 572ee98c4a5SJohn Baldwin return (error); 573ee98c4a5SJohn Baldwin } 574ee98c4a5SJohn Baldwin 5757ee37807SMarius Strobl raid_act->ioc_status = htole16(req->IOCStatus); 576ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 577ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 578ee98c4a5SJohn Baldwin return (0); 579ee98c4a5SJohn Baldwin } 580ee98c4a5SJohn Baldwin 581ee98c4a5SJohn Baldwin res = (struct mpt_user_raid_action_result *) 582ee98c4a5SJohn Baldwin (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt)); 583ee98c4a5SJohn Baldwin raid_act->volume_status = res->volume_status; 584ee98c4a5SJohn Baldwin raid_act->action_status = res->action_status; 585ee98c4a5SJohn Baldwin bcopy(res->action_data, raid_act->action_data, 586ee98c4a5SJohn Baldwin sizeof(res->action_data)); 5874124f62eSJohn Baldwin if (mpt_page->vaddr != NULL) 5884124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 5896c5276c8SMarius Strobl BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 590ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 591ee98c4a5SJohn Baldwin return (0); 592ee98c4a5SJohn Baldwin } 593ee98c4a5SJohn Baldwin 594ee98c4a5SJohn Baldwin static int 59500b4e54aSWarner Losh mpt_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 596ee98c4a5SJohn Baldwin { 597ee98c4a5SJohn Baldwin struct mpt_softc *mpt; 598ee98c4a5SJohn Baldwin struct mpt_cfg_page_req *page_req; 599ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req; 600ee98c4a5SJohn Baldwin struct mpt_raid_action *raid_act; 6014124f62eSJohn Baldwin struct mpt_page_memory mpt_page; 602ee98c4a5SJohn Baldwin #ifdef __amd64__ 603ee98c4a5SJohn Baldwin struct mpt_cfg_page_req32 *page_req32; 604ee98c4a5SJohn Baldwin struct mpt_cfg_page_req page_req_swab; 605ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req32 *ext_page_req32; 606ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req ext_page_req_swab; 607ee98c4a5SJohn Baldwin struct mpt_raid_action32 *raid_act32; 608ee98c4a5SJohn Baldwin struct mpt_raid_action raid_act_swab; 609ee98c4a5SJohn Baldwin #endif 610ee98c4a5SJohn Baldwin int error; 611ee98c4a5SJohn Baldwin 612ee98c4a5SJohn Baldwin mpt = dev->si_drv1; 613ee98c4a5SJohn Baldwin page_req = (void *)arg; 614ee98c4a5SJohn Baldwin ext_page_req = (void *)arg; 615ee98c4a5SJohn Baldwin raid_act = (void *)arg; 6164124f62eSJohn Baldwin mpt_page.vaddr = NULL; 617ee98c4a5SJohn Baldwin 618ee98c4a5SJohn Baldwin #ifdef __amd64__ 619ee98c4a5SJohn Baldwin /* Convert 32-bit structs to native ones. */ 620ee98c4a5SJohn Baldwin page_req32 = (void *)arg; 621ee98c4a5SJohn Baldwin ext_page_req32 = (void *)arg; 622ee98c4a5SJohn Baldwin raid_act32 = (void *)arg; 623ee98c4a5SJohn Baldwin switch (cmd) { 624ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 625ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 626ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 627ee98c4a5SJohn Baldwin page_req = &page_req_swab; 628ee98c4a5SJohn Baldwin page_req->header = page_req32->header; 629ee98c4a5SJohn Baldwin page_req->page_address = page_req32->page_address; 630ee98c4a5SJohn Baldwin page_req->buf = PTRIN(page_req32->buf); 631ee98c4a5SJohn Baldwin page_req->len = page_req32->len; 632ee98c4a5SJohn Baldwin page_req->ioc_status = page_req32->ioc_status; 633ee98c4a5SJohn Baldwin break; 634ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 635ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 636ee98c4a5SJohn Baldwin ext_page_req = &ext_page_req_swab; 637ee98c4a5SJohn Baldwin ext_page_req->header = ext_page_req32->header; 638ee98c4a5SJohn Baldwin ext_page_req->page_address = ext_page_req32->page_address; 639ee98c4a5SJohn Baldwin ext_page_req->buf = PTRIN(ext_page_req32->buf); 640ee98c4a5SJohn Baldwin ext_page_req->len = ext_page_req32->len; 641ee98c4a5SJohn Baldwin ext_page_req->ioc_status = ext_page_req32->ioc_status; 642ee98c4a5SJohn Baldwin break; 643ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 644ee98c4a5SJohn Baldwin raid_act = &raid_act_swab; 645ee98c4a5SJohn Baldwin raid_act->action = raid_act32->action; 646ee98c4a5SJohn Baldwin raid_act->volume_bus = raid_act32->volume_bus; 647ee98c4a5SJohn Baldwin raid_act->volume_id = raid_act32->volume_id; 648ee98c4a5SJohn Baldwin raid_act->phys_disk_num = raid_act32->phys_disk_num; 649ee98c4a5SJohn Baldwin raid_act->action_data_word = raid_act32->action_data_word; 650ee98c4a5SJohn Baldwin raid_act->buf = PTRIN(raid_act32->buf); 651ee98c4a5SJohn Baldwin raid_act->len = raid_act32->len; 652ee98c4a5SJohn Baldwin raid_act->volume_status = raid_act32->volume_status; 653ee98c4a5SJohn Baldwin bcopy(raid_act32->action_data, raid_act->action_data, 654ee98c4a5SJohn Baldwin sizeof(raid_act->action_data)); 655ee98c4a5SJohn Baldwin raid_act->action_status = raid_act32->action_status; 656ee98c4a5SJohn Baldwin raid_act->ioc_status = raid_act32->ioc_status; 657ee98c4a5SJohn Baldwin raid_act->write = raid_act32->write; 658ee98c4a5SJohn Baldwin break; 659ee98c4a5SJohn Baldwin } 660ee98c4a5SJohn Baldwin #endif 661ee98c4a5SJohn Baldwin 662ee98c4a5SJohn Baldwin switch (cmd) { 663ee98c4a5SJohn Baldwin #ifdef __amd64__ 664ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 665ee98c4a5SJohn Baldwin #endif 666ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER: 667ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 668ee98c4a5SJohn Baldwin error = mpt_user_read_cfg_header(mpt, page_req); 669ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 670ee98c4a5SJohn Baldwin break; 671ee98c4a5SJohn Baldwin #ifdef __amd64__ 672ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 673ee98c4a5SJohn Baldwin #endif 674ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE: 6758276c414SEd Maste if (page_req->len < (int)sizeof(CONFIG_PAGE_HEADER)) { 6768276c414SEd Maste error = EINVAL; 6778276c414SEd Maste break; 6788276c414SEd Maste } 6794124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len); 6804124f62eSJohn Baldwin if (error) 681ee98c4a5SJohn Baldwin break; 6824124f62eSJohn Baldwin error = copyin(page_req->buf, mpt_page.vaddr, 683ee98c4a5SJohn Baldwin sizeof(CONFIG_PAGE_HEADER)); 684ee98c4a5SJohn Baldwin if (error) 685ee98c4a5SJohn Baldwin break; 686ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 6874124f62eSJohn Baldwin error = mpt_user_read_cfg_page(mpt, page_req, &mpt_page); 688ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 689ee98c4a5SJohn Baldwin if (error) 690ee98c4a5SJohn Baldwin break; 6914124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, page_req->buf, page_req->len); 692ee98c4a5SJohn Baldwin break; 693ee98c4a5SJohn Baldwin #ifdef __amd64__ 694ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 695ee98c4a5SJohn Baldwin #endif 696ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER: 697ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 698ee98c4a5SJohn Baldwin error = mpt_user_read_extcfg_header(mpt, ext_page_req); 699ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 700ee98c4a5SJohn Baldwin break; 701ee98c4a5SJohn Baldwin #ifdef __amd64__ 702ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 703ee98c4a5SJohn Baldwin #endif 704ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE: 7058276c414SEd Maste if (ext_page_req->len < 7068276c414SEd Maste (int)sizeof(CONFIG_EXTENDED_PAGE_HEADER)) { 7078276c414SEd Maste error = EINVAL; 7088276c414SEd Maste break; 7098276c414SEd Maste } 7104124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, ext_page_req->len); 7114124f62eSJohn Baldwin if (error) 712ee98c4a5SJohn Baldwin break; 7134124f62eSJohn Baldwin error = copyin(ext_page_req->buf, mpt_page.vaddr, 714ee98c4a5SJohn Baldwin sizeof(CONFIG_EXTENDED_PAGE_HEADER)); 715ee98c4a5SJohn Baldwin if (error) 716ee98c4a5SJohn Baldwin break; 717ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7184124f62eSJohn Baldwin error = mpt_user_read_extcfg_page(mpt, ext_page_req, &mpt_page); 719ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 720ee98c4a5SJohn Baldwin if (error) 721ee98c4a5SJohn Baldwin break; 7224124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, ext_page_req->buf, 7234124f62eSJohn Baldwin ext_page_req->len); 724ee98c4a5SJohn Baldwin break; 725ee98c4a5SJohn Baldwin #ifdef __amd64__ 726ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 727ee98c4a5SJohn Baldwin #endif 728ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE: 7298276c414SEd Maste if (page_req->len < (int)sizeof(CONFIG_PAGE_HEADER)) { 7308276c414SEd Maste error = EINVAL; 7318276c414SEd Maste break; 7328276c414SEd Maste } 7334124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len); 7344124f62eSJohn Baldwin if (error) 735ee98c4a5SJohn Baldwin break; 7364124f62eSJohn Baldwin error = copyin(page_req->buf, mpt_page.vaddr, page_req->len); 737ee98c4a5SJohn Baldwin if (error) 738ee98c4a5SJohn Baldwin break; 739ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7404124f62eSJohn Baldwin error = mpt_user_write_cfg_page(mpt, page_req, &mpt_page); 741ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 742ee98c4a5SJohn Baldwin break; 743ee98c4a5SJohn Baldwin #ifdef __amd64__ 744ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 745ee98c4a5SJohn Baldwin #endif 746ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION: 747ee98c4a5SJohn Baldwin if (raid_act->buf != NULL) { 7484124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, raid_act->len); 7494124f62eSJohn Baldwin if (error) 750ee98c4a5SJohn Baldwin break; 7514124f62eSJohn Baldwin error = copyin(raid_act->buf, mpt_page.vaddr, 7524124f62eSJohn Baldwin raid_act->len); 753ee98c4a5SJohn Baldwin if (error) 754ee98c4a5SJohn Baldwin break; 755ee98c4a5SJohn Baldwin } 756ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7574124f62eSJohn Baldwin error = mpt_user_raid_action(mpt, raid_act, &mpt_page); 758ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 759ee98c4a5SJohn Baldwin if (error) 760ee98c4a5SJohn Baldwin break; 7614124f62eSJohn Baldwin if (raid_act->buf != NULL) 7624124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, raid_act->buf, 7634124f62eSJohn Baldwin raid_act->len); 764ee98c4a5SJohn Baldwin break; 765ee98c4a5SJohn Baldwin default: 766ee98c4a5SJohn Baldwin error = ENOIOCTL; 767ee98c4a5SJohn Baldwin break; 768ee98c4a5SJohn Baldwin } 769ee98c4a5SJohn Baldwin 7704124f62eSJohn Baldwin mpt_free_buffer(&mpt_page); 771ee98c4a5SJohn Baldwin 772ee98c4a5SJohn Baldwin if (error) 773ee98c4a5SJohn Baldwin return (error); 774ee98c4a5SJohn Baldwin 775ee98c4a5SJohn Baldwin #ifdef __amd64__ 776ee98c4a5SJohn Baldwin /* Convert native structs to 32-bit ones. */ 777ee98c4a5SJohn Baldwin switch (cmd) { 778ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 779ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 780ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 781ee98c4a5SJohn Baldwin page_req32->header = page_req->header; 782ee98c4a5SJohn Baldwin page_req32->page_address = page_req->page_address; 783ee98c4a5SJohn Baldwin page_req32->buf = PTROUT(page_req->buf); 784ee98c4a5SJohn Baldwin page_req32->len = page_req->len; 785ee98c4a5SJohn Baldwin page_req32->ioc_status = page_req->ioc_status; 786ee98c4a5SJohn Baldwin break; 787ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 788ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 789ee98c4a5SJohn Baldwin ext_page_req32->header = ext_page_req->header; 790ee98c4a5SJohn Baldwin ext_page_req32->page_address = ext_page_req->page_address; 791ee98c4a5SJohn Baldwin ext_page_req32->buf = PTROUT(ext_page_req->buf); 792ee98c4a5SJohn Baldwin ext_page_req32->len = ext_page_req->len; 793ee98c4a5SJohn Baldwin ext_page_req32->ioc_status = ext_page_req->ioc_status; 794ee98c4a5SJohn Baldwin break; 795ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 796ee98c4a5SJohn Baldwin raid_act32->action = raid_act->action; 797ee98c4a5SJohn Baldwin raid_act32->volume_bus = raid_act->volume_bus; 798ee98c4a5SJohn Baldwin raid_act32->volume_id = raid_act->volume_id; 799ee98c4a5SJohn Baldwin raid_act32->phys_disk_num = raid_act->phys_disk_num; 800ee98c4a5SJohn Baldwin raid_act32->action_data_word = raid_act->action_data_word; 801ee98c4a5SJohn Baldwin raid_act32->buf = PTROUT(raid_act->buf); 802ee98c4a5SJohn Baldwin raid_act32->len = raid_act->len; 803ee98c4a5SJohn Baldwin raid_act32->volume_status = raid_act->volume_status; 804ee98c4a5SJohn Baldwin bcopy(raid_act->action_data, raid_act32->action_data, 805ee98c4a5SJohn Baldwin sizeof(raid_act->action_data)); 806ee98c4a5SJohn Baldwin raid_act32->action_status = raid_act->action_status; 807ee98c4a5SJohn Baldwin raid_act32->ioc_status = raid_act->ioc_status; 808ee98c4a5SJohn Baldwin raid_act32->write = raid_act->write; 809ee98c4a5SJohn Baldwin break; 810ee98c4a5SJohn Baldwin } 811ee98c4a5SJohn Baldwin #endif 812ee98c4a5SJohn Baldwin 813ee98c4a5SJohn Baldwin return (0); 814ee98c4a5SJohn Baldwin } 815