1ee98c4a5SJohn Baldwin /*- 2ee98c4a5SJohn Baldwin * Copyright (c) 2008 Yahoo!, Inc. 3ee98c4a5SJohn Baldwin * All rights reserved. 4ee98c4a5SJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 5ee98c4a5SJohn Baldwin * 6ee98c4a5SJohn Baldwin * Redistribution and use in source and binary forms, with or without 7ee98c4a5SJohn Baldwin * modification, are permitted provided that the following conditions 8ee98c4a5SJohn Baldwin * are met: 9ee98c4a5SJohn Baldwin * 1. Redistributions of source code must retain the above copyright 10ee98c4a5SJohn Baldwin * notice, this list of conditions and the following disclaimer. 11ee98c4a5SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 12ee98c4a5SJohn Baldwin * notice, this list of conditions and the following disclaimer in the 13ee98c4a5SJohn Baldwin * documentation and/or other materials provided with the distribution. 14ee98c4a5SJohn Baldwin * 3. Neither the name of the author nor the names of any co-contributors 15ee98c4a5SJohn Baldwin * may be used to endorse or promote products derived from this software 16ee98c4a5SJohn Baldwin * without specific prior written permission. 17ee98c4a5SJohn Baldwin * 18ee98c4a5SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19ee98c4a5SJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20ee98c4a5SJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21ee98c4a5SJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22ee98c4a5SJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23ee98c4a5SJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24ee98c4a5SJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25ee98c4a5SJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26ee98c4a5SJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27ee98c4a5SJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28ee98c4a5SJohn Baldwin * SUCH DAMAGE. 29ee98c4a5SJohn Baldwin * 30ee98c4a5SJohn Baldwin * LSI MPT-Fusion Host Adapter FreeBSD userland interface 31ee98c4a5SJohn Baldwin */ 32ee98c4a5SJohn Baldwin 33ee98c4a5SJohn Baldwin #include <sys/cdefs.h> 34ee98c4a5SJohn Baldwin __FBSDID("$FreeBSD$"); 35ee98c4a5SJohn Baldwin 36ee98c4a5SJohn Baldwin #include <sys/param.h> 37ee98c4a5SJohn Baldwin #include <sys/conf.h> 38ee98c4a5SJohn Baldwin #include <sys/errno.h> 39ee98c4a5SJohn Baldwin #include <sys/ioccom.h> 40ee98c4a5SJohn Baldwin #include <sys/mpt_ioctl.h> 41ee98c4a5SJohn Baldwin 42ee98c4a5SJohn Baldwin #include <dev/mpt/mpt.h> 43ee98c4a5SJohn Baldwin 44ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result { 45ee98c4a5SJohn Baldwin uint32_t volume_status; 46ee98c4a5SJohn Baldwin uint32_t action_data[4]; 47ee98c4a5SJohn Baldwin uint16_t action_status; 48ee98c4a5SJohn Baldwin }; 49ee98c4a5SJohn Baldwin 504124f62eSJohn Baldwin struct mpt_page_memory { 514124f62eSJohn Baldwin bus_dma_tag_t tag; 524124f62eSJohn Baldwin bus_dmamap_t map; 534124f62eSJohn Baldwin bus_addr_t paddr; 544124f62eSJohn Baldwin void *vaddr; 554124f62eSJohn Baldwin }; 564124f62eSJohn Baldwin 57ee98c4a5SJohn Baldwin static mpt_probe_handler_t mpt_user_probe; 58ee98c4a5SJohn Baldwin static mpt_attach_handler_t mpt_user_attach; 59ee98c4a5SJohn Baldwin static mpt_enable_handler_t mpt_user_enable; 60ee98c4a5SJohn Baldwin static mpt_ready_handler_t mpt_user_ready; 61ee98c4a5SJohn Baldwin static mpt_event_handler_t mpt_user_event; 62ee98c4a5SJohn Baldwin static mpt_reset_handler_t mpt_user_reset; 63ee98c4a5SJohn Baldwin static mpt_detach_handler_t mpt_user_detach; 64ee98c4a5SJohn Baldwin 65ee98c4a5SJohn Baldwin static struct mpt_personality mpt_user_personality = { 66ee98c4a5SJohn Baldwin .name = "mpt_user", 67ee98c4a5SJohn Baldwin .probe = mpt_user_probe, 68ee98c4a5SJohn Baldwin .attach = mpt_user_attach, 69ee98c4a5SJohn Baldwin .enable = mpt_user_enable, 70ee98c4a5SJohn Baldwin .ready = mpt_user_ready, 71ee98c4a5SJohn Baldwin .event = mpt_user_event, 72ee98c4a5SJohn Baldwin .reset = mpt_user_reset, 73ee98c4a5SJohn Baldwin .detach = mpt_user_detach, 74ee98c4a5SJohn Baldwin }; 75ee98c4a5SJohn Baldwin 76ee98c4a5SJohn Baldwin DECLARE_MPT_PERSONALITY(mpt_user, SI_ORDER_SECOND); 77ee98c4a5SJohn Baldwin 78ee98c4a5SJohn Baldwin static mpt_reply_handler_t mpt_user_reply_handler; 79ee98c4a5SJohn Baldwin 80ee98c4a5SJohn Baldwin static d_open_t mpt_open; 81ee98c4a5SJohn Baldwin static d_close_t mpt_close; 82ee98c4a5SJohn Baldwin static d_ioctl_t mpt_ioctl; 83ee98c4a5SJohn Baldwin 84ee98c4a5SJohn Baldwin static struct cdevsw mpt_cdevsw = { 85ee98c4a5SJohn Baldwin .d_version = D_VERSION, 86ee98c4a5SJohn Baldwin .d_flags = 0, 87ee98c4a5SJohn Baldwin .d_open = mpt_open, 88ee98c4a5SJohn Baldwin .d_close = mpt_close, 89ee98c4a5SJohn Baldwin .d_ioctl = mpt_ioctl, 90ee98c4a5SJohn Baldwin .d_name = "mpt", 91ee98c4a5SJohn Baldwin }; 92ee98c4a5SJohn Baldwin 93ee98c4a5SJohn Baldwin static MALLOC_DEFINE(M_MPTUSER, "mpt_user", "Buffers for mpt(4) ioctls"); 94ee98c4a5SJohn Baldwin 95ee98c4a5SJohn Baldwin static uint32_t user_handler_id = MPT_HANDLER_ID_NONE; 96ee98c4a5SJohn Baldwin 97ee98c4a5SJohn Baldwin int 98ee98c4a5SJohn Baldwin mpt_user_probe(struct mpt_softc *mpt) 99ee98c4a5SJohn Baldwin { 100ee98c4a5SJohn Baldwin 101ee98c4a5SJohn Baldwin /* Attach to every controller. */ 102ee98c4a5SJohn Baldwin return (0); 103ee98c4a5SJohn Baldwin } 104ee98c4a5SJohn Baldwin 105ee98c4a5SJohn Baldwin int 106ee98c4a5SJohn Baldwin mpt_user_attach(struct mpt_softc *mpt) 107ee98c4a5SJohn Baldwin { 108ee98c4a5SJohn Baldwin mpt_handler_t handler; 109ee98c4a5SJohn Baldwin int error, unit; 110ee98c4a5SJohn Baldwin 111ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 112ee98c4a5SJohn Baldwin handler.reply_handler = mpt_user_reply_handler; 113ee98c4a5SJohn Baldwin error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 114ee98c4a5SJohn Baldwin &user_handler_id); 115ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 116ee98c4a5SJohn Baldwin if (error != 0) { 117ee98c4a5SJohn Baldwin mpt_prt(mpt, "Unable to register user handler!\n"); 118ee98c4a5SJohn Baldwin return (error); 119ee98c4a5SJohn Baldwin } 120ee98c4a5SJohn Baldwin unit = device_get_unit(mpt->dev); 121ee98c4a5SJohn Baldwin mpt->cdev = make_dev(&mpt_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640, 122ee98c4a5SJohn Baldwin "mpt%d", unit); 123ee98c4a5SJohn Baldwin if (mpt->cdev == NULL) { 124ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 125ee98c4a5SJohn Baldwin mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 126ee98c4a5SJohn Baldwin user_handler_id); 127ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 128ee98c4a5SJohn Baldwin return (ENOMEM); 129ee98c4a5SJohn Baldwin } 130ee98c4a5SJohn Baldwin mpt->cdev->si_drv1 = mpt; 131ee98c4a5SJohn Baldwin return (0); 132ee98c4a5SJohn Baldwin } 133ee98c4a5SJohn Baldwin 134ee98c4a5SJohn Baldwin int 135ee98c4a5SJohn Baldwin mpt_user_enable(struct mpt_softc *mpt) 136ee98c4a5SJohn Baldwin { 137ee98c4a5SJohn Baldwin 138ee98c4a5SJohn Baldwin return (0); 139ee98c4a5SJohn Baldwin } 140ee98c4a5SJohn Baldwin 141ee98c4a5SJohn Baldwin void 142ee98c4a5SJohn Baldwin mpt_user_ready(struct mpt_softc *mpt) 143ee98c4a5SJohn Baldwin { 144ee98c4a5SJohn Baldwin } 145ee98c4a5SJohn Baldwin 146ee98c4a5SJohn Baldwin int 147ee98c4a5SJohn Baldwin mpt_user_event(struct mpt_softc *mpt, request_t *req, 148ee98c4a5SJohn Baldwin MSG_EVENT_NOTIFY_REPLY *msg) 149ee98c4a5SJohn Baldwin { 150ee98c4a5SJohn Baldwin 151ee98c4a5SJohn Baldwin /* Someday we may want to let a user daemon listen for events? */ 152ee98c4a5SJohn Baldwin return (0); 153ee98c4a5SJohn Baldwin } 154ee98c4a5SJohn Baldwin 155ee98c4a5SJohn Baldwin void 156ee98c4a5SJohn Baldwin mpt_user_reset(struct mpt_softc *mpt, int type) 157ee98c4a5SJohn Baldwin { 158ee98c4a5SJohn Baldwin } 159ee98c4a5SJohn Baldwin 160ee98c4a5SJohn Baldwin void 161ee98c4a5SJohn Baldwin mpt_user_detach(struct mpt_softc *mpt) 162ee98c4a5SJohn Baldwin { 163ee98c4a5SJohn Baldwin mpt_handler_t handler; 164ee98c4a5SJohn Baldwin 165ee98c4a5SJohn Baldwin /* XXX: do a purge of pending requests? */ 166ee98c4a5SJohn Baldwin destroy_dev(mpt->cdev); 167ee98c4a5SJohn Baldwin 168ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 169ee98c4a5SJohn Baldwin handler.reply_handler = mpt_user_reply_handler; 170ee98c4a5SJohn Baldwin mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 171ee98c4a5SJohn Baldwin user_handler_id); 172ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 173ee98c4a5SJohn Baldwin } 174ee98c4a5SJohn Baldwin 175ee98c4a5SJohn Baldwin static int 176ee98c4a5SJohn Baldwin mpt_open(struct cdev *dev, int flags, int fmt, d_thread_t *td) 177ee98c4a5SJohn Baldwin { 178ee98c4a5SJohn Baldwin 179ee98c4a5SJohn Baldwin return (0); 180ee98c4a5SJohn Baldwin } 181ee98c4a5SJohn Baldwin 182ee98c4a5SJohn Baldwin static int 183ee98c4a5SJohn Baldwin mpt_close(struct cdev *dev, int flags, int fmt, d_thread_t *td) 184ee98c4a5SJohn Baldwin { 185ee98c4a5SJohn Baldwin 186ee98c4a5SJohn Baldwin return (0); 187ee98c4a5SJohn Baldwin } 188ee98c4a5SJohn Baldwin 189ee98c4a5SJohn Baldwin static int 1904124f62eSJohn Baldwin mpt_alloc_buffer(struct mpt_softc *mpt, struct mpt_page_memory *page_mem, 1914124f62eSJohn Baldwin size_t len) 1924124f62eSJohn Baldwin { 1934124f62eSJohn Baldwin struct mpt_map_info mi; 1944124f62eSJohn Baldwin int error; 1954124f62eSJohn Baldwin 1964124f62eSJohn Baldwin page_mem->vaddr = NULL; 1974124f62eSJohn Baldwin 1984124f62eSJohn Baldwin /* Limit requests to 16M. */ 1994124f62eSJohn Baldwin if (len > 16 * 1024 * 1024) 2004124f62eSJohn Baldwin return (ENOSPC); 2014124f62eSJohn Baldwin error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 0, 2024124f62eSJohn Baldwin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 2034124f62eSJohn Baldwin len, 1, len, 0, &page_mem->tag); 2044124f62eSJohn Baldwin if (error) 2054124f62eSJohn Baldwin return (error); 2064124f62eSJohn Baldwin error = bus_dmamem_alloc(page_mem->tag, &page_mem->vaddr, 2074124f62eSJohn Baldwin BUS_DMA_NOWAIT, &page_mem->map); 2084124f62eSJohn Baldwin if (error) { 2094124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2104124f62eSJohn Baldwin return (error); 2114124f62eSJohn Baldwin } 2124124f62eSJohn Baldwin mi.mpt = mpt; 2134124f62eSJohn Baldwin error = bus_dmamap_load(page_mem->tag, page_mem->map, page_mem->vaddr, 2144124f62eSJohn Baldwin len, mpt_map_rquest, &mi, BUS_DMA_NOWAIT); 2154124f62eSJohn Baldwin if (error == 0) 2164124f62eSJohn Baldwin error = mi.error; 2174124f62eSJohn Baldwin if (error) { 2184124f62eSJohn Baldwin bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map); 2194124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2204124f62eSJohn Baldwin page_mem->vaddr = NULL; 2214124f62eSJohn Baldwin return (error); 2224124f62eSJohn Baldwin } 2234124f62eSJohn Baldwin page_mem->paddr = mi.phys; 2244124f62eSJohn Baldwin return (0); 2254124f62eSJohn Baldwin } 2264124f62eSJohn Baldwin 2274124f62eSJohn Baldwin static void 2284124f62eSJohn Baldwin mpt_free_buffer(struct mpt_page_memory *page_mem) 2294124f62eSJohn Baldwin { 2304124f62eSJohn Baldwin 2314124f62eSJohn Baldwin if (page_mem->vaddr == NULL) 2324124f62eSJohn Baldwin return; 2334124f62eSJohn Baldwin bus_dmamap_unload(page_mem->tag, page_mem->map); 2344124f62eSJohn Baldwin bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map); 2354124f62eSJohn Baldwin bus_dma_tag_destroy(page_mem->tag); 2364124f62eSJohn Baldwin page_mem->vaddr = NULL; 2374124f62eSJohn Baldwin } 2384124f62eSJohn Baldwin 2394124f62eSJohn Baldwin static int 240ee98c4a5SJohn Baldwin mpt_user_read_cfg_header(struct mpt_softc *mpt, 241ee98c4a5SJohn Baldwin struct mpt_cfg_page_req *page_req) 242ee98c4a5SJohn Baldwin { 243ee98c4a5SJohn Baldwin request_t *req; 244ee98c4a5SJohn Baldwin cfgparms_t params; 245ee98c4a5SJohn Baldwin MSG_CONFIG *cfgp; 246ee98c4a5SJohn Baldwin int error; 247ee98c4a5SJohn Baldwin 248ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 249ee98c4a5SJohn Baldwin if (req == NULL) { 250ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_header: Get request failed!\n"); 251ee98c4a5SJohn Baldwin return (ENOMEM); 252ee98c4a5SJohn Baldwin } 253ee98c4a5SJohn Baldwin 254ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_HEADER; 255ee98c4a5SJohn Baldwin params.PageVersion = 0; 256ee98c4a5SJohn Baldwin params.PageLength = 0; 257ee98c4a5SJohn Baldwin params.PageNumber = page_req->header.PageNumber; 258ee98c4a5SJohn Baldwin params.PageType = page_req->header.PageType; 2597ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 260ee98c4a5SJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0, 261ee98c4a5SJohn Baldwin TRUE, 5000); 262ee98c4a5SJohn Baldwin if (error != 0) { 263ee98c4a5SJohn Baldwin /* 264ee98c4a5SJohn Baldwin * Leave the request. Without resetting the chip, it's 265ee98c4a5SJohn Baldwin * still owned by it and we'll just get into trouble 266ee98c4a5SJohn Baldwin * freeing it now. Mark it as abandoned so that if it 267ee98c4a5SJohn Baldwin * shows up later it can be freed. 268ee98c4a5SJohn Baldwin */ 269ee98c4a5SJohn Baldwin mpt_prt(mpt, "read_cfg_header timed out\n"); 270ee98c4a5SJohn Baldwin return (ETIMEDOUT); 271ee98c4a5SJohn Baldwin } 272ee98c4a5SJohn Baldwin 2737ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 274ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) { 275ee98c4a5SJohn Baldwin cfgp = req->req_vbuf; 276ee98c4a5SJohn Baldwin bcopy(&cfgp->Header, &page_req->header, 277ee98c4a5SJohn Baldwin sizeof(page_req->header)); 278ee98c4a5SJohn Baldwin } 279ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 280ee98c4a5SJohn Baldwin return (0); 281ee98c4a5SJohn Baldwin } 282ee98c4a5SJohn Baldwin 283ee98c4a5SJohn Baldwin static int 284ee98c4a5SJohn Baldwin mpt_user_read_cfg_page(struct mpt_softc *mpt, struct mpt_cfg_page_req *page_req, 2854124f62eSJohn Baldwin struct mpt_page_memory *mpt_page) 286ee98c4a5SJohn Baldwin { 287ee98c4a5SJohn Baldwin CONFIG_PAGE_HEADER *hdr; 288ee98c4a5SJohn Baldwin request_t *req; 289ee98c4a5SJohn Baldwin cfgparms_t params; 290ee98c4a5SJohn Baldwin int error; 291ee98c4a5SJohn Baldwin 292ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 293ee98c4a5SJohn Baldwin if (req == NULL) { 294ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_page: Get request failed!\n"); 295ee98c4a5SJohn Baldwin return (ENOMEM); 296ee98c4a5SJohn Baldwin } 297ee98c4a5SJohn Baldwin 2984124f62eSJohn Baldwin hdr = mpt_page->vaddr; 299ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 300ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 301ee98c4a5SJohn Baldwin params.PageLength = hdr->PageLength; 302ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 303ee98c4a5SJohn Baldwin params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK; 3047ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 3054124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 3067ee37807SMarius Strobl le32toh(page_req->len), TRUE, 5000); 307ee98c4a5SJohn Baldwin if (error != 0) { 308ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_cfg_page timed out\n"); 309ee98c4a5SJohn Baldwin return (ETIMEDOUT); 310ee98c4a5SJohn Baldwin } 311ee98c4a5SJohn Baldwin 3127ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 3134124f62eSJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) 3144124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 315ee98c4a5SJohn Baldwin BUS_DMASYNC_POSTREAD); 316ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 317ee98c4a5SJohn Baldwin return (0); 318ee98c4a5SJohn Baldwin } 319ee98c4a5SJohn Baldwin 320ee98c4a5SJohn Baldwin static int 321ee98c4a5SJohn Baldwin mpt_user_read_extcfg_header(struct mpt_softc *mpt, 322ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req) 323ee98c4a5SJohn Baldwin { 324ee98c4a5SJohn Baldwin request_t *req; 325ee98c4a5SJohn Baldwin cfgparms_t params; 326ee98c4a5SJohn Baldwin MSG_CONFIG_REPLY *cfgp; 327ee98c4a5SJohn Baldwin int error; 328ee98c4a5SJohn Baldwin 329ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 330ee98c4a5SJohn Baldwin if (req == NULL) { 331ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_header: Get request failed!\n"); 332ee98c4a5SJohn Baldwin return (ENOMEM); 333ee98c4a5SJohn Baldwin } 334ee98c4a5SJohn Baldwin 335ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_HEADER; 336ee98c4a5SJohn Baldwin params.PageVersion = ext_page_req->header.PageVersion; 337ee98c4a5SJohn Baldwin params.PageLength = 0; 338ee98c4a5SJohn Baldwin params.PageNumber = ext_page_req->header.PageNumber; 339ee98c4a5SJohn Baldwin params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 3407ee37807SMarius Strobl params.PageAddress = le32toh(ext_page_req->page_address); 341ee98c4a5SJohn Baldwin params.ExtPageType = ext_page_req->header.ExtPageType; 342ee98c4a5SJohn Baldwin params.ExtPageLength = 0; 343ee98c4a5SJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0, 344ee98c4a5SJohn Baldwin TRUE, 5000); 345ee98c4a5SJohn Baldwin if (error != 0) { 346ee98c4a5SJohn Baldwin /* 347ee98c4a5SJohn Baldwin * Leave the request. Without resetting the chip, it's 348ee98c4a5SJohn Baldwin * still owned by it and we'll just get into trouble 349ee98c4a5SJohn Baldwin * freeing it now. Mark it as abandoned so that if it 350ee98c4a5SJohn Baldwin * shows up later it can be freed. 351ee98c4a5SJohn Baldwin */ 352ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_header timed out\n"); 353ee98c4a5SJohn Baldwin return (ETIMEDOUT); 354ee98c4a5SJohn Baldwin } 355ee98c4a5SJohn Baldwin 3567ee37807SMarius Strobl ext_page_req->ioc_status = htole16(req->IOCStatus); 357ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) { 358ee98c4a5SJohn Baldwin cfgp = req->req_vbuf; 359ee98c4a5SJohn Baldwin ext_page_req->header.PageVersion = cfgp->Header.PageVersion; 360ee98c4a5SJohn Baldwin ext_page_req->header.PageNumber = cfgp->Header.PageNumber; 361ee98c4a5SJohn Baldwin ext_page_req->header.PageType = cfgp->Header.PageType; 362ee98c4a5SJohn Baldwin ext_page_req->header.ExtPageLength = cfgp->ExtPageLength; 363ee98c4a5SJohn Baldwin ext_page_req->header.ExtPageType = cfgp->ExtPageType; 364ee98c4a5SJohn Baldwin } 365ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 366ee98c4a5SJohn Baldwin return (0); 367ee98c4a5SJohn Baldwin } 368ee98c4a5SJohn Baldwin 369ee98c4a5SJohn Baldwin static int 370ee98c4a5SJohn Baldwin mpt_user_read_extcfg_page(struct mpt_softc *mpt, 3714124f62eSJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req, struct mpt_page_memory *mpt_page) 372ee98c4a5SJohn Baldwin { 373ee98c4a5SJohn Baldwin CONFIG_EXTENDED_PAGE_HEADER *hdr; 374ee98c4a5SJohn Baldwin request_t *req; 375ee98c4a5SJohn Baldwin cfgparms_t params; 376ee98c4a5SJohn Baldwin int error; 377ee98c4a5SJohn Baldwin 378ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 379ee98c4a5SJohn Baldwin if (req == NULL) { 380ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_page: Get request failed!\n"); 381ee98c4a5SJohn Baldwin return (ENOMEM); 382ee98c4a5SJohn Baldwin } 383ee98c4a5SJohn Baldwin 3844124f62eSJohn Baldwin hdr = mpt_page->vaddr; 385ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 386ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 387ee98c4a5SJohn Baldwin params.PageLength = 0; 388ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 389ee98c4a5SJohn Baldwin params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 3907ee37807SMarius Strobl params.PageAddress = le32toh(ext_page_req->page_address); 391ee98c4a5SJohn Baldwin params.ExtPageType = hdr->ExtPageType; 392ee98c4a5SJohn Baldwin params.ExtPageLength = hdr->ExtPageLength; 3934124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 3947ee37807SMarius Strobl le32toh(ext_page_req->len), TRUE, 5000); 395ee98c4a5SJohn Baldwin if (error != 0) { 396ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_read_extcfg_page timed out\n"); 397ee98c4a5SJohn Baldwin return (ETIMEDOUT); 398ee98c4a5SJohn Baldwin } 399ee98c4a5SJohn Baldwin 4007ee37807SMarius Strobl ext_page_req->ioc_status = htole16(req->IOCStatus); 4014124f62eSJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) 4024124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 403ee98c4a5SJohn Baldwin BUS_DMASYNC_POSTREAD); 404ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 405ee98c4a5SJohn Baldwin return (0); 406ee98c4a5SJohn Baldwin } 407ee98c4a5SJohn Baldwin 408ee98c4a5SJohn Baldwin static int 409ee98c4a5SJohn Baldwin mpt_user_write_cfg_page(struct mpt_softc *mpt, 4104124f62eSJohn Baldwin struct mpt_cfg_page_req *page_req, struct mpt_page_memory *mpt_page) 411ee98c4a5SJohn Baldwin { 412ee98c4a5SJohn Baldwin CONFIG_PAGE_HEADER *hdr; 413ee98c4a5SJohn Baldwin request_t *req; 414ee98c4a5SJohn Baldwin cfgparms_t params; 415ee98c4a5SJohn Baldwin u_int hdr_attr; 416ee98c4a5SJohn Baldwin int error; 417ee98c4a5SJohn Baldwin 4184124f62eSJohn Baldwin hdr = mpt_page->vaddr; 419ee98c4a5SJohn Baldwin hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK; 420ee98c4a5SJohn Baldwin if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE && 421ee98c4a5SJohn Baldwin hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) { 422ee98c4a5SJohn Baldwin mpt_prt(mpt, "page type 0x%x not changeable\n", 423ee98c4a5SJohn Baldwin hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); 424ee98c4a5SJohn Baldwin return (EINVAL); 425ee98c4a5SJohn Baldwin } 426ee98c4a5SJohn Baldwin 427ee98c4a5SJohn Baldwin #if 0 428ee98c4a5SJohn Baldwin /* 429ee98c4a5SJohn Baldwin * We shouldn't mask off other bits here. 430ee98c4a5SJohn Baldwin */ 431ee98c4a5SJohn Baldwin hdr->PageType &= ~MPI_CONFIG_PAGETYPE_MASK; 432ee98c4a5SJohn Baldwin #endif 433ee98c4a5SJohn Baldwin 434ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 435ee98c4a5SJohn Baldwin if (req == NULL) 436ee98c4a5SJohn Baldwin return (ENOMEM); 437ee98c4a5SJohn Baldwin 4384124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_PREWRITE); 439ee98c4a5SJohn Baldwin 440ee98c4a5SJohn Baldwin /* 441ee98c4a5SJohn Baldwin * There isn't any point in restoring stripped out attributes 442ee98c4a5SJohn Baldwin * if you then mask them going down to issue the request. 443ee98c4a5SJohn Baldwin */ 444ee98c4a5SJohn Baldwin 445ee98c4a5SJohn Baldwin params.Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; 446ee98c4a5SJohn Baldwin params.PageVersion = hdr->PageVersion; 447ee98c4a5SJohn Baldwin params.PageLength = hdr->PageLength; 448ee98c4a5SJohn Baldwin params.PageNumber = hdr->PageNumber; 4497ee37807SMarius Strobl params.PageAddress = le32toh(page_req->page_address); 450ee98c4a5SJohn Baldwin #if 0 451ee98c4a5SJohn Baldwin /* Restore stripped out attributes */ 452ee98c4a5SJohn Baldwin hdr->PageType |= hdr_attr; 453ee98c4a5SJohn Baldwin params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK; 454ee98c4a5SJohn Baldwin #else 455ee98c4a5SJohn Baldwin params.PageType = hdr->PageType; 456ee98c4a5SJohn Baldwin #endif 4574124f62eSJohn Baldwin error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr, 4587ee37807SMarius Strobl le32toh(page_req->len), TRUE, 5000); 459ee98c4a5SJohn Baldwin if (error != 0) { 460ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_write_cfg_page timed out\n"); 461ee98c4a5SJohn Baldwin return (ETIMEDOUT); 462ee98c4a5SJohn Baldwin } 463ee98c4a5SJohn Baldwin 4647ee37807SMarius Strobl page_req->ioc_status = htole16(req->IOCStatus); 465ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 466ee98c4a5SJohn Baldwin return (0); 467ee98c4a5SJohn Baldwin } 468ee98c4a5SJohn Baldwin 469ee98c4a5SJohn Baldwin static int 470ee98c4a5SJohn Baldwin mpt_user_reply_handler(struct mpt_softc *mpt, request_t *req, 471ee98c4a5SJohn Baldwin uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame) 472ee98c4a5SJohn Baldwin { 473ee98c4a5SJohn Baldwin MSG_RAID_ACTION_REPLY *reply; 474ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result *res; 475ee98c4a5SJohn Baldwin 476ee98c4a5SJohn Baldwin if (req == NULL) 477ee98c4a5SJohn Baldwin return (TRUE); 478ee98c4a5SJohn Baldwin 479ee98c4a5SJohn Baldwin if (reply_frame != NULL) { 480ee98c4a5SJohn Baldwin bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, 481ee98c4a5SJohn Baldwin BUS_DMASYNC_POSTREAD); 482ee98c4a5SJohn Baldwin reply = (MSG_RAID_ACTION_REPLY *)reply_frame; 483ee98c4a5SJohn Baldwin req->IOCStatus = le16toh(reply->IOCStatus); 484ee98c4a5SJohn Baldwin res = (struct mpt_user_raid_action_result *) 485ee98c4a5SJohn Baldwin (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt)); 486ee98c4a5SJohn Baldwin res->action_status = reply->ActionStatus; 487ee98c4a5SJohn Baldwin res->volume_status = reply->VolumeStatus; 488ee98c4a5SJohn Baldwin bcopy(&reply->ActionData, res->action_data, 489ee98c4a5SJohn Baldwin sizeof(res->action_data)); 490ee98c4a5SJohn Baldwin } 491ee98c4a5SJohn Baldwin 492ee98c4a5SJohn Baldwin req->state &= ~REQ_STATE_QUEUED; 493ee98c4a5SJohn Baldwin req->state |= REQ_STATE_DONE; 494ee98c4a5SJohn Baldwin TAILQ_REMOVE(&mpt->request_pending_list, req, links); 495ee98c4a5SJohn Baldwin 496ee98c4a5SJohn Baldwin if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) { 497ee98c4a5SJohn Baldwin wakeup(req); 498ee98c4a5SJohn Baldwin } else if ((req->state & REQ_STATE_TIMEDOUT) != 0) { 499ee98c4a5SJohn Baldwin /* 500ee98c4a5SJohn Baldwin * Whew- we can free this request (late completion) 501ee98c4a5SJohn Baldwin */ 502ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 503ee98c4a5SJohn Baldwin } 504ee98c4a5SJohn Baldwin 505ee98c4a5SJohn Baldwin return (TRUE); 506ee98c4a5SJohn Baldwin } 507ee98c4a5SJohn Baldwin 508ee98c4a5SJohn Baldwin /* 509ee98c4a5SJohn Baldwin * We use the first part of the request buffer after the request frame 510ee98c4a5SJohn Baldwin * to hold the action data and action status from the RAID reply. The 511ee98c4a5SJohn Baldwin * rest of the request buffer is used to hold the buffer for the 512ee98c4a5SJohn Baldwin * action SGE. 513ee98c4a5SJohn Baldwin */ 514ee98c4a5SJohn Baldwin static int 515ee98c4a5SJohn Baldwin mpt_user_raid_action(struct mpt_softc *mpt, struct mpt_raid_action *raid_act, 5164124f62eSJohn Baldwin struct mpt_page_memory *mpt_page) 517ee98c4a5SJohn Baldwin { 518ee98c4a5SJohn Baldwin request_t *req; 519ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result *res; 520ee98c4a5SJohn Baldwin MSG_RAID_ACTION_REQUEST *rap; 521ee98c4a5SJohn Baldwin SGE_SIMPLE32 *se; 522ee98c4a5SJohn Baldwin int error; 523ee98c4a5SJohn Baldwin 524ee98c4a5SJohn Baldwin req = mpt_get_request(mpt, TRUE); 525ee98c4a5SJohn Baldwin if (req == NULL) 526ee98c4a5SJohn Baldwin return (ENOMEM); 527ee98c4a5SJohn Baldwin rap = req->req_vbuf; 528ee98c4a5SJohn Baldwin memset(rap, 0, sizeof *rap); 529ee98c4a5SJohn Baldwin rap->Action = raid_act->action; 530ee98c4a5SJohn Baldwin rap->ActionDataWord = raid_act->action_data_word; 531ee98c4a5SJohn Baldwin rap->Function = MPI_FUNCTION_RAID_ACTION; 532ee98c4a5SJohn Baldwin rap->VolumeID = raid_act->volume_id; 533ee98c4a5SJohn Baldwin rap->VolumeBus = raid_act->volume_bus; 534ee98c4a5SJohn Baldwin rap->PhysDiskNum = raid_act->phys_disk_num; 535ee98c4a5SJohn Baldwin se = (SGE_SIMPLE32 *)&rap->ActionDataSGE; 5364124f62eSJohn Baldwin if (mpt_page->vaddr != NULL && raid_act->len != 0) { 5374124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 5384124f62eSJohn Baldwin BUS_DMASYNC_PREWRITE); 5397ee37807SMarius Strobl se->Address = htole32(mpt_page->paddr); 5407ee37807SMarius Strobl MPI_pSGE_SET_LENGTH(se, le32toh(raid_act->len)); 541ee98c4a5SJohn Baldwin MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 542ee98c4a5SJohn Baldwin MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 543ee98c4a5SJohn Baldwin MPI_SGE_FLAGS_END_OF_LIST | 544ee98c4a5SJohn Baldwin raid_act->write ? MPI_SGE_FLAGS_HOST_TO_IOC : 545ee98c4a5SJohn Baldwin MPI_SGE_FLAGS_IOC_TO_HOST)); 546ee98c4a5SJohn Baldwin } 5477ee37807SMarius Strobl se->FlagsLength = htole32(se->FlagsLength); 548ee98c4a5SJohn Baldwin rap->MsgContext = htole32(req->index | user_handler_id); 549ee98c4a5SJohn Baldwin 550ee98c4a5SJohn Baldwin mpt_check_doorbell(mpt); 551ee98c4a5SJohn Baldwin mpt_send_cmd(mpt, req); 552ee98c4a5SJohn Baldwin 553ee98c4a5SJohn Baldwin error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, TRUE, 554ee98c4a5SJohn Baldwin 2000); 555ee98c4a5SJohn Baldwin if (error != 0) { 556ee98c4a5SJohn Baldwin /* 557ee98c4a5SJohn Baldwin * Leave request so it can be cleaned up later. 558ee98c4a5SJohn Baldwin */ 559ee98c4a5SJohn Baldwin mpt_prt(mpt, "mpt_user_raid_action timed out\n"); 560ee98c4a5SJohn Baldwin return (error); 561ee98c4a5SJohn Baldwin } 562ee98c4a5SJohn Baldwin 5637ee37807SMarius Strobl raid_act->ioc_status = htole16(req->IOCStatus); 564ee98c4a5SJohn Baldwin if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 565ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 566ee98c4a5SJohn Baldwin return (0); 567ee98c4a5SJohn Baldwin } 568ee98c4a5SJohn Baldwin 569ee98c4a5SJohn Baldwin res = (struct mpt_user_raid_action_result *) 570ee98c4a5SJohn Baldwin (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt)); 571ee98c4a5SJohn Baldwin raid_act->volume_status = res->volume_status; 572ee98c4a5SJohn Baldwin raid_act->action_status = res->action_status; 573ee98c4a5SJohn Baldwin bcopy(res->action_data, raid_act->action_data, 574ee98c4a5SJohn Baldwin sizeof(res->action_data)); 5754124f62eSJohn Baldwin if (mpt_page->vaddr != NULL) 5764124f62eSJohn Baldwin bus_dmamap_sync(mpt_page->tag, mpt_page->map, 5774124f62eSJohn Baldwin BUS_DMASYNC_POSTREAD); 578ee98c4a5SJohn Baldwin mpt_free_request(mpt, req); 579ee98c4a5SJohn Baldwin return (0); 580ee98c4a5SJohn Baldwin } 581ee98c4a5SJohn Baldwin 582ee98c4a5SJohn Baldwin #ifdef __amd64__ 583ee98c4a5SJohn Baldwin #define PTRIN(p) ((void *)(uintptr_t)(p)) 584ee98c4a5SJohn Baldwin #define PTROUT(v) ((u_int32_t)(uintptr_t)(v)) 585ee98c4a5SJohn Baldwin #endif 586ee98c4a5SJohn Baldwin 587ee98c4a5SJohn Baldwin static int 588ee98c4a5SJohn Baldwin mpt_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) 589ee98c4a5SJohn Baldwin { 590ee98c4a5SJohn Baldwin struct mpt_softc *mpt; 591ee98c4a5SJohn Baldwin struct mpt_cfg_page_req *page_req; 592ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req *ext_page_req; 593ee98c4a5SJohn Baldwin struct mpt_raid_action *raid_act; 5944124f62eSJohn Baldwin struct mpt_page_memory mpt_page; 595ee98c4a5SJohn Baldwin #ifdef __amd64__ 596ee98c4a5SJohn Baldwin struct mpt_cfg_page_req32 *page_req32; 597ee98c4a5SJohn Baldwin struct mpt_cfg_page_req page_req_swab; 598ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req32 *ext_page_req32; 599ee98c4a5SJohn Baldwin struct mpt_ext_cfg_page_req ext_page_req_swab; 600ee98c4a5SJohn Baldwin struct mpt_raid_action32 *raid_act32; 601ee98c4a5SJohn Baldwin struct mpt_raid_action raid_act_swab; 602ee98c4a5SJohn Baldwin #endif 603ee98c4a5SJohn Baldwin int error; 604ee98c4a5SJohn Baldwin 605ee98c4a5SJohn Baldwin mpt = dev->si_drv1; 606ee98c4a5SJohn Baldwin page_req = (void *)arg; 607ee98c4a5SJohn Baldwin ext_page_req = (void *)arg; 608ee98c4a5SJohn Baldwin raid_act = (void *)arg; 6094124f62eSJohn Baldwin mpt_page.vaddr = NULL; 610ee98c4a5SJohn Baldwin 611ee98c4a5SJohn Baldwin #ifdef __amd64__ 612ee98c4a5SJohn Baldwin /* Convert 32-bit structs to native ones. */ 613ee98c4a5SJohn Baldwin page_req32 = (void *)arg; 614ee98c4a5SJohn Baldwin ext_page_req32 = (void *)arg; 615ee98c4a5SJohn Baldwin raid_act32 = (void *)arg; 616ee98c4a5SJohn Baldwin switch (cmd) { 617ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 618ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 619ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 620ee98c4a5SJohn Baldwin page_req = &page_req_swab; 621ee98c4a5SJohn Baldwin page_req->header = page_req32->header; 622ee98c4a5SJohn Baldwin page_req->page_address = page_req32->page_address; 623ee98c4a5SJohn Baldwin page_req->buf = PTRIN(page_req32->buf); 624ee98c4a5SJohn Baldwin page_req->len = page_req32->len; 625ee98c4a5SJohn Baldwin page_req->ioc_status = page_req32->ioc_status; 626ee98c4a5SJohn Baldwin break; 627ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 628ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 629ee98c4a5SJohn Baldwin ext_page_req = &ext_page_req_swab; 630ee98c4a5SJohn Baldwin ext_page_req->header = ext_page_req32->header; 631ee98c4a5SJohn Baldwin ext_page_req->page_address = ext_page_req32->page_address; 632ee98c4a5SJohn Baldwin ext_page_req->buf = PTRIN(ext_page_req32->buf); 633ee98c4a5SJohn Baldwin ext_page_req->len = ext_page_req32->len; 634ee98c4a5SJohn Baldwin ext_page_req->ioc_status = ext_page_req32->ioc_status; 635ee98c4a5SJohn Baldwin break; 636ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 637ee98c4a5SJohn Baldwin raid_act = &raid_act_swab; 638ee98c4a5SJohn Baldwin raid_act->action = raid_act32->action; 639ee98c4a5SJohn Baldwin raid_act->volume_bus = raid_act32->volume_bus; 640ee98c4a5SJohn Baldwin raid_act->volume_id = raid_act32->volume_id; 641ee98c4a5SJohn Baldwin raid_act->phys_disk_num = raid_act32->phys_disk_num; 642ee98c4a5SJohn Baldwin raid_act->action_data_word = raid_act32->action_data_word; 643ee98c4a5SJohn Baldwin raid_act->buf = PTRIN(raid_act32->buf); 644ee98c4a5SJohn Baldwin raid_act->len = raid_act32->len; 645ee98c4a5SJohn Baldwin raid_act->volume_status = raid_act32->volume_status; 646ee98c4a5SJohn Baldwin bcopy(raid_act32->action_data, raid_act->action_data, 647ee98c4a5SJohn Baldwin sizeof(raid_act->action_data)); 648ee98c4a5SJohn Baldwin raid_act->action_status = raid_act32->action_status; 649ee98c4a5SJohn Baldwin raid_act->ioc_status = raid_act32->ioc_status; 650ee98c4a5SJohn Baldwin raid_act->write = raid_act32->write; 651ee98c4a5SJohn Baldwin break; 652ee98c4a5SJohn Baldwin } 653ee98c4a5SJohn Baldwin #endif 654ee98c4a5SJohn Baldwin 655ee98c4a5SJohn Baldwin switch (cmd) { 656ee98c4a5SJohn Baldwin #ifdef __amd64__ 657ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 658ee98c4a5SJohn Baldwin #endif 659ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER: 660ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 661ee98c4a5SJohn Baldwin error = mpt_user_read_cfg_header(mpt, page_req); 662ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 663ee98c4a5SJohn Baldwin break; 664ee98c4a5SJohn Baldwin #ifdef __amd64__ 665ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 666ee98c4a5SJohn Baldwin #endif 667ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE: 6684124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len); 6694124f62eSJohn Baldwin if (error) 670ee98c4a5SJohn Baldwin break; 6714124f62eSJohn Baldwin error = copyin(page_req->buf, mpt_page.vaddr, 672ee98c4a5SJohn Baldwin sizeof(CONFIG_PAGE_HEADER)); 673ee98c4a5SJohn Baldwin if (error) 674ee98c4a5SJohn Baldwin break; 675ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 6764124f62eSJohn Baldwin error = mpt_user_read_cfg_page(mpt, page_req, &mpt_page); 677ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 678ee98c4a5SJohn Baldwin if (error) 679ee98c4a5SJohn Baldwin break; 6804124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, page_req->buf, page_req->len); 681ee98c4a5SJohn Baldwin break; 682ee98c4a5SJohn Baldwin #ifdef __amd64__ 683ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 684ee98c4a5SJohn Baldwin #endif 685ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER: 686ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 687ee98c4a5SJohn Baldwin error = mpt_user_read_extcfg_header(mpt, ext_page_req); 688ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 689ee98c4a5SJohn Baldwin break; 690ee98c4a5SJohn Baldwin #ifdef __amd64__ 691ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 692ee98c4a5SJohn Baldwin #endif 693ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE: 6944124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, ext_page_req->len); 6954124f62eSJohn Baldwin if (error) 696ee98c4a5SJohn Baldwin break; 6974124f62eSJohn Baldwin error = copyin(ext_page_req->buf, mpt_page.vaddr, 698ee98c4a5SJohn Baldwin sizeof(CONFIG_EXTENDED_PAGE_HEADER)); 699ee98c4a5SJohn Baldwin if (error) 700ee98c4a5SJohn Baldwin break; 701ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7024124f62eSJohn Baldwin error = mpt_user_read_extcfg_page(mpt, ext_page_req, &mpt_page); 703ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 704ee98c4a5SJohn Baldwin if (error) 705ee98c4a5SJohn Baldwin break; 7064124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, ext_page_req->buf, 7074124f62eSJohn Baldwin ext_page_req->len); 708ee98c4a5SJohn Baldwin break; 709ee98c4a5SJohn Baldwin #ifdef __amd64__ 710ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 711ee98c4a5SJohn Baldwin #endif 712ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE: 7134124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len); 7144124f62eSJohn Baldwin if (error) 715ee98c4a5SJohn Baldwin break; 7164124f62eSJohn Baldwin error = copyin(page_req->buf, mpt_page.vaddr, page_req->len); 717ee98c4a5SJohn Baldwin if (error) 718ee98c4a5SJohn Baldwin break; 719ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7204124f62eSJohn Baldwin error = mpt_user_write_cfg_page(mpt, page_req, &mpt_page); 721ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 722ee98c4a5SJohn Baldwin break; 723ee98c4a5SJohn Baldwin #ifdef __amd64__ 724ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 725ee98c4a5SJohn Baldwin #endif 726ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION: 727ee98c4a5SJohn Baldwin if (raid_act->buf != NULL) { 7284124f62eSJohn Baldwin error = mpt_alloc_buffer(mpt, &mpt_page, raid_act->len); 7294124f62eSJohn Baldwin if (error) 730ee98c4a5SJohn Baldwin break; 7314124f62eSJohn Baldwin error = copyin(raid_act->buf, mpt_page.vaddr, 7324124f62eSJohn Baldwin raid_act->len); 733ee98c4a5SJohn Baldwin if (error) 734ee98c4a5SJohn Baldwin break; 735ee98c4a5SJohn Baldwin } 736ee98c4a5SJohn Baldwin MPT_LOCK(mpt); 7374124f62eSJohn Baldwin error = mpt_user_raid_action(mpt, raid_act, &mpt_page); 738ee98c4a5SJohn Baldwin MPT_UNLOCK(mpt); 739ee98c4a5SJohn Baldwin if (error) 740ee98c4a5SJohn Baldwin break; 7414124f62eSJohn Baldwin if (raid_act->buf != NULL) 7424124f62eSJohn Baldwin error = copyout(mpt_page.vaddr, raid_act->buf, 7434124f62eSJohn Baldwin raid_act->len); 744ee98c4a5SJohn Baldwin break; 745ee98c4a5SJohn Baldwin default: 746ee98c4a5SJohn Baldwin error = ENOIOCTL; 747ee98c4a5SJohn Baldwin break; 748ee98c4a5SJohn Baldwin } 749ee98c4a5SJohn Baldwin 7504124f62eSJohn Baldwin mpt_free_buffer(&mpt_page); 751ee98c4a5SJohn Baldwin 752ee98c4a5SJohn Baldwin if (error) 753ee98c4a5SJohn Baldwin return (error); 754ee98c4a5SJohn Baldwin 755ee98c4a5SJohn Baldwin #ifdef __amd64__ 756ee98c4a5SJohn Baldwin /* Convert native structs to 32-bit ones. */ 757ee98c4a5SJohn Baldwin switch (cmd) { 758ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_HEADER32: 759ee98c4a5SJohn Baldwin case MPTIO_READ_CFG_PAGE32: 760ee98c4a5SJohn Baldwin case MPTIO_WRITE_CFG_PAGE32: 761ee98c4a5SJohn Baldwin page_req32->header = page_req->header; 762ee98c4a5SJohn Baldwin page_req32->page_address = page_req->page_address; 763ee98c4a5SJohn Baldwin page_req32->buf = PTROUT(page_req->buf); 764ee98c4a5SJohn Baldwin page_req32->len = page_req->len; 765ee98c4a5SJohn Baldwin page_req32->ioc_status = page_req->ioc_status; 766ee98c4a5SJohn Baldwin break; 767ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_HEADER32: 768ee98c4a5SJohn Baldwin case MPTIO_READ_EXT_CFG_PAGE32: 769ee98c4a5SJohn Baldwin ext_page_req32->header = ext_page_req->header; 770ee98c4a5SJohn Baldwin ext_page_req32->page_address = ext_page_req->page_address; 771ee98c4a5SJohn Baldwin ext_page_req32->buf = PTROUT(ext_page_req->buf); 772ee98c4a5SJohn Baldwin ext_page_req32->len = ext_page_req->len; 773ee98c4a5SJohn Baldwin ext_page_req32->ioc_status = ext_page_req->ioc_status; 774ee98c4a5SJohn Baldwin break; 775ee98c4a5SJohn Baldwin case MPTIO_RAID_ACTION32: 776ee98c4a5SJohn Baldwin raid_act32->action = raid_act->action; 777ee98c4a5SJohn Baldwin raid_act32->volume_bus = raid_act->volume_bus; 778ee98c4a5SJohn Baldwin raid_act32->volume_id = raid_act->volume_id; 779ee98c4a5SJohn Baldwin raid_act32->phys_disk_num = raid_act->phys_disk_num; 780ee98c4a5SJohn Baldwin raid_act32->action_data_word = raid_act->action_data_word; 781ee98c4a5SJohn Baldwin raid_act32->buf = PTROUT(raid_act->buf); 782ee98c4a5SJohn Baldwin raid_act32->len = raid_act->len; 783ee98c4a5SJohn Baldwin raid_act32->volume_status = raid_act->volume_status; 784ee98c4a5SJohn Baldwin bcopy(raid_act->action_data, raid_act32->action_data, 785ee98c4a5SJohn Baldwin sizeof(raid_act->action_data)); 786ee98c4a5SJohn Baldwin raid_act32->action_status = raid_act->action_status; 787ee98c4a5SJohn Baldwin raid_act32->ioc_status = raid_act->ioc_status; 788ee98c4a5SJohn Baldwin raid_act32->write = raid_act->write; 789ee98c4a5SJohn Baldwin break; 790ee98c4a5SJohn Baldwin } 791ee98c4a5SJohn Baldwin #endif 792ee98c4a5SJohn Baldwin 793ee98c4a5SJohn Baldwin return (0); 794ee98c4a5SJohn Baldwin } 795