2 * Copyright (c) 2008 Yahoo!, Inc.
4 * Written by: John Baldwin <jhb@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the names of any co-contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * LSI MPS-Fusion Host Adapter FreeBSD userland interface
32 * $FreeBSD: src/sys/dev/mps/mps_user.c,v 1.9 2010/11/30 22:39:46 ken Exp $
35 #include "opt_compat.h"
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/module.h>
45 #include <sys/malloc.h>
47 #include <sys/sysctl.h>
48 #include <sys/ioccom.h>
49 #include <sys/endian.h>
51 #include <sys/sysent.h>
54 #include <sys/device.h>
56 #include <bus/cam/scsi/scsi_all.h>
58 #include <dev/disk/mps/mpi/mpi2_type.h>
59 #include <dev/disk/mps/mpi/mpi2.h>
60 #include <dev/disk/mps/mpi/mpi2_ioc.h>
61 #include <dev/disk/mps/mpi/mpi2_cnfg.h>
62 #include <dev/disk/mps/mpsvar.h>
63 #include <dev/disk/mps/mps_table.h>
64 #include <dev/disk/mps/mps_ioctl.h>
66 static d_open_t mps_open;
67 static d_close_t mps_close;
68 static d_ioctl_t mps_ioctl_devsw;
70 static struct dev_ops mps_ops = {
74 .d_ioctl = mps_ioctl_devsw,
77 typedef int (mps_user_f)(struct mps_command *, struct mps_usr_command *);
78 static mps_user_f mpi_pre_ioc_facts;
79 static mps_user_f mpi_pre_port_facts;
80 static mps_user_f mpi_pre_fw_download;
81 static mps_user_f mpi_pre_fw_upload;
82 static mps_user_f mpi_pre_sata_passthrough;
83 static mps_user_f mpi_pre_smp_passthrough;
84 static mps_user_f mpi_pre_config;
85 static mps_user_f mpi_pre_sas_io_unit_control;
87 static int mps_user_read_cfg_header(struct mps_softc *,
88 struct mps_cfg_page_req *);
89 static int mps_user_read_cfg_page(struct mps_softc *,
90 struct mps_cfg_page_req *, void *);
91 static int mps_user_read_extcfg_header(struct mps_softc *,
92 struct mps_ext_cfg_page_req *);
93 static int mps_user_read_extcfg_page(struct mps_softc *,
94 struct mps_ext_cfg_page_req *, void *);
95 static int mps_user_write_cfg_page(struct mps_softc *,
96 struct mps_cfg_page_req *, void *);
97 static int mps_user_setup_request(struct mps_command *,
98 struct mps_usr_command *);
99 static int mps_user_command(struct mps_softc *, struct mps_usr_command *);
101 static MALLOC_DEFINE(M_MPSUSER, "mps_user", "Buffers for mps(4) ioctls");
104 mps_attach_user(struct mps_softc *sc)
108 unit = device_get_unit(sc->mps_dev);
109 sc->mps_cdev = make_dev(&mps_ops, unit, UID_ROOT, GID_OPERATOR, 0640,
111 if (sc->mps_cdev == NULL) {
114 sc->mps_cdev->si_drv1 = sc;
119 mps_detach_user(struct mps_softc *sc)
122 /* XXX: do a purge of pending requests? */
123 destroy_dev(sc->mps_cdev);
124 dev_ops_remove_minor(&mps_ops, device_get_unit(sc->mps_dev));
129 mps_open(struct dev_open_args *ap)
136 mps_close(struct dev_close_args *ap)
143 mps_user_read_cfg_header(struct mps_softc *sc,
144 struct mps_cfg_page_req *page_req)
146 MPI2_CONFIG_PAGE_HEADER *hdr;
147 struct mps_config_params params;
150 hdr = ¶ms.hdr.Struct;
151 params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
152 params.page_address = le32toh(page_req->page_address);
153 hdr->PageVersion = 0;
155 hdr->PageNumber = page_req->header.PageNumber;
156 hdr->PageType = page_req->header.PageType;
157 params.buffer = NULL;
159 params.callback = NULL;
161 if ((error = mps_read_config_page(sc, ¶ms)) != 0) {
163 * Leave the request. Without resetting the chip, it's
164 * still owned by it and we'll just get into trouble
165 * freeing it now. Mark it as abandoned so that if it
166 * shows up later it can be freed.
168 mps_printf(sc, "read_cfg_header timed out\n");
172 page_req->ioc_status = htole16(params.status);
173 if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
174 MPI2_IOCSTATUS_SUCCESS) {
175 bcopy(hdr, &page_req->header, sizeof(page_req->header));
182 mps_user_read_cfg_page(struct mps_softc *sc, struct mps_cfg_page_req *page_req,
185 MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
186 struct mps_config_params params;
190 hdr = ¶ms.hdr.Struct;
191 hdr->PageVersion = reqhdr->PageVersion;
192 hdr->PageLength = reqhdr->PageLength;
193 hdr->PageNumber = reqhdr->PageNumber;
194 hdr->PageType = reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK;
195 params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
196 params.page_address = le32toh(page_req->page_address);
198 params.length = le32toh(page_req->len);
199 params.callback = NULL;
201 if ((error = mps_read_config_page(sc, ¶ms)) != 0) {
202 mps_printf(sc, "mps_user_read_cfg_page timed out\n");
206 page_req->ioc_status = htole16(params.status);
211 mps_user_read_extcfg_header(struct mps_softc *sc,
212 struct mps_ext_cfg_page_req *ext_page_req)
214 MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
215 struct mps_config_params params;
218 hdr = ¶ms.hdr.Ext;
219 params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
220 hdr->PageVersion = ext_page_req->header.PageVersion;
221 hdr->ExtPageLength = 0;
222 hdr->PageNumber = ext_page_req->header.PageNumber;
223 hdr->ExtPageType = ext_page_req->header.ExtPageType;
224 params.page_address = le32toh(ext_page_req->page_address);
225 if ((error = mps_read_config_page(sc, ¶ms)) != 0) {
227 * Leave the request. Without resetting the chip, it's
228 * still owned by it and we'll just get into trouble
229 * freeing it now. Mark it as abandoned so that if it
230 * shows up later it can be freed.
232 mps_printf(sc, "mps_user_read_extcfg_header timed out\n");
236 ext_page_req->ioc_status = htole16(params.status);
237 if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
238 MPI2_IOCSTATUS_SUCCESS) {
239 ext_page_req->header.PageVersion = hdr->PageVersion;
240 ext_page_req->header.PageNumber = hdr->PageNumber;
241 ext_page_req->header.PageType = hdr->PageType;
242 ext_page_req->header.ExtPageLength = hdr->ExtPageLength;
243 ext_page_req->header.ExtPageType = hdr->ExtPageType;
250 mps_user_read_extcfg_page(struct mps_softc *sc,
251 struct mps_ext_cfg_page_req *ext_page_req, void *buf)
253 MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr;
254 struct mps_config_params params;
258 hdr = ¶ms.hdr.Ext;
259 params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
260 params.page_address = le32toh(ext_page_req->page_address);
261 hdr->PageVersion = reqhdr->PageVersion;
262 hdr->PageNumber = reqhdr->PageNumber;
263 hdr->ExtPageType = reqhdr->ExtPageType;
264 hdr->ExtPageLength = reqhdr->ExtPageLength;
266 params.length = le32toh(ext_page_req->len);
267 params.callback = NULL;
269 if ((error = mps_read_config_page(sc, ¶ms)) != 0) {
270 mps_printf(sc, "mps_user_read_extcfg_page timed out\n");
274 ext_page_req->ioc_status = htole16(params.status);
279 mps_user_write_cfg_page(struct mps_softc *sc,
280 struct mps_cfg_page_req *page_req, void *buf)
282 MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
283 struct mps_config_params params;
288 hdr = ¶ms.hdr.Struct;
289 hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK;
290 if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE &&
291 hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) {
292 mps_printf(sc, "page type 0x%x not changeable\n",
293 reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK);
298 * There isn't any point in restoring stripped out attributes
299 * if you then mask them going down to issue the request.
302 hdr->PageVersion = reqhdr->PageVersion;
303 hdr->PageLength = reqhdr->PageLength;
304 hdr->PageNumber = reqhdr->PageNumber;
305 hdr->PageType = reqhdr->PageType;
306 params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
307 params.page_address = le32toh(page_req->page_address);
309 params.length = le32toh(page_req->len);
310 params.callback = NULL;
312 if ((error = mps_write_config_page(sc, ¶ms)) != 0) {
313 mps_printf(sc, "mps_write_cfg_page timed out\n");
317 page_req->ioc_status = htole16(params.status);
322 mpi_init_sge(struct mps_command *cm, void *req, void *sge)
326 space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4;
327 off = (uintptr_t)sge - (uintptr_t)req;
329 KASSERT(off < space, ("bad pointers %p %p, off %d, space %d",
330 req, sge, off, space));
333 cm->cm_sglsize = space - off;
337 * Prepare the mps_command for an IOC_FACTS request.
340 mpi_pre_ioc_facts(struct mps_command *cm, struct mps_usr_command *cmd)
342 MPI2_IOC_FACTS_REQUEST *req = (void *)cm->cm_req;
343 MPI2_IOC_FACTS_REPLY *rpl;
345 if (cmd->req_len != sizeof *req)
347 if (cmd->rpl_len != sizeof *rpl)
356 * Prepare the mps_command for a PORT_FACTS request.
359 mpi_pre_port_facts(struct mps_command *cm, struct mps_usr_command *cmd)
361 MPI2_PORT_FACTS_REQUEST *req = (void *)cm->cm_req;
362 MPI2_PORT_FACTS_REPLY *rpl;
364 if (cmd->req_len != sizeof *req)
366 if (cmd->rpl_len != sizeof *rpl)
375 * Prepare the mps_command for a FW_DOWNLOAD request.
378 mpi_pre_fw_download(struct mps_command *cm, struct mps_usr_command *cmd)
380 MPI2_FW_DOWNLOAD_REQUEST *req = (void *)cm->cm_req;
381 MPI2_FW_DOWNLOAD_REPLY *rpl;
382 MPI2_FW_DOWNLOAD_TCSGE tc;
386 * This code assumes there is room in the request's SGL for
387 * the TransactionContext plus at least a SGL chain element.
389 CTASSERT(sizeof req->SGL >= sizeof tc + MPS_SGC_SIZE);
391 if (cmd->req_len != sizeof *req)
393 if (cmd->rpl_len != sizeof *rpl)
399 error = copyin(cmd->buf, cm->cm_data, cmd->len);
403 mpi_init_sge(cm, req, &req->SGL);
404 bzero(&tc, sizeof tc);
407 * For now, the F/W image must be provided in a single request.
409 if ((req->MsgFlags & MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT) == 0)
411 if (req->TotalImageSize != cmd->len)
415 * The value of the first two elements is specified in the
416 * Fusion-MPT Message Passing Interface document.
419 tc.DetailsLength = 12;
421 tc.ImageSize = cmd->len;
423 cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
425 return (mps_push_sge(cm, &tc, sizeof tc, 0));
429 * Prepare the mps_command for a FW_UPLOAD request.
432 mpi_pre_fw_upload(struct mps_command *cm, struct mps_usr_command *cmd)
434 MPI2_FW_UPLOAD_REQUEST *req = (void *)cm->cm_req;
435 MPI2_FW_UPLOAD_REPLY *rpl;
436 MPI2_FW_UPLOAD_TCSGE tc;
439 * This code assumes there is room in the request's SGL for
440 * the TransactionContext plus at least a SGL chain element.
442 CTASSERT(sizeof req->SGL >= sizeof tc + MPS_SGC_SIZE);
444 if (cmd->req_len != sizeof *req)
446 if (cmd->rpl_len != sizeof *rpl)
449 mpi_init_sge(cm, req, &req->SGL);
451 /* Perhaps just asking what the size of the fw is? */
455 bzero(&tc, sizeof tc);
458 * The value of the first two elements is specified in the
459 * Fusion-MPT Message Passing Interface document.
462 tc.DetailsLength = 12;
464 * XXX Is there any reason to fetch a partial image? I.e. to
465 * set ImageOffset to something other than 0?
468 tc.ImageSize = cmd->len;
470 return (mps_push_sge(cm, &tc, sizeof tc, 0));
474 * Prepare the mps_command for a SATA_PASSTHROUGH request.
477 mpi_pre_sata_passthrough(struct mps_command *cm, struct mps_usr_command *cmd)
479 MPI2_SATA_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
480 MPI2_SATA_PASSTHROUGH_REPLY *rpl;
482 if (cmd->req_len != sizeof *req)
484 if (cmd->rpl_len != sizeof *rpl)
487 mpi_init_sge(cm, req, &req->SGL);
492 * Prepare the mps_command for a SMP_PASSTHROUGH request.
495 mpi_pre_smp_passthrough(struct mps_command *cm, struct mps_usr_command *cmd)
497 MPI2_SMP_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
498 MPI2_SMP_PASSTHROUGH_REPLY *rpl;
500 if (cmd->req_len != sizeof *req)
502 if (cmd->rpl_len != sizeof *rpl)
505 mpi_init_sge(cm, req, &req->SGL);
510 * Prepare the mps_command for a CONFIG request.
513 mpi_pre_config(struct mps_command *cm, struct mps_usr_command *cmd)
515 MPI2_CONFIG_REQUEST *req = (void *)cm->cm_req;
516 MPI2_CONFIG_REPLY *rpl;
518 if (cmd->req_len != sizeof *req)
520 if (cmd->rpl_len != sizeof *rpl)
523 mpi_init_sge(cm, req, &req->PageBufferSGE);
528 * Prepare the mps_command for a SAS_IO_UNIT_CONTROL request.
531 mpi_pre_sas_io_unit_control(struct mps_command *cm,
532 struct mps_usr_command *cmd)
541 * A set of functions to prepare an mps_command for the various
542 * supported requests.
544 struct mps_user_func {
547 } mps_user_func_list[] = {
548 { MPI2_FUNCTION_IOC_FACTS, mpi_pre_ioc_facts },
549 { MPI2_FUNCTION_PORT_FACTS, mpi_pre_port_facts },
550 { MPI2_FUNCTION_FW_DOWNLOAD, mpi_pre_fw_download },
551 { MPI2_FUNCTION_FW_UPLOAD, mpi_pre_fw_upload },
552 { MPI2_FUNCTION_SATA_PASSTHROUGH, mpi_pre_sata_passthrough },
553 { MPI2_FUNCTION_SMP_PASSTHROUGH, mpi_pre_smp_passthrough},
554 { MPI2_FUNCTION_CONFIG, mpi_pre_config},
555 { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL, mpi_pre_sas_io_unit_control },
556 { 0xFF, NULL } /* list end */
560 mps_user_setup_request(struct mps_command *cm, struct mps_usr_command *cmd)
562 MPI2_REQUEST_HEADER *hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
563 struct mps_user_func *f;
565 for (f = mps_user_func_list; f->f_pre != NULL; f++) {
566 if (hdr->Function == f->Function)
567 return (f->f_pre(cm, cmd));
573 mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
575 MPI2_REQUEST_HEADER *hdr;
576 MPI2_DEFAULT_REPLY *rpl;
578 struct mps_command *cm = NULL;
583 cm = mps_alloc_command(sc);
586 mps_printf(sc, "mps_user_command: no mps requests\n");
592 hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
594 mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d rpl %p %d\n",
595 cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len );
597 if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
599 goto RetFreeUnlocked;
601 err = copyin(cmd->req, hdr, cmd->req_len);
603 goto RetFreeUnlocked;
605 mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X "
606 "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );
608 err = mps_user_setup_request(cm, cmd);
610 mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
612 goto RetFreeUnlocked;
616 buf = kmalloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
618 cm->cm_length = cmd->len;
624 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_WAKEUP;
625 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
628 err = mps_map_command(sc, cm);
630 if (err != 0 && err != EINPROGRESS) {
631 mps_printf(sc, "%s: invalid request: error %d\n",
635 lksleep(cm, &sc->mps_lock, 0, "mpsuser", 0);
637 rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
638 sz = rpl->MsgLength * 4;
640 if (sz > cmd->rpl_len) {
642 "mps_user_command: reply buffer too small %d required %d\n",
649 copyout(rpl, cmd->rpl, sz);
651 copyout(buf, cmd->buf, cmd->len);
652 mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz );
657 mps_free_command(sc, cm);
661 kfree(buf, M_MPSUSER);
666 mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag)
668 struct mps_softc *sc;
669 struct mps_cfg_page_req *page_req;
670 struct mps_ext_cfg_page_req *ext_page_req;
676 page_req = (void *)arg;
677 ext_page_req = (void *)arg;
680 case MPSIO_READ_CFG_HEADER:
682 error = mps_user_read_cfg_header(sc, page_req);
685 case MPSIO_READ_CFG_PAGE:
686 mps_page = kmalloc(page_req->len, M_MPSUSER, M_WAITOK | M_ZERO);
687 error = copyin(page_req->buf, mps_page,
688 sizeof(MPI2_CONFIG_PAGE_HEADER));
692 error = mps_user_read_cfg_page(sc, page_req, mps_page);
696 error = copyout(mps_page, page_req->buf, page_req->len);
698 case MPSIO_READ_EXT_CFG_HEADER:
700 error = mps_user_read_extcfg_header(sc, ext_page_req);
703 case MPSIO_READ_EXT_CFG_PAGE:
704 mps_page = kmalloc(ext_page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
705 error = copyin(ext_page_req->buf, mps_page,
706 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
710 error = mps_user_read_extcfg_page(sc, ext_page_req, mps_page);
714 error = copyout(mps_page, ext_page_req->buf, ext_page_req->len);
716 case MPSIO_WRITE_CFG_PAGE:
717 mps_page = kmalloc(page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
718 error = copyin(page_req->buf, mps_page, page_req->len);
722 error = mps_user_write_cfg_page(sc, page_req, mps_page);
725 case MPSIO_MPS_COMMAND:
726 error = mps_user_command(sc, (struct mps_usr_command *)arg);
733 if (mps_page != NULL)
734 kfree(mps_page, M_MPSUSER);
739 #ifdef COMPAT_FREEBSD32
741 /* Macros from compat/freebsd32/freebsd32.h */
742 #define PTRIN(v) (void *)(uintptr_t)(v)
743 #define PTROUT(v) (uint32_t)(uintptr_t)(v)
745 #define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
746 #define PTRIN_CP(src,dst,fld) \
747 do { (dst).fld = PTRIN((src).fld); } while (0)
748 #define PTROUT_CP(src,dst,fld) \
749 do { (dst).fld = PTROUT((src).fld); } while (0)
751 struct mps_cfg_page_req32 {
752 MPI2_CONFIG_PAGE_HEADER header;
753 uint32_t page_address;
759 struct mps_ext_cfg_page_req32 {
760 MPI2_CONFIG_EXTENDED_PAGE_HEADER header;
761 uint32_t page_address;
767 struct mps_raid_action32 {
771 uint8_t phys_disk_num;
772 uint32_t action_data_word;
775 uint32_t volume_status;
776 uint32_t action_data[4];
777 uint16_t action_status;
782 struct mps_usr_command32 {
792 #define MPSIO_READ_CFG_HEADER32 _IOWR('M', 200, struct mps_cfg_page_req32)
793 #define MPSIO_READ_CFG_PAGE32 _IOWR('M', 201, struct mps_cfg_page_req32)
794 #define MPSIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mps_ext_cfg_page_req32)
795 #define MPSIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mps_ext_cfg_page_req32)
796 #define MPSIO_WRITE_CFG_PAGE32 _IOWR('M', 204, struct mps_cfg_page_req32)
797 #define MPSIO_RAID_ACTION32 _IOWR('M', 205, struct mps_raid_action32)
798 #define MPSIO_MPS_COMMAND32 _IOWR('M', 210, struct mps_usr_command32)
801 mps_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag,
804 struct mps_cfg_page_req32 *page32 = _arg;
805 struct mps_ext_cfg_page_req32 *ext32 = _arg;
806 struct mps_raid_action32 *raid32 = _arg;
807 struct mps_usr_command32 *user32 = _arg;
809 struct mps_cfg_page_req page;
810 struct mps_ext_cfg_page_req ext;
811 struct mps_raid_action raid;
812 struct mps_usr_command user;
818 case MPSIO_READ_CFG_HEADER32:
819 case MPSIO_READ_CFG_PAGE32:
820 case MPSIO_WRITE_CFG_PAGE32:
821 if (cmd32 == MPSIO_READ_CFG_HEADER32)
822 cmd = MPSIO_READ_CFG_HEADER;
823 else if (cmd32 == MPSIO_READ_CFG_PAGE32)
824 cmd = MPSIO_READ_CFG_PAGE;
826 cmd = MPSIO_WRITE_CFG_PAGE;
827 CP(*page32, arg.page, header);
828 CP(*page32, arg.page, page_address);
829 PTRIN_CP(*page32, arg.page, buf);
830 CP(*page32, arg.page, len);
831 CP(*page32, arg.page, ioc_status);
834 case MPSIO_READ_EXT_CFG_HEADER32:
835 case MPSIO_READ_EXT_CFG_PAGE32:
836 if (cmd32 == MPSIO_READ_EXT_CFG_HEADER32)
837 cmd = MPSIO_READ_EXT_CFG_HEADER;
839 cmd = MPSIO_READ_EXT_CFG_PAGE;
840 CP(*ext32, arg.ext, header);
841 CP(*ext32, arg.ext, page_address);
842 PTRIN_CP(*ext32, arg.ext, buf);
843 CP(*ext32, arg.ext, len);
844 CP(*ext32, arg.ext, ioc_status);
847 case MPSIO_RAID_ACTION32:
848 cmd = MPSIO_RAID_ACTION;
849 CP(*raid32, arg.raid, action);
850 CP(*raid32, arg.raid, volume_bus);
851 CP(*raid32, arg.raid, volume_id);
852 CP(*raid32, arg.raid, phys_disk_num);
853 CP(*raid32, arg.raid, action_data_word);
854 PTRIN_CP(*raid32, arg.raid, buf);
855 CP(*raid32, arg.raid, len);
856 CP(*raid32, arg.raid, volume_status);
857 bcopy(raid32->action_data, arg.raid.action_data,
858 sizeof arg.raid.action_data);
859 CP(*raid32, arg.raid, ioc_status);
860 CP(*raid32, arg.raid, write);
863 case MPSIO_MPS_COMMAND32:
864 cmd = MPSIO_MPS_COMMAND;
865 PTRIN_CP(*user32, arg.user, req);
866 CP(*user32, arg.user, req_len);
867 PTRIN_CP(*user32, arg.user, rpl);
868 CP(*user32, arg.user, rpl_len);
869 PTRIN_CP(*user32, arg.user, buf);
870 CP(*user32, arg.user, len);
871 CP(*user32, arg.user, flags);
877 error = mps_ioctl(dev, cmd, &arg, flag, td);
878 if (error == 0 && (cmd32 & IOC_OUT) != 0) {
880 case MPSIO_READ_CFG_HEADER32:
881 case MPSIO_READ_CFG_PAGE32:
882 case MPSIO_WRITE_CFG_PAGE32:
883 CP(arg.page, *page32, header);
884 CP(arg.page, *page32, page_address);
885 PTROUT_CP(arg.page, *page32, buf);
886 CP(arg.page, *page32, len);
887 CP(arg.page, *page32, ioc_status);
890 case MPSIO_READ_EXT_CFG_HEADER32:
891 case MPSIO_READ_EXT_CFG_PAGE32:
892 CP(arg.ext, *ext32, header);
893 CP(arg.ext, *ext32, page_address);
894 PTROUT_CP(arg.ext, *ext32, buf);
895 CP(arg.ext, *ext32, len);
896 CP(arg.ext, *ext32, ioc_status);
899 case MPSIO_RAID_ACTION32:
900 CP(arg.raid, *raid32, action);
901 CP(arg.raid, *raid32, volume_bus);
902 CP(arg.raid, *raid32, volume_id);
903 CP(arg.raid, *raid32, phys_disk_num);
904 CP(arg.raid, *raid32, action_data_word);
905 PTROUT_CP(arg.raid, *raid32, buf);
906 CP(arg.raid, *raid32, len);
907 CP(arg.raid, *raid32, volume_status);
908 bcopy(arg.raid.action_data, raid32->action_data,
909 sizeof arg.raid.action_data);
910 CP(arg.raid, *raid32, ioc_status);
911 CP(arg.raid, *raid32, write);
914 case MPSIO_MPS_COMMAND32:
915 PTROUT_CP(arg.user, *user32, req);
916 CP(arg.user, *user32, req_len);
917 PTROUT_CP(arg.user, *user32, rpl);
918 CP(arg.user, *user32, rpl_len);
919 PTROUT_CP(arg.user, *user32, buf);
920 CP(arg.user, *user32, len);
921 CP(arg.user, *user32, flags);
928 #endif /* COMPAT_FREEBSD32 */
931 mps_ioctl_devsw(struct dev_ioctl_args *ap)
933 cdev_t dev = ap->a_head.a_dev;
934 u_long com = ap->a_cmd;
935 caddr_t arg = ap->a_data;
936 int flag = ap->a_fflag;
938 #ifdef COMPAT_FREEBSD32
939 if (SV_CURPROC_FLAG(SV_ILP32))
940 return (mps_ioctl32(dev, com, arg, flag, td));
942 return (mps_ioctl(dev, com, arg, flag));