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> 39ee98c4a5SJohn Baldwin #include <sys/conf.h> 40ee98c4a5SJohn Baldwin #include <sys/errno.h> 41ee98c4a5SJohn Baldwin #include <sys/ioccom.h> 42ee98c4a5SJohn Baldwin #include <sys/mpt_ioctl.h> 43ee98c4a5SJohn Baldwin 44ee98c4a5SJohn Baldwin #include <dev/mpt/mpt.h> 45ee98c4a5SJohn Baldwin 46ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result { 47ee98c4a5SJohn Baldwin uint32_t volume_status; 48ee98c4a5SJohn Baldwin uint32_t action_data[4]; 49ee98c4a5SJohn Baldwin uint16_t action_status; 50ee98c4a5SJohn Baldwin }; 51ee98c4a5SJohn Baldwin 524124f62eSJohn Baldwin struct mpt_page_memory { 534124f62eSJohn Baldwin bus_dma_tag_t tag; 544124f62eSJohn Baldwin bus_dmamap_t map; 554124f62eSJohn Baldwin bus_addr_t paddr; 564124f62eSJohn Baldwin void *vaddr; 574124f62eSJohn Baldwin }; 584124f62eSJohn Baldwin 59ee98c4a5SJohn Baldwin static mpt_probe_handler_t mpt_user_probe; 60ee98c4a5SJohn Baldwin static mpt_attach_handler_t mpt_user_attach; 61ee98c4a5SJohn Baldwin static mpt_enable_handler_t mpt_user_enable; 62ee98c4a5SJohn Baldwin static mpt_ready_handler_t mpt_user_ready; 63ee98c4a5SJohn Baldwin static mpt_event_handler_t mpt_user_event; 64ee98c4a5SJohn Baldwin static mpt_reset_handler_t mpt_user_reset; 65ee98c4a5SJohn Baldwin static mpt_detach_handler_t mpt_user_detach; 66ee98c4a5SJohn Baldwin 67ee98c4a5SJohn Baldwin static struct mpt_personality mpt_user_personality = { 68ee98c4a5SJohn Baldwin .name = "mpt_user", 69ee98c4a5SJohn Baldwin .probe = mpt_user_probe, 70ee98c4a5SJohn Baldwin .attach = mpt_user_attach, 71ee98c4a5SJohn Baldwin .enable = mpt_user_enable, 72ee98c4a5SJohn Baldwin .ready = mpt_user_ready, 73ee98c4a5SJohn Baldwin .event = mpt_user_event, 74ee98c4a5SJohn Baldwin .reset = mpt_user_reset, 75ee98c4a5SJohn Baldwin .detach = mpt_user_detach, 76ee98c4a5SJohn Baldwin }; 77ee98c4a5SJohn Baldwin 78ee98c4a5SJohn Baldwin DECLARE_MPT_PERSONALITY(mpt_user, SI_ORDER_SECOND); 79ee98c4a5SJohn Baldwin 80ee98c4a5SJohn Baldwin static mpt_reply_handler_t mpt_user_reply_handler; 81ee98c4a5SJohn Baldwin 82ee98c4a5SJohn Baldwin static d_open_t mpt_open; 83ee98c4a5SJohn Baldwin static d_close_t mpt_close; 84ee98c4a5SJohn Baldwin static d_ioctl_t mpt_ioctl; 85ee98c4a5SJohn Baldwin 86ee98c4a5SJohn Baldwin static struct cdevsw mpt_cdevsw = { 87ee98c4a5SJohn Baldwin .d_version = D_VERSION, 88ee98c4a5SJohn Baldwin .d_flags = 0, 89ee98c4a5SJohn Baldwin .d_open = mpt_open, 90ee98c4a5SJohn Baldwin .d_close = mpt_close, 91ee98c4a5SJohn Baldwin .d_ioctl = mpt_ioctl, 92ee98c4a5SJohn Baldwin .d_name = "mpt", 93ee98c4a5SJohn Baldwin }; 94ee98c4a5SJohn Baldwin 95ee98c4a5SJohn Baldwin static MALLOC_DEFINE(M_MPTUSER, "mpt_user", "Buffers for mpt(4) ioctls"); 96ee98c4a5SJohn Baldwin 97ee98c4a5SJohn Baldwin static uint32_t user_handler_id = MPT_HANDLER_ID_NONE; 98ee98c4a5SJohn Baldwin 9987e255acSMarius Strobl static int 100ee98c4a5SJohn Baldwin mpt_user_probe(struct mpt_softc *mpt) 101ee98c4a5SJohn Baldwin { 102ee98c4a5SJohn Baldwin 103ee98c4a5SJohn Baldwin /* Attach to every controller. */ 104ee98c4a5SJohn Baldwin return (0); 105ee98c4a5SJohn Baldwin } 106ee98c4a5SJohn Baldwin 10787e255acSMarius Strobl static int 108ee98c4a5SJohn Baldwin mpt_user_attach(struct mpt_softc *mpt) 109ee98c4a5SJohn Baldwin { 110ee98c4a5SJohn Baldwin mpt_handler_t handler; 111ee98c4a5SJohn Baldwin int error, unit; 112ee98c4a5SJohn Baldwin 113ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 114ee98c4a5SJohn Baldwin handler.reply_handler = mpt_user_reply_handler; 115ee98c4a5SJohn Baldwin error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 116ee98c4a5SJohn Baldwin &user_handler_id); 117ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 118ee98c4a5SJohn Baldwin if (error != 0) { 119ee98c4a5SJohn Baldwin mpt_prt(mpt, "Unable to register user handler!\n"); 120ee98c4a5SJohn Baldwin return (error); 121ee98c4a5SJohn Baldwin } 122ee98c4a5SJohn Baldwin unit = device_get_unit(mpt->dev); 123ee98c4a5SJohn Baldwin mpt->cdev = make_dev(&mpt_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640, 124ee98c4a5SJohn Baldwin "mpt%d", unit); 125ee98c4a5SJohn Baldwin if (mpt->cdev == NULL) { 126ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 127ee98c4a5SJohn Baldwin mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 128ee98c4a5SJohn Baldwin user_handler_id); 129ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 130ee98c4a5SJohn Baldwin return (ENOMEM); 131ee98c4a5SJohn Baldwin } 132ee98c4a5SJohn Baldwin mpt->cdev->si_drv1 = mpt; 133ee98c4a5SJohn Baldwin return (0); 134ee98c4a5SJohn Baldwin } 135ee98c4a5SJohn Baldwin 13687e255acSMarius Strobl static int 137ee98c4a5SJohn Baldwin mpt_user_enable(struct mpt_softc *mpt) 138ee98c4a5SJohn Baldwin { 139ee98c4a5SJohn Baldwin 140ee98c4a5SJohn Baldwin return (0); 141ee98c4a5SJohn Baldwin } 142ee98c4a5SJohn Baldwin 14387e255acSMarius Strobl static void 144ee98c4a5SJohn Baldwin mpt_user_ready(struct mpt_softc *mpt) 145ee98c4a5SJohn Baldwin { 14687e255acSMarius Strobl 147ee98c4a5SJohn Baldwin } 148ee98c4a5SJohn Baldwin 14987e255acSMarius Strobl static int 150ee98c4a5SJohn Baldwin mpt_user_event(struct mpt_softc *mpt, request_t *req, 151ee98c4a5SJohn Baldwin MSG_EVENT_NOTIFY_REPLY *msg) 152ee98c4a5SJohn Baldwin { 153ee98c4a5SJohn Baldwin 154ee98c4a5SJohn Baldwin /* Someday we may want to let a user daemon listen for events? */ 155ee98c4a5SJohn Baldwin return (0); 156ee98c4a5SJohn Baldwin } 157ee98c4a5SJohn Baldwin 15887e255acSMarius Strobl static void 159ee98c4a5SJohn Baldwin mpt_user_reset(struct mpt_softc *mpt, int type) 160ee98c4a5SJohn Baldwin { 16187e255acSMarius Strobl 162ee98c4a5SJohn Baldwin } 163ee98c4a5SJohn Baldwin 16487e255acSMarius Strobl static void 165ee98c4a5SJohn Baldwin mpt_user_detach(struct mpt_softc *mpt) 166ee98c4a5SJohn Baldwin { 167ee98c4a5SJohn Baldwin mpt_handler_t handler; 168ee98c4a5SJohn Baldwin 169ee98c4a5SJohn Baldwin /* XXX: do a purge of pending requests? */ 170ee98c4a5SJohn Baldwin destroy_dev(mpt->cdev); 171ee98c4a5SJohn Baldwin 172ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 173ee98c4a5SJohn Baldwin handler.reply_handler = mpt_user_reply_handler; 174ee98c4a5SJohn Baldwin mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 175ee98c4a5SJohn Baldwin user_handler_id); 176ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 177ee98c4a5SJohn Baldwin } 178ee98c4a5SJohn Baldwin 179ee98c4a5SJohn Baldwin static int 18000b4e54aSWarner Losh mpt_open(struct cdev *dev, int flags, int fmt, struct thread *td) 181ee98c4a5SJohn Baldwin { 182ee98c4a5SJohn Baldwin 183ee98c4a5SJohn Baldwin return (0); 184ee98c4a5SJohn Baldwin } 185ee98c4a5SJohn Baldwin 186ee98c4a5SJohn Baldwin static int 18700b4e54aSWarner Losh mpt_close(struct cdev *dev, int flags, int fmt, struct thread *td) 188ee98c4a5SJohn Baldwin { 189ee98c4a5SJohn Baldwin 190ee98c4a5SJohn Baldwin return (0); 191ee98c4a5SJohn Baldwin } 192ee98c4a5SJohn Baldwin 193ee98c4a5SJohn Baldwin static int 1944124f62eSJohn Baldwin mpt_alloc_buffer(struct mpt_softc *mpt, struct mpt_page_memory *page_mem, 1954124f62eSJohn Baldwin size_t len) 1964124f62eSJohn Baldwin { 1974124f62eSJohn Baldwin struct mpt_map_info mi; 1984124f62eSJohn Baldwin int error; 1994124f62eSJohn Baldwin 2004124f62eSJohn Baldwin page_mem->vaddr = NULL; 2014124f62eSJohn Baldwin 2024124f62eSJohn Baldwin /* Limit requests to 16M. */ 2034124f62eSJohn Baldwin if (len > 16 * 1024 * 1024) 2044124f62eSJohn Baldwin return (ENOSPC); 2054124f62eSJohn Baldwin error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 0, 2064124f62eSJohn Baldwin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 2074124f62eSJohn Baldwin len, 1, len, 0, &page_mem->tag); 2084124f62eSJohn Baldwin if (error) 2094124f62eSJohn Baldwin return (error); 2104124f62eSJohn Baldwin error = bus_dmamem_alloc(page_mem->tag, &page_mem->vaddr, 2116c5276c8SMarius Strobl BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &page_mem->map); 2124124f62eSJohn Baldwin if (error) { 2134124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2144124f62eSJohn Baldwin return (error); 2154124f62eSJohn Baldwin } 2164124f62eSJohn Baldwin mi.mpt = mpt; 2174124f62eSJohn Baldwin error = bus_dmamap_load(page_mem->tag, page_mem->map, page_mem->vaddr, 2184124f62eSJohn Baldwin len, mpt_map_rquest, &mi, BUS_DMA_NOWAIT); 2194124f62eSJohn Baldwin if (error == 0) 2204124f62eSJohn Baldwin error = mi.error; 2214124f62eSJohn Baldwin if (error) { 2224124f62eSJohn Baldwin bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map); 2234124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2244124f62eSJohn Baldwin page_mem->vaddr = NULL; 2254124f62eSJohn Baldwin return (error); 2264124f62eSJohn Baldwin } 2274124f62eSJohn Baldwin page_mem->paddr = mi.phys; 2284124f62eSJohn Baldwin return (0); 2294124f62eSJohn Baldwin } 2304124f62eSJohn Baldwin 2314124f62eSJohn Baldwin static void 2324124f62eSJohn Baldwin mpt_free_buffer(struct mpt_page_memory *page_mem) 2334124f62eSJohn Baldwin { 2344124f62eSJohn Baldwin 2354124f62eSJohn Baldwin if (page_mem->vaddr == NULL) 2364124f62eSJohn Baldwin return; 2374124f62eSJohn Baldwin bus_dmamap_unload(page_mem->tag, page_mem->map); 2384124f62eSJohn Baldwin bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map); 2394124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2404124f62eSJohn Baldwin page_mem->vaddr = NULL; 2414124f62eSJohn Baldwin } 2424124f62eSJohn Baldwin 2434124f62eSJohn Baldwin static int 244ee98c4a5SJohn Baldwin mpt_user_read_cfg_header(struct mpt_softc *mpt, 245ee98c4a5SJohn Baldwin struct mpt_cfg_page_req *page_req) 246ee98c4a5SJohn Baldwin { 247ee98c4a5SJohn Baldwin request_t *req; 248ee98c4a5SJohn Baldwin cfgparms_t params; 249ee98c4a5SJohn Baldwin MSG_CONFIG *cfgp; 250ee98c4a5SJohn Baldwin int error; 251ee98c4a5SJohn Baldwin 252ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 253ee98c4a5SJohn Baldwin if (req == NULL) { 254ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_header: Get request failed!\n"); 255ee98c4a5SJohn Baldwin return (ENOMEM); 256ee98c4a5SJohn Baldwin } 257ee98c4a5SJohn Baldwin 258ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_HEADER; 259ee98c4a5SJohn Baldwin params.PageVersion = 0; 260ee98c4a5SJohn Baldwin params.PageLength = 0; 261ee98c4a5SJohn Baldwin params.PageNumber = page_req->header.PageNumber; 262ee98c4a5SJohn Baldwin params.PageType = page_req->header.PageType; 2637ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 264ee98c4a5SJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0, 265ee98c4a5SJohn Baldwin TRUE, 5000); 266ee98c4a5SJohn Baldwin if (error != 0) { 267ee98c4a5SJohn Baldwin /* 268ee98c4a5SJohn Baldwin * Leave the request. Without resetting the chip, it's 269ee98c4a5SJohn Baldwin * still owned by it and we'll just get into trouble 270ee98c4a5SJohn Baldwin * freeing it now. Mark it as abandoned so that if it 271ee98c4a5SJohn Baldwin * shows up later it can be freed. 272ee98c4a5SJohn Baldwin */ 273ee98c4a5SJohn Baldwin mpt_prt(mpt, "read_cfg_header timed out\n"); 274ee98c4a5SJohn Baldwin return (ETIMEDOUT); 275ee98c4a5SJohn Baldwin } 276ee98c4a5SJohn Baldwin 2777ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 278ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) { 279ee98c4a5SJohn Baldwin cfgp = req->req_vbuf; 280ee98c4a5SJohn Baldwin bcopy(&cfgp->Header, &page_req->header, 281ee98c4a5SJohn Baldwin sizeof(page_req->header)); 282ee98c4a5SJohn Baldwin } 283ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 284ee98c4a5SJohn Baldwin return (0); 285ee98c4a5SJohn Baldwin } 286ee98c4a5SJohn Baldwin 287ee98c4a5SJohn Baldwin static int 288ee98c4a5SJohn Baldwin mpt_user_read_cfg_page(struct mpt_softc *mpt, struct mpt_cfg_page_req *page_req, 2894124f62eSJohn Baldwin struct mpt_page_memory *mpt_page) 290ee98c4a5SJohn Baldwin { 291ee98c4a5SJohn Baldwin CONFIG_PAGE_HEADER *hdr; 292ee98c4a5SJohn Baldwin request_t *req; 293ee98c4a5SJohn Baldwin cfgparms_t params; 294ee98c4a5SJohn Baldwin int error; 295ee98c4a5SJohn Baldwin 296ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 297ee98c4a5SJohn Baldwin if (req == NULL) { 298ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_page: Get request failed!\n"); 299ee98c4a5SJohn Baldwin return (ENOMEM); 300ee98c4a5SJohn Baldwin } 301ee98c4a5SJohn Baldwin 3024124f62eSJohn Baldwin hdr = mpt_page->vaddr; 303ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 304ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 305ee98c4a5SJohn Baldwin params.PageLength = hdr->PageLength; 306ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 307ee98c4a5SJohn Baldwin params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK; 3087ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 3096c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, 3106c5276c8SMarius Strobl BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3114124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 3127ee37807SMarius Strobl le32toh(page_req->len), TRUE, 5000); 313ee98c4a5SJohn Baldwin if (error != 0) { 314ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_page timed out\n"); 315ee98c4a5SJohn Baldwin return (ETIMEDOUT); 316ee98c4a5SJohn Baldwin } 317ee98c4a5SJohn Baldwin 3187ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 3194124f62eSJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) 3204124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 3216c5276c8SMarius Strobl BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 322ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 323ee98c4a5SJohn Baldwin return (0); 324ee98c4a5SJohn Baldwin } 325ee98c4a5SJohn Baldwin 326ee98c4a5SJohn Baldwin static int 327ee98c4a5SJohn Baldwin mpt_user_read_extcfg_header(struct mpt_softc *mpt, 328ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req) 329ee98c4a5SJohn Baldwin { 330ee98c4a5SJohn Baldwin request_t *req; 331ee98c4a5SJohn Baldwin cfgparms_t params; 332ee98c4a5SJohn Baldwin MSG_CONFIG_REPLY *cfgp; 333ee98c4a5SJohn Baldwin int error; 334ee98c4a5SJohn Baldwin 335ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 336ee98c4a5SJohn Baldwin if (req == NULL) { 337ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_header: Get request failed!\n"); 338ee98c4a5SJohn Baldwin return (ENOMEM); 339ee98c4a5SJohn Baldwin } 340ee98c4a5SJohn Baldwin 341ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_HEADER; 342ee98c4a5SJohn Baldwin params.PageVersion = ext_page_req->header.PageVersion; 343ee98c4a5SJohn Baldwin params.PageLength = 0; 344ee98c4a5SJohn Baldwin params.PageNumber = ext_page_req->header.PageNumber; 345ee98c4a5SJohn Baldwin params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 3467ee37807SMarius Strobl params.PageAddress = le32toh(ext_page_req->page_address); 347ee98c4a5SJohn Baldwin params.ExtPageType = ext_page_req->header.ExtPageType; 348ee98c4a5SJohn Baldwin params.ExtPageLength = 0; 349ee98c4a5SJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0, 350ee98c4a5SJohn Baldwin TRUE, 5000); 351ee98c4a5SJohn Baldwin if (error != 0) { 352ee98c4a5SJohn Baldwin /* 353ee98c4a5SJohn Baldwin * Leave the request. Without resetting the chip, it's 354ee98c4a5SJohn Baldwin * still owned by it and we'll just get into trouble 355ee98c4a5SJohn Baldwin * freeing it now. Mark it as abandoned so that if it 356ee98c4a5SJohn Baldwin * shows up later it can be freed. 357ee98c4a5SJohn Baldwin */ 358ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_header timed out\n"); 359ee98c4a5SJohn Baldwin return (ETIMEDOUT); 360ee98c4a5SJohn Baldwin } 361ee98c4a5SJohn Baldwin 3627ee37807SMarius Strobl ext_page_req->ioc_status = htole16(req->IOCStatus); 363ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) { 364ee98c4a5SJohn Baldwin cfgp = req->req_vbuf; 365ee98c4a5SJohn Baldwin ext_page_req->header.PageVersion = cfgp->Header.PageVersion; 366ee98c4a5SJohn Baldwin ext_page_req->header.PageNumber = cfgp->Header.PageNumber; 367ee98c4a5SJohn Baldwin ext_page_req->header.PageType = cfgp->Header.PageType; 368ee98c4a5SJohn Baldwin ext_page_req->header.ExtPageLength = cfgp->ExtPageLength; 369ee98c4a5SJohn Baldwin ext_page_req->header.ExtPageType = cfgp->ExtPageType; 370ee98c4a5SJohn Baldwin } 371ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 372ee98c4a5SJohn Baldwin return (0); 373ee98c4a5SJohn Baldwin } 374ee98c4a5SJohn Baldwin 375ee98c4a5SJohn Baldwin static int 376ee98c4a5SJohn Baldwin mpt_user_read_extcfg_page(struct mpt_softc *mpt, 3774124f62eSJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req, struct mpt_page_memory *mpt_page) 378ee98c4a5SJohn Baldwin { 379ee98c4a5SJohn Baldwin CONFIG_EXTENDED_PAGE_HEADER *hdr; 380ee98c4a5SJohn Baldwin request_t *req; 381ee98c4a5SJohn Baldwin cfgparms_t params; 382ee98c4a5SJohn Baldwin int error; 383ee98c4a5SJohn Baldwin 384ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 385ee98c4a5SJohn Baldwin if (req == NULL) { 386ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_page: Get request failed!\n"); 387ee98c4a5SJohn Baldwin return (ENOMEM); 388ee98c4a5SJohn Baldwin } 389ee98c4a5SJohn Baldwin 3904124f62eSJohn Baldwin hdr = mpt_page->vaddr; 391ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 392ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 393ee98c4a5SJohn Baldwin params.PageLength = 0; 394ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 395ee98c4a5SJohn Baldwin params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 3967ee37807SMarius Strobl params.PageAddress = le32toh(ext_page_req->page_address); 397ee98c4a5SJohn Baldwin params.ExtPageType = hdr->ExtPageType; 398ee98c4a5SJohn Baldwin params.ExtPageLength = hdr->ExtPageLength; 3996c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, 4006c5276c8SMarius Strobl BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 4014124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 4027ee37807SMarius Strobl le32toh(ext_page_req->len), TRUE, 5000); 403ee98c4a5SJohn Baldwin if (error != 0) { 404ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_page timed out\n"); 405ee98c4a5SJohn Baldwin return (ETIMEDOUT); 406ee98c4a5SJohn Baldwin } 407ee98c4a5SJohn Baldwin 4087ee37807SMarius Strobl ext_page_req->ioc_status = htole16(req->IOCStatus); 4094124f62eSJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) 4104124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 4116c5276c8SMarius Strobl BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 412ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 413ee98c4a5SJohn Baldwin return (0); 414ee98c4a5SJohn Baldwin } 415ee98c4a5SJohn Baldwin 416ee98c4a5SJohn Baldwin static int 417ee98c4a5SJohn Baldwin mpt_user_write_cfg_page(struct mpt_softc *mpt, 4184124f62eSJohn Baldwin struct mpt_cfg_page_req *page_req, struct mpt_page_memory *mpt_page) 419ee98c4a5SJohn Baldwin { 420ee98c4a5SJohn Baldwin CONFIG_PAGE_HEADER *hdr; 421ee98c4a5SJohn Baldwin request_t *req; 422ee98c4a5SJohn Baldwin cfgparms_t params; 423ee98c4a5SJohn Baldwin u_int hdr_attr; 424ee98c4a5SJohn Baldwin int error; 425ee98c4a5SJohn Baldwin 4264124f62eSJohn Baldwin hdr = mpt_page->vaddr; 427ee98c4a5SJohn Baldwin hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK; 428ee98c4a5SJohn Baldwin if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE && 429ee98c4a5SJohn Baldwin hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) { 430ee98c4a5SJohn Baldwin mpt_prt(mpt, "page type 0x%x not changeable\n", 431ee98c4a5SJohn Baldwin hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); 432ee98c4a5SJohn Baldwin return (EINVAL); 433ee98c4a5SJohn Baldwin } 434ee98c4a5SJohn Baldwin 435ee98c4a5SJohn Baldwin #if 0 436ee98c4a5SJohn Baldwin /* 437ee98c4a5SJohn Baldwin * We shouldn't mask off other bits here. 438ee98c4a5SJohn Baldwin */ 439ee98c4a5SJohn Baldwin hdr->PageType &= ~MPI_CONFIG_PAGETYPE_MASK; 440ee98c4a5SJohn Baldwin #endif 441ee98c4a5SJohn Baldwin 442ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 443ee98c4a5SJohn Baldwin if (req == NULL) 444ee98c4a5SJohn Baldwin return (ENOMEM); 445ee98c4a5SJohn Baldwin 4466c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_PREREAD | 4476c5276c8SMarius Strobl BUS_DMASYNC_PREWRITE); 448ee98c4a5SJohn Baldwin 449ee98c4a5SJohn Baldwin /* 450ee98c4a5SJohn Baldwin * There isn't any point in restoring stripped out attributes 451ee98c4a5SJohn Baldwin * if you then mask them going down to issue the request. 452ee98c4a5SJohn Baldwin */ 453ee98c4a5SJohn Baldwin 454ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; 455ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 456ee98c4a5SJohn Baldwin params.PageLength = hdr->PageLength; 457ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 4587ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 459ee98c4a5SJohn Baldwin #if 0 460ee98c4a5SJohn Baldwin /* Restore stripped out attributes */ 461ee98c4a5SJohn Baldwin hdr->PageType |= hdr_attr; 462ee98c4a5SJohn Baldwin params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK; 463ee98c4a5SJohn Baldwin #else 464ee98c4a5SJohn Baldwin params.PageType = hdr->PageType; 465ee98c4a5SJohn Baldwin #endif 4664124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 4677ee37807SMarius Strobl le32toh(page_req->len), TRUE, 5000); 468ee98c4a5SJohn Baldwin if (error != 0) { 469ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_write_cfg_page timed out\n"); 470ee98c4a5SJohn Baldwin return (ETIMEDOUT); 471ee98c4a5SJohn Baldwin } 472ee98c4a5SJohn Baldwin 4737ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 4746c5276c8SMarius Strobl bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_POSTREAD | 4756c5276c8SMarius Strobl BUS_DMASYNC_POSTWRITE); 476ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 477ee98c4a5SJohn Baldwin return (0); 478ee98c4a5SJohn Baldwin } 479ee98c4a5SJohn Baldwin 480ee98c4a5SJohn Baldwin static int 481ee98c4a5SJohn Baldwin mpt_user_reply_handler(struct mpt_softc *mpt, request_t *req, 482ee98c4a5SJohn Baldwin uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame) 483ee98c4a5SJohn Baldwin { 484ee98c4a5SJohn Baldwin MSG_RAID_ACTION_REPLY *reply; 485ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result *res; 486ee98c4a5SJohn Baldwin 487ee98c4a5SJohn Baldwin if (req == NULL) 488ee98c4a5SJohn Baldwin return (TRUE); 489ee98c4a5SJohn Baldwin 490ee98c4a5SJohn Baldwin if (reply_frame != NULL) { 491ee98c4a5SJohn Baldwin reply = (MSG_RAID_ACTION_REPLY *)reply_frame; 492ee98c4a5SJohn Baldwin req->IOCStatus = le16toh(reply->IOCStatus); 493ee98c4a5SJohn Baldwin res = (struct mpt_user_raid_action_result *) 494ee98c4a5SJohn Baldwin (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt)); 495ee98c4a5SJohn Baldwin res->action_status = reply->ActionStatus; 496ee98c4a5SJohn Baldwin res->volume_status = reply->VolumeStatus; 497ee98c4a5SJohn Baldwin bcopy(&reply->ActionData, res->action_data, 498ee98c4a5SJohn Baldwin sizeof(res->action_data)); 499ee98c4a5SJohn Baldwin } 500ee98c4a5SJohn Baldwin 501ee98c4a5SJohn Baldwin req->state &= ~REQ_STATE_QUEUED; 502ee98c4a5SJohn Baldwin req->state |= REQ_STATE_DONE; 503ee98c4a5SJohn Baldwin TAILQ_REMOVE(&mpt->request_pending_list, req, links); 504ee98c4a5SJohn Baldwin 505ee98c4a5SJohn Baldwin if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) { 506ee98c4a5SJohn Baldwin wakeup(req); 507ee98c4a5SJohn Baldwin } else if ((req->state & REQ_STATE_TIMEDOUT) != 0) { 508ee98c4a5SJohn Baldwin /* 509ee98c4a5SJohn Baldwin * Whew- we can free this request (late completion) 510ee98c4a5SJohn Baldwin */ 511ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 512ee98c4a5SJohn Baldwin } 513ee98c4a5SJohn Baldwin 514ee98c4a5SJohn Baldwin return (TRUE); 515ee98c4a5SJohn Baldwin } 516ee98c4a5SJohn Baldwin 517ee98c4a5SJohn Baldwin /* 518ee98c4a5SJohn Baldwin * We use the first part of the request buffer after the request frame 519ee98c4a5SJohn Baldwin * to hold the action data and action status from the RAID reply. The 520ee98c4a5SJohn Baldwin * rest of the request buffer is used to hold the buffer for the 521ee98c4a5SJohn Baldwin * action SGE. 522ee98c4a5SJohn Baldwin */ 523ee98c4a5SJohn Baldwin static int 524ee98c4a5SJohn Baldwin mpt_user_raid_action(struct mpt_softc *mpt, struct mpt_raid_action *raid_act, 5254124f62eSJohn Baldwin struct mpt_page_memory *mpt_page) 526ee98c4a5SJohn Baldwin { 527ee98c4a5SJohn Baldwin request_t *req; 528ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result *res; 529ee98c4a5SJohn Baldwin MSG_RAID_ACTION_REQUEST *rap; 530ee98c4a5SJohn Baldwin SGE_SIMPLE32 *se; 531ee98c4a5SJohn Baldwin int error; 532ee98c4a5SJohn Baldwin 533ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 534ee98c4a5SJohn Baldwin if (req == NULL) 535ee98c4a5SJohn Baldwin return (ENOMEM); 536ee98c4a5SJohn Baldwin rap = req->req_vbuf; 537ee98c4a5SJohn Baldwin memset(rap, 0, sizeof *rap); 538ee98c4a5SJohn Baldwin rap->Action = raid_act->action; 539ee98c4a5SJohn Baldwin rap->ActionDataWord = raid_act->action_data_word; 540ee98c4a5SJohn Baldwin rap->Function = MPI_FUNCTION_RAID_ACTION; 541ee98c4a5SJohn Baldwin rap->VolumeID = raid_act->volume_id; 542ee98c4a5SJohn Baldwin rap->VolumeBus = raid_act->volume_bus; 543ee98c4a5SJohn Baldwin rap->PhysDiskNum = raid_act->phys_disk_num; 544ee98c4a5SJohn Baldwin se = (SGE_SIMPLE32 *)&rap->ActionDataSGE; 5454124f62eSJohn Baldwin if (mpt_page->vaddr != NULL && raid_act->len != 0) { 5464124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 5476c5276c8SMarius Strobl BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 5487ee37807SMarius Strobl se->Address = htole32(mpt_page->paddr); 5497ee37807SMarius Strobl MPI_pSGE_SET_LENGTH(se, le32toh(raid_act->len)); 550ee98c4a5SJohn Baldwin MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 551ee98c4a5SJohn Baldwin MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 552ee98c4a5SJohn Baldwin MPI_SGE_FLAGS_END_OF_LIST | 553cb5a9183SXin LI (raid_act->write ? MPI_SGE_FLAGS_HOST_TO_IOC : 554cb5a9183SXin LI MPI_SGE_FLAGS_IOC_TO_HOST))); 555ee98c4a5SJohn Baldwin } 5567ee37807SMarius Strobl se->FlagsLength = htole32(se->FlagsLength); 557ee98c4a5SJohn Baldwin rap->MsgContext = htole32(req->index | user_handler_id); 558ee98c4a5SJohn Baldwin 559ee98c4a5SJohn Baldwin mpt_check_doorbell(mpt); 560ee98c4a5SJohn Baldwin mpt_send_cmd(mpt, req); 561ee98c4a5SJohn Baldwin 562ee98c4a5SJohn Baldwin error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, TRUE, 563ee98c4a5SJohn Baldwin 2000); 564ee98c4a5SJohn Baldwin if (error != 0) { 565ee98c4a5SJohn Baldwin /* 566ee98c4a5SJohn Baldwin * Leave request so it can be cleaned up later. 567ee98c4a5SJohn Baldwin */ 568ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_raid_action timed out\n"); 569ee98c4a5SJohn Baldwin return (error); 570ee98c4a5SJohn Baldwin } 571ee98c4a5SJohn Baldwin 5727ee37807SMarius Strobl raid_act->ioc_status = htole16(req->IOCStatus); 573ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 574ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 575ee98c4a5SJohn Baldwin return (0); 576ee98c4a5SJohn Baldwin } 577ee98c4a5SJohn Baldwin 578ee98c4a5SJohn Baldwin res = (struct mpt_user_raid_action_result *) 579ee98c4a5SJohn Baldwin (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt)); 580ee98c4a5SJohn Baldwin raid_act->volume_status = res->volume_status; 581ee98c4a5SJohn Baldwin raid_act->action_status = res->action_status; 582ee98c4a5SJohn Baldwin bcopy(res->action_data, raid_act->action_data, 583ee98c4a5SJohn Baldwin sizeof(res->action_data)); 5844124f62eSJohn Baldwin if (mpt_page->vaddr != NULL) 5854124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 5866c5276c8SMarius Strobl BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 587ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 588ee98c4a5SJohn Baldwin return (0); 589ee98c4a5SJohn Baldwin } 590ee98c4a5SJohn Baldwin 591ee98c4a5SJohn Baldwin #ifdef __amd64__ 592ee98c4a5SJohn Baldwin #define PTRIN(p) ((void *)(uintptr_t)(p)) 593ee98c4a5SJohn Baldwin #define PTROUT(v) ((u_int32_t)(uintptr_t)(v)) 594ee98c4a5SJohn Baldwin #endif 595ee98c4a5SJohn Baldwin 596ee98c4a5SJohn Baldwin static int 59700b4e54aSWarner Losh mpt_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 598ee98c4a5SJohn Baldwin { 599ee98c4a5SJohn Baldwin struct mpt_softc *mpt; 600ee98c4a5SJohn Baldwin struct mpt_cfg_page_req *page_req; 601ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req; 602ee98c4a5SJohn Baldwin struct mpt_raid_action *raid_act; 6034124f62eSJohn Baldwin struct mpt_page_memory mpt_page; 604ee98c4a5SJohn Baldwin #ifdef __amd64__ 605ee98c4a5SJohn Baldwin struct mpt_cfg_page_req32 *page_req32; 606ee98c4a5SJohn Baldwin struct mpt_cfg_page_req page_req_swab; 607ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req32 *ext_page_req32; 608ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req ext_page_req_swab; 609ee98c4a5SJohn Baldwin struct mpt_raid_action32 *raid_act32; 610ee98c4a5SJohn Baldwin struct mpt_raid_action raid_act_swab; 611ee98c4a5SJohn Baldwin #endif 612ee98c4a5SJohn Baldwin int error; 613ee98c4a5SJohn Baldwin 614ee98c4a5SJohn Baldwin mpt = dev->si_drv1; 615ee98c4a5SJohn Baldwin page_req = (void *)arg; 616ee98c4a5SJohn Baldwin ext_page_req = (void *)arg; 617ee98c4a5SJohn Baldwin raid_act = (void *)arg; 6184124f62eSJohn Baldwin mpt_page.vaddr = NULL; 619ee98c4a5SJohn Baldwin 620ee98c4a5SJohn Baldwin #ifdef __amd64__ 621ee98c4a5SJohn Baldwin /* Convert 32-bit structs to native ones. */ 622ee98c4a5SJohn Baldwin page_req32 = (void *)arg; 623ee98c4a5SJohn Baldwin ext_page_req32 = (void *)arg; 624ee98c4a5SJohn Baldwin raid_act32 = (void *)arg; 625ee98c4a5SJohn Baldwin switch (cmd) { 626ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 627ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 628ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 629ee98c4a5SJohn Baldwin page_req = &page_req_swab; 630ee98c4a5SJohn Baldwin page_req->header = page_req32->header; 631ee98c4a5SJohn Baldwin page_req->page_address = page_req32->page_address; 632ee98c4a5SJohn Baldwin page_req->buf = PTRIN(page_req32->buf); 633ee98c4a5SJohn Baldwin page_req->len = page_req32->len; 634ee98c4a5SJohn Baldwin page_req->ioc_status = page_req32->ioc_status; 635ee98c4a5SJohn Baldwin break; 636ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 637ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 638ee98c4a5SJohn Baldwin ext_page_req = &ext_page_req_swab; 639ee98c4a5SJohn Baldwin ext_page_req->header = ext_page_req32->header; 640ee98c4a5SJohn Baldwin ext_page_req->page_address = ext_page_req32->page_address; 641ee98c4a5SJohn Baldwin ext_page_req->buf = PTRIN(ext_page_req32->buf); 642ee98c4a5SJohn Baldwin ext_page_req->len = ext_page_req32->len; 643ee98c4a5SJohn Baldwin ext_page_req->ioc_status = ext_page_req32->ioc_status; 644ee98c4a5SJohn Baldwin break; 645ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 646ee98c4a5SJohn Baldwin raid_act = &raid_act_swab; 647ee98c4a5SJohn Baldwin raid_act->action = raid_act32->action; 648ee98c4a5SJohn Baldwin raid_act->volume_bus = raid_act32->volume_bus; 649ee98c4a5SJohn Baldwin raid_act->volume_id = raid_act32->volume_id; 650ee98c4a5SJohn Baldwin raid_act->phys_disk_num = raid_act32->phys_disk_num; 651ee98c4a5SJohn Baldwin raid_act->action_data_word = raid_act32->action_data_word; 652ee98c4a5SJohn Baldwin raid_act->buf = PTRIN(raid_act32->buf); 653ee98c4a5SJohn Baldwin raid_act->len = raid_act32->len; 654ee98c4a5SJohn Baldwin raid_act->volume_status = raid_act32->volume_status; 655ee98c4a5SJohn Baldwin bcopy(raid_act32->action_data, raid_act->action_data, 656ee98c4a5SJohn Baldwin sizeof(raid_act->action_data)); 657ee98c4a5SJohn Baldwin raid_act->action_status = raid_act32->action_status; 658ee98c4a5SJohn Baldwin raid_act->ioc_status = raid_act32->ioc_status; 659ee98c4a5SJohn Baldwin raid_act->write = raid_act32->write; 660ee98c4a5SJohn Baldwin break; 661ee98c4a5SJohn Baldwin } 662ee98c4a5SJohn Baldwin #endif 663ee98c4a5SJohn Baldwin 664ee98c4a5SJohn Baldwin switch (cmd) { 665ee98c4a5SJohn Baldwin #ifdef __amd64__ 666ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 667ee98c4a5SJohn Baldwin #endif 668ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER: 669ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 670ee98c4a5SJohn Baldwin error = mpt_user_read_cfg_header(mpt, page_req); 671ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 672ee98c4a5SJohn Baldwin break; 673ee98c4a5SJohn Baldwin #ifdef __amd64__ 674ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 675ee98c4a5SJohn Baldwin #endif 676ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE: 6774124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len); 6784124f62eSJohn Baldwin if (error) 679ee98c4a5SJohn Baldwin break; 6804124f62eSJohn Baldwin error = copyin(page_req->buf, mpt_page.vaddr, 681ee98c4a5SJohn Baldwin sizeof(CONFIG_PAGE_HEADER)); 682ee98c4a5SJohn Baldwin if (error) 683ee98c4a5SJohn Baldwin break; 684ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 6854124f62eSJohn Baldwin error = mpt_user_read_cfg_page(mpt, page_req, &mpt_page); 686ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 687ee98c4a5SJohn Baldwin if (error) 688ee98c4a5SJohn Baldwin break; 6894124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, page_req->buf, page_req->len); 690ee98c4a5SJohn Baldwin break; 691ee98c4a5SJohn Baldwin #ifdef __amd64__ 692ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 693ee98c4a5SJohn Baldwin #endif 694ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER: 695ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 696ee98c4a5SJohn Baldwin error = mpt_user_read_extcfg_header(mpt, ext_page_req); 697ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 698ee98c4a5SJohn Baldwin break; 699ee98c4a5SJohn Baldwin #ifdef __amd64__ 700ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 701ee98c4a5SJohn Baldwin #endif 702ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE: 7034124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, ext_page_req->len); 7044124f62eSJohn Baldwin if (error) 705ee98c4a5SJohn Baldwin break; 7064124f62eSJohn Baldwin error = copyin(ext_page_req->buf, mpt_page.vaddr, 707ee98c4a5SJohn Baldwin sizeof(CONFIG_EXTENDED_PAGE_HEADER)); 708ee98c4a5SJohn Baldwin if (error) 709ee98c4a5SJohn Baldwin break; 710ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7114124f62eSJohn Baldwin error = mpt_user_read_extcfg_page(mpt, ext_page_req, &mpt_page); 712ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 713ee98c4a5SJohn Baldwin if (error) 714ee98c4a5SJohn Baldwin break; 7154124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, ext_page_req->buf, 7164124f62eSJohn Baldwin ext_page_req->len); 717ee98c4a5SJohn Baldwin break; 718ee98c4a5SJohn Baldwin #ifdef __amd64__ 719ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 720ee98c4a5SJohn Baldwin #endif 721ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE: 7224124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len); 7234124f62eSJohn Baldwin if (error) 724ee98c4a5SJohn Baldwin break; 7254124f62eSJohn Baldwin error = copyin(page_req->buf, mpt_page.vaddr, page_req->len); 726ee98c4a5SJohn Baldwin if (error) 727ee98c4a5SJohn Baldwin break; 728ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7294124f62eSJohn Baldwin error = mpt_user_write_cfg_page(mpt, page_req, &mpt_page); 730ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 731ee98c4a5SJohn Baldwin break; 732ee98c4a5SJohn Baldwin #ifdef __amd64__ 733ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 734ee98c4a5SJohn Baldwin #endif 735ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION: 736ee98c4a5SJohn Baldwin if (raid_act->buf != NULL) { 7374124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, raid_act->len); 7384124f62eSJohn Baldwin if (error) 739ee98c4a5SJohn Baldwin break; 7404124f62eSJohn Baldwin error = copyin(raid_act->buf, mpt_page.vaddr, 7414124f62eSJohn Baldwin raid_act->len); 742ee98c4a5SJohn Baldwin if (error) 743ee98c4a5SJohn Baldwin break; 744ee98c4a5SJohn Baldwin } 745ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7464124f62eSJohn Baldwin error = mpt_user_raid_action(mpt, raid_act, &mpt_page); 747ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 748ee98c4a5SJohn Baldwin if (error) 749ee98c4a5SJohn Baldwin break; 7504124f62eSJohn Baldwin if (raid_act->buf != NULL) 7514124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, raid_act->buf, 7524124f62eSJohn Baldwin raid_act->len); 753ee98c4a5SJohn Baldwin break; 754ee98c4a5SJohn Baldwin default: 755ee98c4a5SJohn Baldwin error = ENOIOCTL; 756ee98c4a5SJohn Baldwin break; 757ee98c4a5SJohn Baldwin } 758ee98c4a5SJohn Baldwin 7594124f62eSJohn Baldwin mpt_free_buffer(&mpt_page); 760ee98c4a5SJohn Baldwin 761ee98c4a5SJohn Baldwin if (error) 762ee98c4a5SJohn Baldwin return (error); 763ee98c4a5SJohn Baldwin 764ee98c4a5SJohn Baldwin #ifdef __amd64__ 765ee98c4a5SJohn Baldwin /* Convert native structs to 32-bit ones. */ 766ee98c4a5SJohn Baldwin switch (cmd) { 767ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 768ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 769ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 770ee98c4a5SJohn Baldwin page_req32->header = page_req->header; 771ee98c4a5SJohn Baldwin page_req32->page_address = page_req->page_address; 772ee98c4a5SJohn Baldwin page_req32->buf = PTROUT(page_req->buf); 773ee98c4a5SJohn Baldwin page_req32->len = page_req->len; 774ee98c4a5SJohn Baldwin page_req32->ioc_status = page_req->ioc_status; 775ee98c4a5SJohn Baldwin break; 776ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 777ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 778ee98c4a5SJohn Baldwin ext_page_req32->header = ext_page_req->header; 779ee98c4a5SJohn Baldwin ext_page_req32->page_address = ext_page_req->page_address; 780ee98c4a5SJohn Baldwin ext_page_req32->buf = PTROUT(ext_page_req->buf); 781ee98c4a5SJohn Baldwin ext_page_req32->len = ext_page_req->len; 782ee98c4a5SJohn Baldwin ext_page_req32->ioc_status = ext_page_req->ioc_status; 783ee98c4a5SJohn Baldwin break; 784ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 785ee98c4a5SJohn Baldwin raid_act32->action = raid_act->action; 786ee98c4a5SJohn Baldwin raid_act32->volume_bus = raid_act->volume_bus; 787ee98c4a5SJohn Baldwin raid_act32->volume_id = raid_act->volume_id; 788ee98c4a5SJohn Baldwin raid_act32->phys_disk_num = raid_act->phys_disk_num; 789ee98c4a5SJohn Baldwin raid_act32->action_data_word = raid_act->action_data_word; 790ee98c4a5SJohn Baldwin raid_act32->buf = PTROUT(raid_act->buf); 791ee98c4a5SJohn Baldwin raid_act32->len = raid_act->len; 792ee98c4a5SJohn Baldwin raid_act32->volume_status = raid_act->volume_status; 793ee98c4a5SJohn Baldwin bcopy(raid_act->action_data, raid_act32->action_data, 794ee98c4a5SJohn Baldwin sizeof(raid_act->action_data)); 795ee98c4a5SJohn Baldwin raid_act32->action_status = raid_act->action_status; 796ee98c4a5SJohn Baldwin raid_act32->ioc_status = raid_act->ioc_status; 797ee98c4a5SJohn Baldwin raid_act32->write = raid_act->write; 798ee98c4a5SJohn Baldwin break; 799ee98c4a5SJohn Baldwin } 800ee98c4a5SJohn Baldwin #endif 801ee98c4a5SJohn Baldwin 802ee98c4a5SJohn Baldwin return (0); 803ee98c4a5SJohn Baldwin } 804