2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 2008 Yahoo!, Inc.
6 * Written by: John Baldwin <jhb@FreeBSD.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * LSI MPT-Fusion Host Adapter FreeBSD userland interface
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
38 #include <sys/param.h>
40 #include <sys/abi_compat.h>
43 #include <sys/errno.h>
44 #include <sys/ioccom.h>
45 #include <sys/mpt_ioctl.h>
47 #include <dev/mpt/mpt.h>
49 struct mpt_user_raid_action_result {
50 uint32_t volume_status;
51 uint32_t action_data[4];
52 uint16_t action_status;
55 struct mpt_page_memory {
62 static mpt_probe_handler_t mpt_user_probe;
63 static mpt_attach_handler_t mpt_user_attach;
64 static mpt_enable_handler_t mpt_user_enable;
65 static mpt_ready_handler_t mpt_user_ready;
66 static mpt_event_handler_t mpt_user_event;
67 static mpt_reset_handler_t mpt_user_reset;
68 static mpt_detach_handler_t mpt_user_detach;
70 static struct mpt_personality mpt_user_personality = {
72 .probe = mpt_user_probe,
73 .attach = mpt_user_attach,
74 .enable = mpt_user_enable,
75 .ready = mpt_user_ready,
76 .event = mpt_user_event,
77 .reset = mpt_user_reset,
78 .detach = mpt_user_detach,
81 DECLARE_MPT_PERSONALITY(mpt_user, SI_ORDER_SECOND);
83 static mpt_reply_handler_t mpt_user_reply_handler;
85 static d_open_t mpt_open;
86 static d_close_t mpt_close;
87 static d_ioctl_t mpt_ioctl;
89 static struct cdevsw mpt_cdevsw = {
90 .d_version = D_VERSION,
98 static MALLOC_DEFINE(M_MPTUSER, "mpt_user", "Buffers for mpt(4) ioctls");
100 static uint32_t user_handler_id = MPT_HANDLER_ID_NONE;
103 mpt_user_probe(struct mpt_softc *mpt)
106 /* Attach to every controller. */
111 mpt_user_attach(struct mpt_softc *mpt)
113 mpt_handler_t handler;
117 handler.reply_handler = mpt_user_reply_handler;
118 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
122 mpt_prt(mpt, "Unable to register user handler!\n");
125 unit = device_get_unit(mpt->dev);
126 mpt->cdev = make_dev(&mpt_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640,
128 if (mpt->cdev == NULL) {
130 mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
135 mpt->cdev->si_drv1 = mpt;
140 mpt_user_enable(struct mpt_softc *mpt)
147 mpt_user_ready(struct mpt_softc *mpt)
153 mpt_user_event(struct mpt_softc *mpt, request_t *req,
154 MSG_EVENT_NOTIFY_REPLY *msg)
157 /* Someday we may want to let a user daemon listen for events? */
162 mpt_user_reset(struct mpt_softc *mpt, int type)
168 mpt_user_detach(struct mpt_softc *mpt)
170 mpt_handler_t handler;
172 /* XXX: do a purge of pending requests? */
173 destroy_dev(mpt->cdev);
176 handler.reply_handler = mpt_user_reply_handler;
177 mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
183 mpt_open(struct cdev *dev, int flags, int fmt, struct thread *td)
190 mpt_close(struct cdev *dev, int flags, int fmt, struct thread *td)
197 mpt_alloc_buffer(struct mpt_softc *mpt, struct mpt_page_memory *page_mem,
200 struct mpt_map_info mi;
203 page_mem->vaddr = NULL;
205 /* Limit requests to 16M. */
206 if (len > 16 * 1024 * 1024)
208 error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 0,
209 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
210 len, 1, len, 0, &page_mem->tag);
213 error = bus_dmamem_alloc(page_mem->tag, &page_mem->vaddr,
214 BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &page_mem->map);
216 bus_dma_tag_destroy(page_mem->tag);
220 error = bus_dmamap_load(page_mem->tag, page_mem->map, page_mem->vaddr,
221 len, mpt_map_rquest, &mi, BUS_DMA_NOWAIT);
225 bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map);
226 bus_dma_tag_destroy(page_mem->tag);
227 page_mem->vaddr = NULL;
230 page_mem->paddr = mi.phys;
235 mpt_free_buffer(struct mpt_page_memory *page_mem)
238 if (page_mem->vaddr == NULL)
240 bus_dmamap_unload(page_mem->tag, page_mem->map);
241 bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map);
242 bus_dma_tag_destroy(page_mem->tag);
243 page_mem->vaddr = NULL;
247 mpt_user_read_cfg_header(struct mpt_softc *mpt,
248 struct mpt_cfg_page_req *page_req)
255 req = mpt_get_request(mpt, TRUE);
257 mpt_prt(mpt, "mpt_user_read_cfg_header: Get request failed!\n");
261 params.Action = MPI_CONFIG_ACTION_PAGE_HEADER;
262 params.PageVersion = 0;
263 params.PageLength = 0;
264 params.PageNumber = page_req->header.PageNumber;
265 params.PageType = page_req->header.PageType;
266 params.PageAddress = le32toh(page_req->page_address);
267 error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0,
271 * Leave the request. Without resetting the chip, it's
272 * still owned by it and we'll just get into trouble
273 * freeing it now. Mark it as abandoned so that if it
274 * shows up later it can be freed.
276 mpt_prt(mpt, "read_cfg_header timed out\n");
280 page_req->ioc_status = htole16(req->IOCStatus);
281 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) {
282 cfgp = req->req_vbuf;
283 bcopy(&cfgp->Header, &page_req->header,
284 sizeof(page_req->header));
286 mpt_free_request(mpt, req);
291 mpt_user_read_cfg_page(struct mpt_softc *mpt, struct mpt_cfg_page_req *page_req,
292 struct mpt_page_memory *mpt_page)
294 CONFIG_PAGE_HEADER *hdr;
299 req = mpt_get_request(mpt, TRUE);
301 mpt_prt(mpt, "mpt_user_read_cfg_page: Get request failed!\n");
305 hdr = mpt_page->vaddr;
306 params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
307 params.PageVersion = hdr->PageVersion;
308 params.PageLength = hdr->PageLength;
309 params.PageNumber = hdr->PageNumber;
310 params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK;
311 params.PageAddress = le32toh(page_req->page_address);
312 bus_dmamap_sync(mpt_page->tag, mpt_page->map,
313 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
314 error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr,
315 le32toh(page_req->len), TRUE, 5000);
317 mpt_prt(mpt, "mpt_user_read_cfg_page timed out\n");
321 page_req->ioc_status = htole16(req->IOCStatus);
322 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS)
323 bus_dmamap_sync(mpt_page->tag, mpt_page->map,
324 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
325 mpt_free_request(mpt, req);
330 mpt_user_read_extcfg_header(struct mpt_softc *mpt,
331 struct mpt_ext_cfg_page_req *ext_page_req)
335 MSG_CONFIG_REPLY *cfgp;
338 req = mpt_get_request(mpt, TRUE);
340 mpt_prt(mpt, "mpt_user_read_extcfg_header: Get request failed!\n");
344 params.Action = MPI_CONFIG_ACTION_PAGE_HEADER;
345 params.PageVersion = ext_page_req->header.PageVersion;
346 params.PageLength = 0;
347 params.PageNumber = ext_page_req->header.PageNumber;
348 params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
349 params.PageAddress = le32toh(ext_page_req->page_address);
350 params.ExtPageType = ext_page_req->header.ExtPageType;
351 params.ExtPageLength = 0;
352 error = mpt_issue_cfg_req(mpt, req, ¶ms, /*addr*/0, /*len*/0,
356 * Leave the request. Without resetting the chip, it's
357 * still owned by it and we'll just get into trouble
358 * freeing it now. Mark it as abandoned so that if it
359 * shows up later it can be freed.
361 mpt_prt(mpt, "mpt_user_read_extcfg_header timed out\n");
365 ext_page_req->ioc_status = htole16(req->IOCStatus);
366 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) {
367 cfgp = req->req_vbuf;
368 ext_page_req->header.PageVersion = cfgp->Header.PageVersion;
369 ext_page_req->header.PageNumber = cfgp->Header.PageNumber;
370 ext_page_req->header.PageType = cfgp->Header.PageType;
371 ext_page_req->header.ExtPageLength = cfgp->ExtPageLength;
372 ext_page_req->header.ExtPageType = cfgp->ExtPageType;
374 mpt_free_request(mpt, req);
379 mpt_user_read_extcfg_page(struct mpt_softc *mpt,
380 struct mpt_ext_cfg_page_req *ext_page_req, struct mpt_page_memory *mpt_page)
382 CONFIG_EXTENDED_PAGE_HEADER *hdr;
387 req = mpt_get_request(mpt, TRUE);
389 mpt_prt(mpt, "mpt_user_read_extcfg_page: Get request failed!\n");
393 hdr = mpt_page->vaddr;
394 params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
395 params.PageVersion = hdr->PageVersion;
396 params.PageLength = 0;
397 params.PageNumber = hdr->PageNumber;
398 params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
399 params.PageAddress = le32toh(ext_page_req->page_address);
400 params.ExtPageType = hdr->ExtPageType;
401 params.ExtPageLength = hdr->ExtPageLength;
402 bus_dmamap_sync(mpt_page->tag, mpt_page->map,
403 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
404 error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr,
405 le32toh(ext_page_req->len), TRUE, 5000);
407 mpt_prt(mpt, "mpt_user_read_extcfg_page timed out\n");
411 ext_page_req->ioc_status = htole16(req->IOCStatus);
412 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS)
413 bus_dmamap_sync(mpt_page->tag, mpt_page->map,
414 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
415 mpt_free_request(mpt, req);
420 mpt_user_write_cfg_page(struct mpt_softc *mpt,
421 struct mpt_cfg_page_req *page_req, struct mpt_page_memory *mpt_page)
423 CONFIG_PAGE_HEADER *hdr;
429 hdr = mpt_page->vaddr;
430 hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
431 if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
432 hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
433 mpt_prt(mpt, "page type 0x%x not changeable\n",
434 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
440 * We shouldn't mask off other bits here.
442 hdr->PageType &= ~MPI_CONFIG_PAGETYPE_MASK;
445 req = mpt_get_request(mpt, TRUE);
449 bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_PREREAD |
450 BUS_DMASYNC_PREWRITE);
453 * There isn't any point in restoring stripped out attributes
454 * if you then mask them going down to issue the request.
457 params.Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
458 params.PageVersion = hdr->PageVersion;
459 params.PageLength = hdr->PageLength;
460 params.PageNumber = hdr->PageNumber;
461 params.PageAddress = le32toh(page_req->page_address);
463 /* Restore stripped out attributes */
464 hdr->PageType |= hdr_attr;
465 params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK;
467 params.PageType = hdr->PageType;
469 error = mpt_issue_cfg_req(mpt, req, ¶ms, mpt_page->paddr,
470 le32toh(page_req->len), TRUE, 5000);
472 mpt_prt(mpt, "mpt_write_cfg_page timed out\n");
476 page_req->ioc_status = htole16(req->IOCStatus);
477 bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_POSTREAD |
478 BUS_DMASYNC_POSTWRITE);
479 mpt_free_request(mpt, req);
484 mpt_user_reply_handler(struct mpt_softc *mpt, request_t *req,
485 uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
487 MSG_RAID_ACTION_REPLY *reply;
488 struct mpt_user_raid_action_result *res;
493 if (reply_frame != NULL) {
494 reply = (MSG_RAID_ACTION_REPLY *)reply_frame;
495 req->IOCStatus = le16toh(reply->IOCStatus);
496 res = (struct mpt_user_raid_action_result *)
497 (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt));
498 res->action_status = reply->ActionStatus;
499 res->volume_status = reply->VolumeStatus;
500 bcopy(&reply->ActionData, res->action_data,
501 sizeof(res->action_data));
504 req->state &= ~REQ_STATE_QUEUED;
505 req->state |= REQ_STATE_DONE;
506 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
508 if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
510 } else if ((req->state & REQ_STATE_TIMEDOUT) != 0) {
512 * Whew- we can free this request (late completion)
514 mpt_free_request(mpt, req);
521 * We use the first part of the request buffer after the request frame
522 * to hold the action data and action status from the RAID reply. The
523 * rest of the request buffer is used to hold the buffer for the
527 mpt_user_raid_action(struct mpt_softc *mpt, struct mpt_raid_action *raid_act,
528 struct mpt_page_memory *mpt_page)
531 struct mpt_user_raid_action_result *res;
532 MSG_RAID_ACTION_REQUEST *rap;
536 req = mpt_get_request(mpt, TRUE);
540 memset(rap, 0, sizeof *rap);
541 rap->Action = raid_act->action;
542 rap->ActionDataWord = raid_act->action_data_word;
543 rap->Function = MPI_FUNCTION_RAID_ACTION;
544 rap->VolumeID = raid_act->volume_id;
545 rap->VolumeBus = raid_act->volume_bus;
546 rap->PhysDiskNum = raid_act->phys_disk_num;
547 se = (SGE_SIMPLE32 *)&rap->ActionDataSGE;
548 if (mpt_page->vaddr != NULL && raid_act->len != 0) {
549 bus_dmamap_sync(mpt_page->tag, mpt_page->map,
550 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
551 se->Address = htole32(mpt_page->paddr);
552 MPI_pSGE_SET_LENGTH(se, le32toh(raid_act->len));
553 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
554 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
555 MPI_SGE_FLAGS_END_OF_LIST |
556 (raid_act->write ? MPI_SGE_FLAGS_HOST_TO_IOC :
557 MPI_SGE_FLAGS_IOC_TO_HOST)));
559 se->FlagsLength = htole32(se->FlagsLength);
560 rap->MsgContext = htole32(req->index | user_handler_id);
562 mpt_check_doorbell(mpt);
563 mpt_send_cmd(mpt, req);
565 error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, TRUE,
569 * Leave request so it can be cleaned up later.
571 mpt_prt(mpt, "mpt_user_raid_action timed out\n");
575 raid_act->ioc_status = htole16(req->IOCStatus);
576 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
577 mpt_free_request(mpt, req);
581 res = (struct mpt_user_raid_action_result *)
582 (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt));
583 raid_act->volume_status = res->volume_status;
584 raid_act->action_status = res->action_status;
585 bcopy(res->action_data, raid_act->action_data,
586 sizeof(res->action_data));
587 if (mpt_page->vaddr != NULL)
588 bus_dmamap_sync(mpt_page->tag, mpt_page->map,
589 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
590 mpt_free_request(mpt, req);
595 mpt_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
597 struct mpt_softc *mpt;
598 struct mpt_cfg_page_req *page_req;
599 struct mpt_ext_cfg_page_req *ext_page_req;
600 struct mpt_raid_action *raid_act;
601 struct mpt_page_memory mpt_page;
603 struct mpt_cfg_page_req32 *page_req32;
604 struct mpt_cfg_page_req page_req_swab;
605 struct mpt_ext_cfg_page_req32 *ext_page_req32;
606 struct mpt_ext_cfg_page_req ext_page_req_swab;
607 struct mpt_raid_action32 *raid_act32;
608 struct mpt_raid_action raid_act_swab;
613 page_req = (void *)arg;
614 ext_page_req = (void *)arg;
615 raid_act = (void *)arg;
616 mpt_page.vaddr = NULL;
619 /* Convert 32-bit structs to native ones. */
620 page_req32 = (void *)arg;
621 ext_page_req32 = (void *)arg;
622 raid_act32 = (void *)arg;
624 case MPTIO_READ_CFG_HEADER32:
625 case MPTIO_READ_CFG_PAGE32:
626 case MPTIO_WRITE_CFG_PAGE32:
627 page_req = &page_req_swab;
628 page_req->header = page_req32->header;
629 page_req->page_address = page_req32->page_address;
630 page_req->buf = PTRIN(page_req32->buf);
631 page_req->len = page_req32->len;
632 page_req->ioc_status = page_req32->ioc_status;
634 case MPTIO_READ_EXT_CFG_HEADER32:
635 case MPTIO_READ_EXT_CFG_PAGE32:
636 ext_page_req = &ext_page_req_swab;
637 ext_page_req->header = ext_page_req32->header;
638 ext_page_req->page_address = ext_page_req32->page_address;
639 ext_page_req->buf = PTRIN(ext_page_req32->buf);
640 ext_page_req->len = ext_page_req32->len;
641 ext_page_req->ioc_status = ext_page_req32->ioc_status;
643 case MPTIO_RAID_ACTION32:
644 raid_act = &raid_act_swab;
645 raid_act->action = raid_act32->action;
646 raid_act->volume_bus = raid_act32->volume_bus;
647 raid_act->volume_id = raid_act32->volume_id;
648 raid_act->phys_disk_num = raid_act32->phys_disk_num;
649 raid_act->action_data_word = raid_act32->action_data_word;
650 raid_act->buf = PTRIN(raid_act32->buf);
651 raid_act->len = raid_act32->len;
652 raid_act->volume_status = raid_act32->volume_status;
653 bcopy(raid_act32->action_data, raid_act->action_data,
654 sizeof(raid_act->action_data));
655 raid_act->action_status = raid_act32->action_status;
656 raid_act->ioc_status = raid_act32->ioc_status;
657 raid_act->write = raid_act32->write;
664 case MPTIO_READ_CFG_HEADER32:
666 case MPTIO_READ_CFG_HEADER:
668 error = mpt_user_read_cfg_header(mpt, page_req);
672 case MPTIO_READ_CFG_PAGE32:
674 case MPTIO_READ_CFG_PAGE:
675 error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len);
678 error = copyin(page_req->buf, mpt_page.vaddr,
679 sizeof(CONFIG_PAGE_HEADER));
683 error = mpt_user_read_cfg_page(mpt, page_req, &mpt_page);
687 error = copyout(mpt_page.vaddr, page_req->buf, page_req->len);
690 case MPTIO_READ_EXT_CFG_HEADER32:
692 case MPTIO_READ_EXT_CFG_HEADER:
694 error = mpt_user_read_extcfg_header(mpt, ext_page_req);
698 case MPTIO_READ_EXT_CFG_PAGE32:
700 case MPTIO_READ_EXT_CFG_PAGE:
701 error = mpt_alloc_buffer(mpt, &mpt_page, ext_page_req->len);
704 error = copyin(ext_page_req->buf, mpt_page.vaddr,
705 sizeof(CONFIG_EXTENDED_PAGE_HEADER));
709 error = mpt_user_read_extcfg_page(mpt, ext_page_req, &mpt_page);
713 error = copyout(mpt_page.vaddr, ext_page_req->buf,
717 case MPTIO_WRITE_CFG_PAGE32:
719 case MPTIO_WRITE_CFG_PAGE:
720 error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len);
723 error = copyin(page_req->buf, mpt_page.vaddr, page_req->len);
727 error = mpt_user_write_cfg_page(mpt, page_req, &mpt_page);
731 case MPTIO_RAID_ACTION32:
733 case MPTIO_RAID_ACTION:
734 if (raid_act->buf != NULL) {
735 error = mpt_alloc_buffer(mpt, &mpt_page, raid_act->len);
738 error = copyin(raid_act->buf, mpt_page.vaddr,
744 error = mpt_user_raid_action(mpt, raid_act, &mpt_page);
748 if (raid_act->buf != NULL)
749 error = copyout(mpt_page.vaddr, raid_act->buf,
757 mpt_free_buffer(&mpt_page);
763 /* Convert native structs to 32-bit ones. */
765 case MPTIO_READ_CFG_HEADER32:
766 case MPTIO_READ_CFG_PAGE32:
767 case MPTIO_WRITE_CFG_PAGE32:
768 page_req32->header = page_req->header;
769 page_req32->page_address = page_req->page_address;
770 page_req32->buf = PTROUT(page_req->buf);
771 page_req32->len = page_req->len;
772 page_req32->ioc_status = page_req->ioc_status;
774 case MPTIO_READ_EXT_CFG_HEADER32:
775 case MPTIO_READ_EXT_CFG_PAGE32:
776 ext_page_req32->header = ext_page_req->header;
777 ext_page_req32->page_address = ext_page_req->page_address;
778 ext_page_req32->buf = PTROUT(ext_page_req->buf);
779 ext_page_req32->len = ext_page_req->len;
780 ext_page_req32->ioc_status = ext_page_req->ioc_status;
782 case MPTIO_RAID_ACTION32:
783 raid_act32->action = raid_act->action;
784 raid_act32->volume_bus = raid_act->volume_bus;
785 raid_act32->volume_id = raid_act->volume_id;
786 raid_act32->phys_disk_num = raid_act->phys_disk_num;
787 raid_act32->action_data_word = raid_act->action_data_word;
788 raid_act32->buf = PTROUT(raid_act->buf);
789 raid_act32->len = raid_act->len;
790 raid_act32->volume_status = raid_act->volume_status;
791 bcopy(raid_act->action_data, raid_act32->action_data,
792 sizeof(raid_act->action_data));
793 raid_act32->action_status = raid_act->action_status;
794 raid_act32->ioc_status = raid_act->ioc_status;
795 raid_act32->write = raid_act->write;